mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-21 03:13:42 +08:00
Merge pull request #868 from Unidata/gh849.wif
Pull #849 plus a note in the release notes.
This commit is contained in:
commit
db41b2a653
@ -447,7 +447,7 @@ ENDIF()
|
||||
###
|
||||
|
||||
# Option to use HDF4
|
||||
OPTION(ENABLE_HDF4 "Build netCDF-4 with HDF5 read capability(HDF4, HDF5 and Zlib required)." OFF)
|
||||
OPTION(ENABLE_HDF4 "Build netCDF-4 with HDF4 read capability(HDF4, HDF5 and Zlib required)." OFF)
|
||||
IF(ENABLE_HDF4)
|
||||
SET(USE_HDF4 ON)
|
||||
# Check for include files, libraries.
|
||||
@ -526,6 +526,11 @@ IF(ENABLE_NETCDF_4)
|
||||
SET(USE_NETCDF4 ON CACHE BOOL "")
|
||||
SET(ENABLE_NETCDF_4 ON CACHE BOOL "")
|
||||
SET(ENABLE_NETCDF4 ON CACHE BOOL "")
|
||||
ELSE()
|
||||
SET(USE_HDF4_FILE_TESTS OFF)
|
||||
SET(USE_HDF4 OFF)
|
||||
SET(ENABLE_HDF4_FILE_TESTS OFF)
|
||||
SET(ENABLE_HDF4 OFF)
|
||||
ENDIF()
|
||||
|
||||
# Option to allow for strict null file padding.
|
||||
@ -1609,6 +1614,10 @@ IF(USE_HDF5)
|
||||
add_subdirectory(libsrc4)
|
||||
ENDIF(USE_HDF5)
|
||||
|
||||
IF(USE_HDF4)
|
||||
add_subdirectory(libhdf4)
|
||||
ENDIF(USE_HDF4)
|
||||
|
||||
IF(ENABLE_DAP2)
|
||||
ADD_SUBDIRECTORY(oc2)
|
||||
ADD_SUBDIRECTORY(libdap2)
|
||||
|
@ -62,6 +62,11 @@ if USE_PNETCDF
|
||||
LIBSRCP = libsrcp
|
||||
endif
|
||||
|
||||
# Build HDF4 if desired.
|
||||
if USE_HDF4
|
||||
LIBHDF4 = libhdf4
|
||||
endif
|
||||
|
||||
# Define Test directories
|
||||
if BUILD_TESTSETS
|
||||
TESTDIRS = $(V2_TEST) nc_test $(NC_TEST4) $(NCDAP2TESTDIR) \
|
||||
@ -72,8 +77,8 @@ endif
|
||||
# and run. ncgen must come before ncdump, because their tests
|
||||
# depend on it.
|
||||
SUBDIRS = include $(H5_TEST_DIR) libdispatch libsrc $(LIBSRC4_DIR) \
|
||||
$(LIBSRCP) $(OCLIB) $(DAP2) ${DAP4} liblib $(NCGEN3) $(NCGEN) \
|
||||
$(NCDUMP) $(TESTDIRS) docs $(EXAMPLES)
|
||||
$(LIBSRCP) $(LIBHDF4) $(OCLIB) $(DAP2) ${DAP4} liblib $(NCGEN3) \
|
||||
$(NCGEN) $(NCDUMP) $(TESTDIRS) docs $(EXAMPLES)
|
||||
|
||||
# Remove these generated files, for a distclean.
|
||||
DISTCLEANFILES = VERSION comps.txt test_prog libnetcdf.settings \
|
||||
|
@ -8,6 +8,7 @@ This file contains a high-level description of this package's evolution. Release
|
||||
## 4.6.1 - TBD
|
||||
|
||||
* [Bug Fix] Improved support for CRT builds with Visual Studio, improves zlib detection in hdf5 library. See [Github #853](https://github.com/Unidata/netcdf-c/pull/853) for more information.
|
||||
* [Enhancement][Internal] Moved HDF4 into a distinct dispatch layer. See [Github #849](https://github.com/Unidata/netcdf-c/pull/849) for more information.
|
||||
|
||||
## 4.6.0 - January 24, 2018
|
||||
* [Enhancement] Full support for using HDF5 dynamic filters, both for reading and writing. See the file docs/filters.md.
|
||||
|
@ -207,6 +207,9 @@ AC_MSG_CHECKING([whether reading of HDF4 SD files is to be enabled])
|
||||
AC_ARG_ENABLE([hdf4], [AS_HELP_STRING([--enable-hdf4],
|
||||
[build netcdf-4 with HDF4 read capability (HDF4, HDF5 and zlib required)])])
|
||||
test "x$enable_hdf4" = xyes || enable_hdf4=no
|
||||
if test "x$enable_hdf4" = xyes -a "x$enable_netcdf_4" = xno; then
|
||||
AC_MSG_ERROR([NetCDF-4 is required for HDF4 features])
|
||||
fi
|
||||
AC_MSG_RESULT($enable_hdf4)
|
||||
|
||||
# Does the user want to turn on extra HDF4 file tests?
|
||||
@ -1447,6 +1450,7 @@ AC_CONFIG_FILES([Makefile
|
||||
oc2/Makefile
|
||||
libdap2/Makefile
|
||||
libdap4/Makefile
|
||||
libhdf4/Makefile
|
||||
libdispatch/Makefile
|
||||
liblib/Makefile
|
||||
ncdump/cdl/Makefile
|
||||
|
@ -4,6 +4,8 @@
|
||||
# This automake file generates the Makefile to build the include
|
||||
# directory.
|
||||
|
||||
# Ed Hartnett, Dennis Heimbigner, Ward Fisher
|
||||
|
||||
include_HEADERS = netcdf.h netcdf_meta.h
|
||||
|
||||
if BUILD_PARALLEL
|
||||
@ -14,12 +16,12 @@ if BUILD_DISKLESS
|
||||
include_HEADERS += netcdf_mem.h
|
||||
endif
|
||||
|
||||
noinst_HEADERS = nc_logging.h nc_tests.h fbits.h nc.h \
|
||||
nclist.h ncuri.h ncutf8.h ncdispatch.h ncdimscale.h \
|
||||
netcdf_f.h err_macros.h ncbytes.h nchashmap.h ceconstraints.h rnd.h \
|
||||
nclog.h ncconfigure.h nc4internal.h nctime.h nc3internal.h \
|
||||
onstack.h nc_hashmap.h ncrc.h ncauth.h ncoffsets.h nctestserver.h \
|
||||
nc4dispatch.h nc3dispatch.h ncexternl.h ncwinpath.h ncfilter.h
|
||||
noinst_HEADERS = nc_logging.h nc_tests.h fbits.h nc.h nclist.h \
|
||||
ncuri.h ncutf8.h ncdispatch.h ncdimscale.h netcdf_f.h err_macros.h \
|
||||
ncbytes.h nchashmap.h ceconstraints.h rnd.h nclog.h ncconfigure.h \
|
||||
nc4internal.h nctime.h nc3internal.h onstack.h nc_hashmap.h ncrc.h \
|
||||
ncauth.h ncoffsets.h nctestserver.h nc4dispatch.h nc3dispatch.h \
|
||||
ncexternl.h ncwinpath.h ncfilter.h hdf4dispatch.h
|
||||
|
||||
if USE_DAP
|
||||
noinst_HEADERS += ncdap.h
|
||||
|
276
include/hdf4dispatch.h
Normal file
276
include/hdf4dispatch.h
Normal file
@ -0,0 +1,276 @@
|
||||
/* Copyright 2018, UCAR/Unidata. See netcdf/COPYRIGHT file for copying
|
||||
* and redistribution conditions. */
|
||||
/**
|
||||
* @file
|
||||
* This header file contains the prototypes for the HDF4 versions
|
||||
* of the netCDF functions.
|
||||
*
|
||||
* Ed Hartnett
|
||||
*/
|
||||
#ifndef _HDF4DISPATCH_H
|
||||
#define _HDF4DISPATCH_H
|
||||
|
||||
#include "config.h"
|
||||
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||
#include <errno.h> /* netcdf functions sometimes return system errors */
|
||||
#include "ncdispatch.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int
|
||||
HDF4_create(const char *path, int cmode,
|
||||
size_t initialsz, int basepe, size_t *chunksizehintp,
|
||||
int useparallel, void* parameters,
|
||||
NC_Dispatch*, NC*);
|
||||
|
||||
extern int
|
||||
HDF4_open(const char *path, int mode,
|
||||
int basepe, size_t *chunksizehintp,
|
||||
int use_parallel, void* parameters,
|
||||
NC_Dispatch*, NC*);
|
||||
|
||||
extern int
|
||||
HDF4_redef(int ncid);
|
||||
|
||||
extern int
|
||||
HDF4__enddef(int ncid, size_t h_minfree, size_t v_align,
|
||||
size_t v_minfree, size_t r_align);
|
||||
|
||||
extern int
|
||||
HDF4_sync(int ncid);
|
||||
|
||||
extern int
|
||||
HDF4_abort(int ncid);
|
||||
|
||||
extern int
|
||||
HDF4_close(int ncid);
|
||||
|
||||
extern int
|
||||
HDF4_set_fill(int ncid, int fillmode, int *old_modep);
|
||||
|
||||
extern int
|
||||
HDF4_set_base_pe(int ncid, int pe);
|
||||
|
||||
extern int
|
||||
HDF4_inq_base_pe(int ncid, int *pe);
|
||||
|
||||
extern int
|
||||
HDF4_inq_format(int ncid, int *formatp);
|
||||
|
||||
extern int
|
||||
HDF4_inq_format_extended(int ncid, int *formatp, int *modep);
|
||||
|
||||
extern int
|
||||
HDF4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp);
|
||||
|
||||
extern int
|
||||
HDF4_inq_type(int, nc_type, char *, size_t *);
|
||||
|
||||
/* Begin _dim */
|
||||
|
||||
extern int
|
||||
HDF4_def_dim(int ncid, const char *name, size_t len, int *idp);
|
||||
|
||||
extern int
|
||||
HDF4_inq_dimid(int ncid, const char *name, int *idp);
|
||||
|
||||
extern int
|
||||
HDF4_inq_dim(int ncid, int dimid, char *name, size_t *lenp);
|
||||
|
||||
extern int
|
||||
HDF4_inq_unlimdim(int ncid, int *unlimdimidp);
|
||||
|
||||
extern int
|
||||
HDF4_rename_dim(int ncid, int dimid, const char *name);
|
||||
|
||||
/* End _dim */
|
||||
/* Begin _att */
|
||||
|
||||
extern int
|
||||
HDF4_inq_att(int ncid, int varid, const char *name,
|
||||
nc_type *xtypep, size_t *lenp);
|
||||
|
||||
extern int
|
||||
HDF4_inq_attid(int ncid, int varid, const char *name, int *idp);
|
||||
|
||||
extern int
|
||||
HDF4_inq_attname(int ncid, int varid, int attnum, char *name);
|
||||
|
||||
extern int
|
||||
HDF4_rename_att(int ncid, int varid, const char *name, const char *newname);
|
||||
|
||||
extern int
|
||||
HDF4_del_att(int ncid, int varid, const char*);
|
||||
|
||||
/* End _att */
|
||||
/* Begin {put,get}_att */
|
||||
|
||||
extern int
|
||||
HDF4_get_att(int ncid, int varid, const char *name, void *value, nc_type);
|
||||
|
||||
extern int
|
||||
HDF4_put_att(int ncid, int varid, const char *name, nc_type datatype,
|
||||
size_t len, const void *value, nc_type);
|
||||
|
||||
/* End {put,get}_att */
|
||||
/* Begin _var */
|
||||
|
||||
extern int
|
||||
HDF4_def_var(int ncid, const char *name,
|
||||
nc_type xtype, int ndims, const int *dimidsp, int *varidp);
|
||||
|
||||
extern int
|
||||
HDF4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
|
||||
int *ndimsp, int *dimidsp, int *nattsp,
|
||||
int *shufflep, int *deflatep, int *deflate_levelp,
|
||||
int *fletcher32p, int *contiguousp, size_t *chunksizesp,
|
||||
int *no_fill, void *fill_valuep, int *endiannessp,
|
||||
unsigned int* idp, size_t* nparamsp, unsigned int* params
|
||||
);
|
||||
|
||||
extern int
|
||||
HDF4_inq_varid(int ncid, const char *name, int *varidp);
|
||||
|
||||
extern int
|
||||
HDF4_rename_var(int ncid, int varid, const char *name);
|
||||
|
||||
extern int
|
||||
HDF4_put_vara(int ncid, int varid,
|
||||
const size_t *start, const size_t *count,
|
||||
const void *value, nc_type);
|
||||
|
||||
extern int
|
||||
HDF4_get_vara(int ncid, int varid,
|
||||
const size_t *start, const size_t *count,
|
||||
void *value, nc_type);
|
||||
|
||||
/* End _var */
|
||||
|
||||
/* netCDF4 API only */
|
||||
extern int
|
||||
HDF4_var_par_access(int, int, int);
|
||||
|
||||
extern int
|
||||
HDF4_inq_ncid(int, const char *, int *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_grps(int, int *, int *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_grpname(int, char *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_grpname_full(int, size_t *, char *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_grp_parent(int, int *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_grp_full_ncid(int, const char *, int *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_varids(int, int * nvars, int *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_dimids(int, int * ndims, int *, int);
|
||||
|
||||
extern int
|
||||
HDF4_inq_typeids(int, int * ntypes, int *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_type_equal(int, nc_type, int, nc_type, int *);
|
||||
|
||||
extern int
|
||||
HDF4_def_grp(int, const char *, int *);
|
||||
|
||||
extern int
|
||||
HDF4_rename_grp(int, const char *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_user_type(int, nc_type, char *, size_t *, nc_type *,
|
||||
size_t *, int *);
|
||||
|
||||
extern int
|
||||
HDF4_def_compound(int, size_t, const char *, nc_type *);
|
||||
|
||||
extern int
|
||||
HDF4_insert_compound(int, nc_type, const char *, size_t, nc_type);
|
||||
|
||||
extern int
|
||||
HDF4_insert_array_compound(int, nc_type, const char *, size_t,
|
||||
nc_type, int, const int *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_typeid(int, const char *, nc_type *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_compound_field(int, nc_type, int, char *, size_t *,
|
||||
nc_type *, int *, int *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_compound_fieldindex(int, nc_type, const char *, int *);
|
||||
|
||||
extern int
|
||||
HDF4_def_vlen(int, const char *, nc_type base_typeid, nc_type *);
|
||||
|
||||
extern int
|
||||
HDF4_put_vlen_element(int, int, void *, size_t, const void *);
|
||||
|
||||
extern int
|
||||
HDF4_get_vlen_element(int, int, const void *, size_t *, void *);
|
||||
|
||||
extern int
|
||||
HDF4_def_enum(int, nc_type, const char *, nc_type *);
|
||||
|
||||
extern int
|
||||
HDF4_insert_enum(int, nc_type, const char *, const void *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_enum_member(int, nc_type, int, char *, void *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_enum_ident(int, nc_type, long long, char *);
|
||||
|
||||
extern int
|
||||
HDF4_def_opaque(int, size_t, const char *, nc_type *);
|
||||
|
||||
extern int
|
||||
HDF4_def_var_deflate(int, int, int, int, int);
|
||||
|
||||
extern int
|
||||
HDF4_def_var_fletcher32(int, int, int);
|
||||
|
||||
extern int
|
||||
HDF4_def_var_chunking(int, int, int, const size_t *);
|
||||
|
||||
extern int
|
||||
HDF4_def_var_fill(int, int, int, const void *);
|
||||
|
||||
extern int
|
||||
HDF4_def_var_endian(int, int, int);
|
||||
|
||||
extern int
|
||||
HDF4_def_var_filter(int, int, unsigned int, size_t, const unsigned int*);
|
||||
|
||||
extern int
|
||||
HDF4_set_var_chunk_cache(int, int, size_t, size_t, float);
|
||||
|
||||
extern int
|
||||
HDF4_get_var_chunk_cache(int, int, size_t *, size_t *, float *);
|
||||
|
||||
extern int
|
||||
HDF4_inq_unlimdims(int, int *, int *);
|
||||
|
||||
extern int
|
||||
HDF4_show_metadata(int);
|
||||
|
||||
extern int
|
||||
HDF4_initialize(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_HDF4DISPATCH_H */
|
@ -399,6 +399,7 @@ int nc4_type_free(NC_TYPE_INFO_T *type);
|
||||
int nc4_nc4f_list_add(NC *nc, const char *path, int mode);
|
||||
int nc4_var_add(NC_VAR_INFO_T **var);
|
||||
int nc4_var_del(NC_VAR_INFO_T *var);
|
||||
int nc4_vararray_add(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
|
||||
int nc4_dim_list_add(NC_DIM_INFO_T **list, NC_DIM_INFO_T **dim);
|
||||
int nc4_dim_list_del(NC_DIM_INFO_T **list, NC_DIM_INFO_T *dim);
|
||||
int nc4_att_list_add(NC_ATT_INFO_T **list, NC_ATT_INFO_T **att);
|
||||
|
@ -145,6 +145,12 @@ extern int NC4_initialize(void);
|
||||
extern int NC4_finalize(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_HDF4
|
||||
extern NC_Dispatch* HDF4_dispatch_table;
|
||||
extern int HDF4_initialize(void);
|
||||
extern int HDF4_finalize(void);
|
||||
#endif
|
||||
|
||||
/* Vectors of ones and zeros */
|
||||
extern size_t nc_sizevector0[NC_MAX_VAR_DIMS];
|
||||
extern size_t nc_sizevector1[NC_MAX_VAR_DIMS];
|
||||
|
@ -2062,40 +2062,45 @@ NC_open(const char *path0, int cmode, int basepe, size_t *chunksizehintp,
|
||||
return NC_EINVAL;
|
||||
}
|
||||
|
||||
/* override any other table choice */
|
||||
if(dispatcher != NULL) goto havetable;
|
||||
|
||||
/* Figure out what dispatcher to use */
|
||||
if (!dispatcher) {
|
||||
switch (model) {
|
||||
#if defined(ENABLE_DAP)
|
||||
if(model == (NC_FORMATX_DAP2))
|
||||
dispatcher = NCD2_dispatch_table;
|
||||
else
|
||||
case NC_FORMATX_DAP2:
|
||||
dispatcher = NCD2_dispatch_table;
|
||||
break;
|
||||
#endif
|
||||
#if defined(ENABLE_DAP4)
|
||||
if(model == (NC_FORMATX_DAP4))
|
||||
dispatcher = NCD4_dispatch_table;
|
||||
else
|
||||
case NC_FORMATX_DAP4:
|
||||
dispatcher = NCD4_dispatch_table;
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_PNETCDF)
|
||||
if(model == (NC_FORMATX_PNETCDF))
|
||||
dispatcher = NCP_dispatch_table;
|
||||
else
|
||||
case NC_FORMATX_PNETCDF:
|
||||
dispatcher = NCP_dispatch_table;
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_NETCDF4)
|
||||
if(model == (NC_FORMATX_NC4) || model == (NC_FORMATX_NC_HDF4))
|
||||
dispatcher = NC4_dispatch_table;
|
||||
else
|
||||
case NC_FORMATX_NC4:
|
||||
dispatcher = NC4_dispatch_table;
|
||||
break;
|
||||
#endif
|
||||
if(model == (NC_FORMATX_NC3))
|
||||
dispatcher = NC3_dispatch_table;
|
||||
else {
|
||||
nullfree(path);
|
||||
return NC_ENOTNC;
|
||||
#if defined(USE_HDF4)
|
||||
case NC_FORMATX_NC_HDF4:
|
||||
dispatcher = HDF4_dispatch_table;
|
||||
break;
|
||||
#endif
|
||||
case NC_FORMATX_NC3:
|
||||
dispatcher = NC3_dispatch_table;
|
||||
break;
|
||||
default:
|
||||
nullfree(path);
|
||||
return NC_ENOTNC;
|
||||
}
|
||||
}
|
||||
|
||||
havetable:
|
||||
|
||||
if(dispatcher == NULL) {
|
||||
/* If we can't figure out what dispatch table to use, give up. */
|
||||
if (!dispatcher) {
|
||||
nullfree(path);
|
||||
return NC_ENOTNC;
|
||||
}
|
||||
@ -2175,7 +2180,6 @@ openmagic(struct MagicFile* file)
|
||||
}
|
||||
#ifdef USE_PARALLEL
|
||||
if (file->use_parallel) {
|
||||
MPI_Status mstatus;
|
||||
int retval;
|
||||
MPI_Offset size;
|
||||
MPI_Comm comm = MPI_COMM_WORLD;
|
||||
@ -2293,7 +2297,6 @@ closemagic(struct MagicFile* file)
|
||||
if(file->inmemory) goto done; /* noop*/
|
||||
#ifdef USE_PARALLEL
|
||||
if (file->use_parallel) {
|
||||
MPI_Status mstatus;
|
||||
int retval;
|
||||
if((retval = MPI_File_close(&file->fh)) != MPI_SUCCESS)
|
||||
{status = NC_EPARINIT; goto done;}
|
||||
|
17
libhdf4/CMakeLists.txt
Normal file
17
libhdf4/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
## This is a CMake file, part of Unidata's netCDF package.
|
||||
# Copyright 2018, see the COPYRIGHT file for more information.
|
||||
#
|
||||
# This builds the HDF4 dispatch layer.
|
||||
#
|
||||
# Ed Hartnett
|
||||
|
||||
# The source files for the HDF4 dispatch layer.
|
||||
SET(libhdf4_SOURCES hdf4attr.c hdf4dim.c hdf4dispatch.c hdf4file.c hdf4func.c
|
||||
hdf4grp.c hdf4type.c hdf4var.c)
|
||||
|
||||
# Build the HDF4 dispatch layer as a library that will be included in
|
||||
# the netCDF library.
|
||||
add_library(netcdfhdf4 OBJECT ${libhdf4_SOURCES})
|
||||
|
||||
# Remember to package this file for CMake builds.
|
||||
ADD_EXTRA_DIST(${libhdf4_SOURCES} CMakeLists.txt)
|
25
libhdf4/Makefile.am
Normal file
25
libhdf4/Makefile.am
Normal file
@ -0,0 +1,25 @@
|
||||
# This is part of Unidata's netCDF package. Copyright 2018, see the
|
||||
# COPYRIGHT file for more information.
|
||||
|
||||
# Build the HDF4 dispatch layer.
|
||||
|
||||
# Ed Hartnett
|
||||
|
||||
# Get AM_CPPFLAGS.
|
||||
include $(top_srcdir)/lib_flags.am
|
||||
libnetcdf4_la_CPPFLAGS = ${AM_CPPFLAGS}
|
||||
|
||||
# This is our output. The HDF4 convenience library.
|
||||
noinst_LTLIBRARIES = libnchdf4.la
|
||||
|
||||
# The source files.
|
||||
libnchdf4_la_SOURCES = hdf4dispatch.c hdf4attr.c hdf4dim.c hdf4file.c \
|
||||
hdf4grp.c hdf4type.c hdf4var.c hdf4func.c
|
||||
|
||||
# Package this for cmake build.
|
||||
EXTRA_DIST = CMakeLists.txt
|
||||
|
||||
|
||||
|
||||
|
||||
|
69
libhdf4/hdf4attr.c
Normal file
69
libhdf4/hdf4attr.c
Normal file
@ -0,0 +1,69 @@
|
||||
/* Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for copying
|
||||
* and redistribution conditions.*/
|
||||
/**
|
||||
* @file
|
||||
* @internal This file handles the HDF4 attribute functions.
|
||||
*
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
|
||||
#include "nc4internal.h"
|
||||
#include "nc.h"
|
||||
#include "hdf4dispatch.h"
|
||||
#include "ncdispatch.h"
|
||||
|
||||
int nc4typelen(nc_type type);
|
||||
|
||||
/**
|
||||
* @internal Not allowed for HDF4.
|
||||
*
|
||||
* @param ncid Ignored.
|
||||
* @param varid Ignored.
|
||||
* @param name Ignored.
|
||||
* @param newname Ignored.
|
||||
*
|
||||
* @return ::NC_EPERM Not allowed for HDF4.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_rename_att(int ncid, int varid, const char *name, const char *newname)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Not allowed for HDF4.
|
||||
*
|
||||
* @param ncid Ignored.
|
||||
* @param varid Ignored.
|
||||
* @param name Ignored.
|
||||
*
|
||||
* @return ::NC_EPERM Not allowed with HDF4.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_del_att(int ncid, int varid, const char *name)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Not allowed for HDF4.
|
||||
*
|
||||
* @param ncid Ignored.
|
||||
* @param varid Ignored.
|
||||
* @param name Ignored.
|
||||
* @param file_type Ignored.
|
||||
* @param len Ignored.
|
||||
* @param data Ignored.
|
||||
* @param memtype Ignored.
|
||||
*
|
||||
* @return ::NC_EPERM Not allowed with HDF4.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
size_t len, const void *data, nc_type mem_type)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
44
libhdf4/hdf4dim.c
Normal file
44
libhdf4/hdf4dim.c
Normal file
@ -0,0 +1,44 @@
|
||||
/* Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for copying
|
||||
* and redistribution conditions.*/
|
||||
/**
|
||||
* @file
|
||||
* @internal This file handles the HDF4 dimension functions.
|
||||
*
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
|
||||
#include "nc4internal.h"
|
||||
#include "nc4dispatch.h"
|
||||
|
||||
/**
|
||||
* @internal Dims cannot be defined for HDF4 files.
|
||||
*
|
||||
* @param ncid Ignored.
|
||||
* @param name Ignored.
|
||||
* @param len Ignored.
|
||||
* @param idp Ignored.
|
||||
*
|
||||
* @return ::NC_EPERM Can't define dims.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_def_dim(int ncid, const char *name, size_t len, int *idp)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Not allowed for HDF4.
|
||||
*
|
||||
* @param ncid Ignored.
|
||||
* @param dimid Ignored.
|
||||
* @param name Ignored.
|
||||
*
|
||||
* @return ::NC_NEPERM Can't write to HDF4 file.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_rename_dim(int ncid, int dimid, const char *name)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
134
libhdf4/hdf4dispatch.c
Normal file
134
libhdf4/hdf4dispatch.c
Normal file
@ -0,0 +1,134 @@
|
||||
/* Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for copying
|
||||
* and redistribution conditions.*/
|
||||
/**
|
||||
* @file
|
||||
* @internal Dispatch code for HDF4. HDF4 access is read-only.
|
||||
*
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
#include "hdf4dispatch.h"
|
||||
#include "nc4dispatch.h"
|
||||
#include "nc.h"
|
||||
|
||||
/* This is the dispatch object that holds pointers to all the
|
||||
* functions that make up the HDF4 dispatch interface. */
|
||||
static NC_Dispatch HDF4_dispatcher = {
|
||||
|
||||
NC_FORMATX_NC_HDF4,
|
||||
|
||||
HDF4_create,
|
||||
HDF4_open,
|
||||
|
||||
HDF4_redef,
|
||||
HDF4__enddef,
|
||||
HDF4_sync,
|
||||
HDF4_abort,
|
||||
HDF4_close,
|
||||
HDF4_set_fill,
|
||||
HDF4_inq_base_pe,
|
||||
HDF4_set_base_pe,
|
||||
HDF4_inq_format,
|
||||
HDF4_inq_format_extended,
|
||||
|
||||
NC4_inq,
|
||||
NC4_inq_type,
|
||||
|
||||
HDF4_def_dim,
|
||||
NC4_inq_dimid,
|
||||
NC4_inq_dim,
|
||||
NC4_inq_unlimdim,
|
||||
HDF4_rename_dim,
|
||||
|
||||
NC4_inq_att,
|
||||
NC4_inq_attid,
|
||||
NC4_inq_attname,
|
||||
HDF4_rename_att,
|
||||
HDF4_del_att,
|
||||
NC4_get_att,
|
||||
HDF4_put_att,
|
||||
|
||||
HDF4_def_var,
|
||||
NC4_inq_varid,
|
||||
HDF4_rename_var,
|
||||
HDF4_get_vara,
|
||||
HDF4_put_vara,
|
||||
NCDEFAULT_get_vars,
|
||||
NCDEFAULT_put_vars,
|
||||
NCDEFAULT_get_varm,
|
||||
NCDEFAULT_put_varm,
|
||||
|
||||
NC4_inq_var_all,
|
||||
|
||||
HDF4_var_par_access,
|
||||
HDF4_def_var_fill,
|
||||
|
||||
NC4_show_metadata,
|
||||
NC4_inq_unlimdims,
|
||||
|
||||
NC4_inq_ncid,
|
||||
NC4_inq_grps,
|
||||
NC4_inq_grpname,
|
||||
NC4_inq_grpname_full,
|
||||
NC4_inq_grp_parent,
|
||||
NC4_inq_grp_full_ncid,
|
||||
NC4_inq_varids,
|
||||
NC4_inq_dimids,
|
||||
NC4_inq_typeids,
|
||||
NC4_inq_type_equal,
|
||||
HDF4_def_grp,
|
||||
HDF4_rename_grp,
|
||||
NC4_inq_user_type,
|
||||
NC4_inq_typeid,
|
||||
|
||||
HDF4_def_compound,
|
||||
HDF4_insert_compound,
|
||||
HDF4_insert_array_compound,
|
||||
HDF4_inq_compound_field,
|
||||
HDF4_inq_compound_fieldindex,
|
||||
HDF4_def_vlen,
|
||||
HDF4_put_vlen_element,
|
||||
HDF4_get_vlen_element,
|
||||
HDF4_def_enum,
|
||||
HDF4_insert_enum,
|
||||
HDF4_inq_enum_member,
|
||||
HDF4_inq_enum_ident,
|
||||
HDF4_def_opaque,
|
||||
HDF4_def_var_deflate,
|
||||
HDF4_def_var_fletcher32,
|
||||
HDF4_def_var_chunking,
|
||||
HDF4_def_var_endian,
|
||||
HDF4_def_var_filter,
|
||||
HDF4_set_var_chunk_cache,
|
||||
HDF4_get_var_chunk_cache,
|
||||
|
||||
};
|
||||
|
||||
NC_Dispatch* HDF4_dispatch_table = NULL;
|
||||
|
||||
/**
|
||||
* @internal Initialize HDF4 dispatch layer.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_initialize(void)
|
||||
{
|
||||
HDF4_dispatch_table = &HDF4_dispatcher;
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Finalize HDF4 dispatch layer.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_finalize(void)
|
||||
{
|
||||
return NC_NOERR;
|
||||
}
|
713
libhdf4/hdf4file.c
Normal file
713
libhdf4/hdf4file.c
Normal file
@ -0,0 +1,713 @@
|
||||
/* Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for copying
|
||||
* and redistribution conditions.*/
|
||||
/**
|
||||
* @file @internal The HDF4 file functions.
|
||||
*
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <errno.h> /* netcdf functions sometimes return system errors */
|
||||
#include "nc.h"
|
||||
#include "nc4internal.h"
|
||||
#include "hdf4dispatch.h"
|
||||
#include <mfhdf.h>
|
||||
|
||||
extern int nc4_vararray_add(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
|
||||
|
||||
/** @internal These flags may not be set for open mode. */
|
||||
static const int ILLEGAL_OPEN_FLAGS = (NC_MMAP|NC_64BIT_OFFSET|NC_MPIIO|NC_MPIPOSIX|NC_DISKLESS);
|
||||
|
||||
/**
|
||||
* @internal This function will free all allocated metadata memory,
|
||||
* and close the HDF4 file.
|
||||
*
|
||||
* @param h5 Pointer to HDF5 file info struct.
|
||||
* @param abort True if this is an abort.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
static int
|
||||
close_hdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort)
|
||||
{
|
||||
int retval;
|
||||
|
||||
assert(h5 && h5->controller->path && h5->root_grp && h5->no_write);
|
||||
LOG((3, "%s: h5->controller->path %s abort %d", __func__,
|
||||
h5->controller->path, abort));
|
||||
|
||||
/* According to the docs, always end define mode on close. */
|
||||
if (h5->flags & NC_INDEF)
|
||||
h5->flags ^= NC_INDEF;
|
||||
|
||||
/* Delete all the list contents for vars, dims, and atts, in each
|
||||
* group. */
|
||||
if ((retval = nc4_rec_grp_del(&h5->root_grp, h5->root_grp)))
|
||||
return retval;
|
||||
|
||||
/* Close hdf file. */
|
||||
if (SDend(h5->sdid))
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* Free the nc4_info struct; above code should have reclaimed
|
||||
everything else */
|
||||
free(h5);
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
#define NUM_TYPES 12 /**< Number of netCDF atomic types. */
|
||||
|
||||
/** @internal NetCDF atomic type names. */
|
||||
static const char nc_type_name_g[NUM_TYPES][NC_MAX_NAME + 1] = {"char", "byte", "short",
|
||||
"int", "float", "double", "ubyte",
|
||||
"ushort", "uint", "int64",
|
||||
"uint64", "string"};
|
||||
|
||||
/** @internal NetCDF atomic type sizes. */
|
||||
static const int nc_type_size_g[NUM_TYPES] = {sizeof(char), sizeof(char), sizeof(short),
|
||||
sizeof(int), sizeof(float), sizeof(double), sizeof(unsigned char),
|
||||
sizeof(unsigned short), sizeof(unsigned int), sizeof(long long),
|
||||
sizeof(unsigned long long), sizeof(char *)};
|
||||
|
||||
/**
|
||||
* @internal Create a HDF4 file. Since the HDF4 integration provides
|
||||
* read-only access to HDF4 files, this returns error NC_ENOTNC4.
|
||||
*
|
||||
* @param path Ignored.
|
||||
* @param cmode Ignored.
|
||||
* @param initialsz Ignored.
|
||||
* @param basepe Ignored.
|
||||
* @param chunksizehintp Ignored.
|
||||
* @param use_parallel Ignored.
|
||||
* @param parameters Ignored.
|
||||
* @param dispatch Ignored.
|
||||
* @param nc_file Ignored.
|
||||
*
|
||||
* @return ::NC_ENOTNC4 Cannot create HDF4 files.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_create(const char* path, int cmode, size_t initialsz, int basepe,
|
||||
size_t *chunksizehintp, int use_parallel, void *parameters,
|
||||
NC_Dispatch *dispatch, NC* nc_file)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Given an HDF4 type, set a pointer to netcdf type.
|
||||
*
|
||||
* See http://www.hdfgroup.org/training/HDFtraining/UsersGuide/Fundmtls.fm3.html
|
||||
* for more information re: HDF4 types.
|
||||
*
|
||||
* @param h5 Pointer to HDF5 file info struct.
|
||||
* @param hdf4_typeid Type ID for hdf4 datatype.
|
||||
* @param xtype Pointer to netcdf type, where result will be stored.
|
||||
* @param type_info Pointer to type info for the variable.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
static int
|
||||
get_netcdf_type_from_hdf4(NC_HDF5_FILE_INFO_T *h5, int32 hdf4_typeid,
|
||||
nc_type *xtype, NC_TYPE_INFO_T *type_info)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
/* Added this variable in the course of fixing NCF-332.
|
||||
* Prior to the fix, all data types were assigned
|
||||
* NC_ENDIAN_BIG, so I am preserving that here for now.
|
||||
* Not sure why it wouldn't be NC_ENDIAN_NATIVE, although
|
||||
* I can hazard a guess or two.
|
||||
*/
|
||||
int endianness = NC_ENDIAN_BIG;
|
||||
assert(h5 && xtype);
|
||||
|
||||
switch(hdf4_typeid)
|
||||
{
|
||||
case DFNT_CHAR:
|
||||
*xtype = NC_CHAR;
|
||||
t = 0;
|
||||
break;
|
||||
case DFNT_UCHAR:
|
||||
case DFNT_UINT8:
|
||||
*xtype = NC_UBYTE;
|
||||
t = 6;
|
||||
break;
|
||||
case DFNT_LUINT8:
|
||||
*xtype = NC_UBYTE;
|
||||
t = 6;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_INT8:
|
||||
*xtype = NC_BYTE;
|
||||
t = 1;
|
||||
break;
|
||||
case DFNT_LINT8:
|
||||
*xtype = NC_BYTE;
|
||||
t = 1;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_INT16:
|
||||
*xtype = NC_SHORT;
|
||||
t = 2;
|
||||
break;
|
||||
case DFNT_LINT16:
|
||||
*xtype = NC_SHORT;
|
||||
t = 2;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_UINT16:
|
||||
*xtype = NC_USHORT;
|
||||
t = 7;
|
||||
break;
|
||||
case DFNT_LUINT16:
|
||||
*xtype = NC_USHORT;
|
||||
t = 7;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_INT32:
|
||||
*xtype = NC_INT;
|
||||
t = 3;
|
||||
break;
|
||||
case DFNT_LINT32:
|
||||
*xtype = NC_INT;
|
||||
t = 3;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_UINT32:
|
||||
*xtype = NC_UINT;
|
||||
t = 8;
|
||||
break;
|
||||
case DFNT_LUINT32:
|
||||
*xtype = NC_UINT;
|
||||
t = 8;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_FLOAT32:
|
||||
*xtype = NC_FLOAT;
|
||||
t = 4;
|
||||
break;
|
||||
case DFNT_LFLOAT32:
|
||||
*xtype = NC_FLOAT;
|
||||
t = 4;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_FLOAT64:
|
||||
*xtype = NC_DOUBLE;
|
||||
t = 5;
|
||||
break;
|
||||
case DFNT_LFLOAT64:
|
||||
*xtype = NC_DOUBLE;
|
||||
t = 5;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
default:
|
||||
*xtype = NC_NAT;
|
||||
return NC_EBADTYPID;
|
||||
}
|
||||
|
||||
if (type_info)
|
||||
{
|
||||
if (hdf4_typeid == DFNT_FLOAT32)
|
||||
type_info->nc_type_class = NC_FLOAT;
|
||||
else if (hdf4_typeid == DFNT_FLOAT64)
|
||||
type_info->nc_type_class = NC_DOUBLE;
|
||||
else if (hdf4_typeid == DFNT_CHAR)
|
||||
type_info->nc_type_class = NC_STRING;
|
||||
else
|
||||
type_info->nc_type_class = NC_INT;
|
||||
type_info->endianness = endianness;
|
||||
type_info->nc_typeid = *xtype;
|
||||
type_info->size = nc_type_size_g[t];
|
||||
if (!(type_info->name = strdup(nc_type_name_g[t])))
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Open a HDF4 file.
|
||||
*
|
||||
* @param path The file name of the new file.
|
||||
* @param mode The open mode flag.
|
||||
* @param nc Pointer that gets the NC file info struct.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
static int
|
||||
nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
{
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_ATT_INFO_T *att;
|
||||
int32 num_datasets, num_gatts;
|
||||
int32 rank;
|
||||
int v, d, a;
|
||||
int retval;
|
||||
NC_HDF5_FILE_INFO_T* nc4_info = NULL;
|
||||
|
||||
LOG((3, "%s: path %s mode %d", __func__, path, mode));
|
||||
assert(path && nc);
|
||||
|
||||
/* Must be read-only access to hdf4 files. */
|
||||
if (mode & NC_WRITE)
|
||||
return NC_EINVAL;
|
||||
|
||||
/* Add necessary structs to hold netcdf-4 file data. */
|
||||
if ((retval = nc4_nc4f_list_add(nc, path, mode)))
|
||||
return retval;
|
||||
nc4_info = NC4_DATA(nc);
|
||||
assert(nc4_info && nc4_info->root_grp);
|
||||
h5 = nc4_info;
|
||||
h5->hdf4 = NC_TRUE;
|
||||
grp = h5->root_grp;
|
||||
h5->no_write = NC_TRUE;
|
||||
|
||||
/* Open the file and initialize SD interface. */
|
||||
if ((h5->sdid = SDstart(path, DFACC_READ)) == FAIL)
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* Learn how many datasets and global atts we have. */
|
||||
if (SDfileinfo(h5->sdid, &num_datasets, &num_gatts))
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* Read the atts. */
|
||||
for (a = 0; a < num_gatts; a++)
|
||||
{
|
||||
int32 att_data_type, att_count;
|
||||
size_t att_type_size;
|
||||
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(&h5->root_grp->att, &att)))
|
||||
return retval;
|
||||
att->attnum = grp->natts++;
|
||||
att->created = NC_TRUE;
|
||||
|
||||
/* Learn about this attribute. */
|
||||
if (!(att->name = malloc(NC_MAX_HDF4_NAME * sizeof(char))))
|
||||
return NC_ENOMEM;
|
||||
if (SDattrinfo(h5->sdid, a, att->name, &att_data_type, &att_count))
|
||||
return NC_EATTMETA;
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, att_data_type,
|
||||
&att->nc_typeid, NULL)))
|
||||
return retval;
|
||||
att->len = att_count;
|
||||
|
||||
/* Allocate memory to hold the data. */
|
||||
if ((retval = nc4_get_typelen_mem(h5, att->nc_typeid, 0, &att_type_size)))
|
||||
return retval;
|
||||
if (!(att->data = malloc(att_type_size * att->len)))
|
||||
return NC_ENOMEM;
|
||||
|
||||
/* Read the data. */
|
||||
if (SDreadattr(h5->sdid, a, att->data))
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
|
||||
/* Read each dataset. */
|
||||
for (v = 0; v < num_datasets; v++)
|
||||
{
|
||||
NC_VAR_INFO_T *var;
|
||||
int32 data_type, num_atts;
|
||||
/* Problem: Number of dims is returned by the call that requires
|
||||
a pre-allocated array, 'dimsize'.
|
||||
From SDS_SD website:
|
||||
http://www.hdfgroup.org/training/HDFtraining/UsersGuide/SDS_SD.fm3.html
|
||||
The maximum rank is 32, or MAX_VAR_DIMS (as defined in netcdf.h).
|
||||
|
||||
int32 dimsize[MAX_VAR_DIMS];
|
||||
*/
|
||||
int32 *dimsize = NULL;
|
||||
size_t var_type_size;
|
||||
int a;
|
||||
|
||||
/* Add a variable. */
|
||||
if ((retval = nc4_var_add(&var)))
|
||||
return retval;
|
||||
|
||||
var->varid = grp->nvars++;
|
||||
var->created = NC_TRUE;
|
||||
var->written_to = NC_TRUE;
|
||||
|
||||
/* Add a var to the variable array, growing it as needed. */
|
||||
if ((retval = nc4_vararray_add(grp, var)))
|
||||
return retval;
|
||||
|
||||
/* Open this dataset in HDF4 file. */
|
||||
if ((var->sdsid = SDselect(h5->sdid, v)) == FAIL)
|
||||
return NC_EVARMETA;
|
||||
|
||||
/* Get shape, name, type, and attribute info about this dataset. */
|
||||
if (!(var->name = malloc(NC_MAX_HDF4_NAME + 1)))
|
||||
return NC_ENOMEM;
|
||||
|
||||
/* Invoke SDgetInfo with null dimsize to get rank. */
|
||||
if (SDgetinfo(var->sdsid, var->name, &rank, NULL, &data_type, &num_atts))
|
||||
return NC_EVARMETA;
|
||||
|
||||
var->hash = hash_fast(var->name, strlen(var->name));
|
||||
|
||||
if(!(dimsize = (int32*)malloc(sizeof(int32)*rank)))
|
||||
return NC_ENOMEM;
|
||||
|
||||
if (SDgetinfo(var->sdsid, var->name, &rank, dimsize, &data_type, &num_atts)) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EVARMETA;
|
||||
}
|
||||
|
||||
var->ndims = rank;
|
||||
var->hdf4_data_type = data_type;
|
||||
|
||||
/* Fill special type_info struct for variable type information. */
|
||||
if (!(var->type_info = calloc(1, sizeof(NC_TYPE_INFO_T)))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, data_type, &var->type_info->nc_typeid, var->type_info))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Indicate that the variable has a pointer to the type */
|
||||
var->type_info->rc++;
|
||||
|
||||
if ((retval = nc4_get_typelen_mem(h5, var->type_info->nc_typeid, 0, &var_type_size))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
var->type_info->size = var_type_size;
|
||||
LOG((3, "reading HDF4 dataset %s, rank %d netCDF type %d", var->name,
|
||||
rank, var->type_info->nc_typeid));
|
||||
|
||||
/* Get the fill value. */
|
||||
if (!(var->fill_value = malloc(var_type_size))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
if (SDgetfillvalue(var->sdsid, var->fill_value))
|
||||
{
|
||||
/* Whoops! No fill value! */
|
||||
free(var->fill_value);
|
||||
var->fill_value = NULL;
|
||||
}
|
||||
|
||||
/* Allocate storage for dimension info in this variable. */
|
||||
if (var->ndims)
|
||||
{
|
||||
if (!(var->dim = malloc(sizeof(NC_DIM_INFO_T *) * var->ndims))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
if (!(var->dimids = malloc(sizeof(int) * var->ndims))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Find its dimensions. */
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
{
|
||||
int32 dimid, dim_len, dim_data_type, dim_num_attrs;
|
||||
char dim_name[NC_MAX_NAME + 1];
|
||||
NC_DIM_INFO_T *dim;
|
||||
|
||||
if ((dimid = SDgetdimid(var->sdsid, d)) == FAIL) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EDIMMETA;
|
||||
}
|
||||
if (SDdiminfo(dimid, dim_name, &dim_len, &dim_data_type,
|
||||
&dim_num_attrs))
|
||||
{
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EDIMMETA;
|
||||
}
|
||||
|
||||
/* Do we already have this dimension? HDF4 explicitly uses
|
||||
* the name to tell. */
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
if (!strcmp(dim->name, dim_name))
|
||||
break;
|
||||
|
||||
/* If we didn't find this dimension, add one. */
|
||||
if (!dim)
|
||||
{
|
||||
LOG((4, "adding dimension %s for HDF4 dataset %s",
|
||||
dim_name, var->name));
|
||||
if ((retval = nc4_dim_list_add(&grp->dim, &dim)))
|
||||
return retval;
|
||||
dim->dimid = grp->nc4_info->next_dimid++;
|
||||
if (strlen(dim_name) > NC_MAX_HDF4_NAME)
|
||||
return NC_EMAXNAME;
|
||||
if (!(dim->name = strdup(dim_name)))
|
||||
return NC_ENOMEM;
|
||||
if (dim_len)
|
||||
dim->len = dim_len;
|
||||
else
|
||||
dim->len = *dimsize;
|
||||
dim->hash = hash_fast(dim_name, strlen(dim_name));
|
||||
}
|
||||
|
||||
/* Tell the variable the id of this dimension. */
|
||||
var->dimids[d] = dim->dimid;
|
||||
var->dim[d] = dim;
|
||||
}
|
||||
|
||||
/* Read the atts. */
|
||||
for (a = 0; a < num_atts; a++)
|
||||
{
|
||||
int32 att_data_type, att_count;
|
||||
size_t att_type_size;
|
||||
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(&var->att, &att))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
att->attnum = var->natts++;
|
||||
att->created = NC_TRUE;
|
||||
|
||||
/* Learn about this attribute. */
|
||||
if (!(att->name = malloc(NC_MAX_HDF4_NAME * sizeof(char)))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
if (SDattrinfo(var->sdsid, a, att->name, &att_data_type, &att_count)) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EATTMETA;
|
||||
}
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, att_data_type,
|
||||
&att->nc_typeid, NULL))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
att->len = att_count;
|
||||
|
||||
/* Allocate memory to hold the data. */
|
||||
if ((retval = nc4_get_typelen_mem(h5, att->nc_typeid, 0, &att_type_size))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
if (!(att->data = malloc(att_type_size * att->len))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
/* Read the data. */
|
||||
if (SDreadattr(var->sdsid, a, att->data)) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
}
|
||||
if(dimsize) free(dimsize);
|
||||
|
||||
{
|
||||
/* HDF4 files can be chunked */
|
||||
HDF_CHUNK_DEF chunkdefs;
|
||||
int flag;
|
||||
if(!SDgetchunkinfo(var->sdsid, &chunkdefs, &flag)) {
|
||||
if(flag == HDF_NONE)
|
||||
var->contiguous = NC_TRUE;
|
||||
else if((flag & HDF_CHUNK) != 0) {
|
||||
var->contiguous = NC_FALSE;
|
||||
if (!(var->chunksizes = malloc(var->ndims * sizeof(size_t))))
|
||||
return NC_ENOMEM;
|
||||
for (d = 0; d < var->ndims; d++) {
|
||||
var->chunksizes[d] = chunkdefs.chunk_lengths[d];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* next var */
|
||||
|
||||
#ifdef LOGGING
|
||||
/* This will print out the names, types, lens, etc of the vars and
|
||||
atts in the file, if the logging level is 2 or greater. */
|
||||
log_metadata_nc(h5->root_grp->nc4_info->controller);
|
||||
#endif
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Open a HDF4 file.
|
||||
*
|
||||
* @param path The file name of the file.
|
||||
* @param mode The open mode flag.
|
||||
* @param basepe Ignored by this function.
|
||||
* @param chunksizehintp Ignored by this function.
|
||||
* @param use_parallel Must be 0 for sequential, access. Parallel
|
||||
* access not supported for HDF4.
|
||||
* @param parameters pointer to struct holding extra data (e.g. for
|
||||
* parallel I/O) layer. Ignored if NULL.
|
||||
* @param dispatch Pointer to the dispatch table for this file.
|
||||
* @param nc_file Pointer to an instance of NC.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EINVAL Invalid input.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_open(const char *path, int mode, int basepe, size_t *chunksizehintp,
|
||||
int use_parallel, void *parameters, NC_Dispatch *dispatch,
|
||||
NC *nc_file)
|
||||
{
|
||||
assert(nc_file && path);
|
||||
|
||||
LOG((1, "%s: path %s mode %d params %x", __func__, path, mode,
|
||||
parameters));
|
||||
|
||||
/* Check inputs. */
|
||||
assert(path && !use_parallel);
|
||||
|
||||
/* Check the mode for validity */
|
||||
if (mode & ILLEGAL_OPEN_FLAGS)
|
||||
return NC_EINVAL;
|
||||
|
||||
/* Open the file. */
|
||||
nc_file->int_ncid = nc_file->ext_ncid;
|
||||
return nc4_open_hdf4_file(path, mode, nc_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Unfortunately HDF only allows specification of fill value
|
||||
* only when a dataset is created. Whereas in netcdf, you first create
|
||||
* the variable and then (optionally) specify the fill value. To
|
||||
* accomplish this in HDF5 I have to delete the dataset, and recreate
|
||||
* it, with the fill value specified.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param fillmode File mode.
|
||||
* @param old_modep Pointer that gets old mode. Ignored if NULL.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_set_fill(int ncid, int fillmode, int *old_modep)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Not allowed for HDF4 files.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
*
|
||||
* @return ::NC_ENOTNC4 No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_redef(int ncid)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal This does nothing for HDF4 files. Since they are
|
||||
* read-only, then can never be put into define mode.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param h_minfree Ignored for netCDF-4 files.
|
||||
* @param v_align Ignored for netCDF-4 files.
|
||||
* @param v_minfree Ignored for netCDF-4 files.
|
||||
* @param r_align Ignored for netCDF-4 files.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4__enddef(int ncid, size_t h_minfree, size_t v_align,
|
||||
size_t v_minfree, size_t r_align)
|
||||
{
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Does nothing, since HDF4 files are read only. There can
|
||||
* be no changes to sync to disk.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_sync(int ncid)
|
||||
{
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Closes the file. There can be no changes to abort since
|
||||
* HDF4 files are read only.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_abort(int ncid)
|
||||
{
|
||||
NC *nc;
|
||||
NC_HDF5_FILE_INFO_T* nc4_info;
|
||||
int retval;
|
||||
|
||||
LOG((2, "%s: ncid 0x%x", __func__, ncid));
|
||||
|
||||
/* Find metadata for this file. */
|
||||
if (!(nc = nc4_find_nc_file(ncid, &nc4_info)))
|
||||
return NC_EBADID;
|
||||
assert(nc4_info);
|
||||
|
||||
/* Free any resources the netcdf-4 library has for this file's
|
||||
* metadata. */
|
||||
if ((retval = close_hdf4_file(nc4_info, 1)))
|
||||
return retval;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Close the HDF4 file.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_close(int ncid)
|
||||
{
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC *nc;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
int retval;
|
||||
|
||||
LOG((1, "%s: ncid 0x%x", __func__, ncid));
|
||||
|
||||
/* Find our metadata for this file. */
|
||||
if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
|
||||
return retval;
|
||||
assert(nc && h5 && grp && !grp->parent);
|
||||
|
||||
/* Call the nc4 close. */
|
||||
if ((retval = close_hdf4_file(grp->nc4_info, 0)))
|
||||
return retval;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
|
112
libhdf4/hdf4func.c
Normal file
112
libhdf4/hdf4func.c
Normal file
@ -0,0 +1,112 @@
|
||||
/* Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for copying
|
||||
* and redistribution conditions.*/
|
||||
/**
|
||||
* @file @internal This file handles the (useless) *_base_pe()
|
||||
* functions, and the inq_format functions for the HDF4 dispatch
|
||||
* layer.
|
||||
*
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
|
||||
#include "nc4internal.h"
|
||||
#include "nc4dispatch.h"
|
||||
|
||||
/**
|
||||
* @internal This function only does anything for netcdf-3 files.
|
||||
*
|
||||
* @param ncid File ID (ignored).
|
||||
* @param pe Processor element (ignored).
|
||||
*
|
||||
* @return ::NC_ENOTNC3 Not a netCDF classic format file.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_set_base_pe(int ncid, int pe)
|
||||
{
|
||||
return NC_ENOTNC3;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal This function only does anything for netcdf-3 files.
|
||||
*
|
||||
* @param ncid File ID (ignored).
|
||||
* @param pe Pointer to processor element. Ignored if NULL. Gets a 0
|
||||
* if present.
|
||||
*
|
||||
* @return ::NC_ENOTNC3 Not a netCDF classic format file.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_inq_base_pe(int ncid, int *pe)
|
||||
{
|
||||
return NC_ENOTNC3;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Get the format (i.e. NC_FORMAT_NC_HDF4) of an open HDF4
|
||||
* file.
|
||||
*
|
||||
* @param ncid File ID (ignored).
|
||||
* @param formatp Pointer that gets the constant indicating format.
|
||||
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_inq_format(int ncid, int *formatp)
|
||||
{
|
||||
NC *nc;
|
||||
NC_HDF5_FILE_INFO_T* nc4_info;
|
||||
|
||||
LOG((2, "nc_inq_format: ncid 0x%x", ncid));
|
||||
|
||||
if (!formatp)
|
||||
return NC_NOERR;
|
||||
|
||||
/* Find the file metadata. */
|
||||
if (!(nc = nc4_find_nc_file(ncid, &nc4_info)))
|
||||
return NC_EBADID;
|
||||
|
||||
/* HDF4 is the format. */
|
||||
*formatp = NC_FORMATX_NC_HDF4;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Return the extended format (i.e. the dispatch model),
|
||||
* plus the mode associated with an open file.
|
||||
*
|
||||
* @param ncid File ID (ignored).
|
||||
* @param formatp a pointer that gets the extended format. Note that
|
||||
* this is not the same as the format provided by nc_inq_format(). The
|
||||
* extended foramt indicates the dispatch layer model. HDF4 files
|
||||
* will always get NC_FORMATX_NC_HDF4.
|
||||
* @param modep a pointer that gets the open/create mode associated with
|
||||
* this file. Ignored if NULL.
|
||||
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_inq_format_extended(int ncid, int *formatp, int *modep)
|
||||
{
|
||||
NC *nc;
|
||||
NC_HDF5_FILE_INFO_T* h5;
|
||||
|
||||
LOG((2, "%s: ncid 0x%x", __func__, ncid));
|
||||
|
||||
/* Find the file metadata. */
|
||||
if (!(nc = nc4_find_nc_file(ncid,&h5)))
|
||||
return NC_EBADID;
|
||||
|
||||
if (modep)
|
||||
*modep = (nc->mode|NC_NETCDF4);
|
||||
|
||||
if (formatp)
|
||||
*formatp = NC_FORMATX_NC_HDF4;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
53
libhdf4/hdf4grp.c
Normal file
53
libhdf4/hdf4grp.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for copying
|
||||
* and redistribution conditions.*/
|
||||
/**
|
||||
* @file @internal This file handles groups for the HDF4 dispatch
|
||||
* layer. All functions return ::NC_ENOTNC4.
|
||||
*
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
#include "nc4internal.h"
|
||||
#include "hdf4dispatch.h"
|
||||
|
||||
/**
|
||||
* @internal Create a group. Its ncid is returned in the new_ncid
|
||||
* pointer.
|
||||
*
|
||||
* @param parent_ncid Parent group.
|
||||
* @param name Name of new group.
|
||||
* @param new_ncid Pointer that gets ncid for new group.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_ESTRICTNC3 Classic model in use for this file.
|
||||
* @return ::NC_ENOTNC4 Not a netCDF-4 file.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_def_grp(int parent_ncid, const char *name, int *new_ncid)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Rename a group.
|
||||
*
|
||||
* @param grpid Group ID.
|
||||
* @param name New name for group.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_ENOTNC4 Not a netCDF-4 file.
|
||||
* @return ::NC_EPERM File opened read-only.
|
||||
* @return ::NC_EBADGRPID Renaming root forbidden.
|
||||
* @return ::NC_EHDFERR HDF5 function returned error.
|
||||
* @return ::NC_ENOMEM Out of memory.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_rename_grp(int grpid, const char *name)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
|
309
libhdf4/hdf4type.c
Normal file
309
libhdf4/hdf4type.c
Normal file
@ -0,0 +1,309 @@
|
||||
/* Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for copying
|
||||
* and redistribution conditions.*/
|
||||
/**
|
||||
* @file @internal This file contains the type functions for the HDF4
|
||||
* dispatch layer.
|
||||
*
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
#include "nc4internal.h"
|
||||
#include "nc4dispatch.h"
|
||||
|
||||
#define NUM_ATOMIC_TYPES 13 /**< Number of netCDF atomic types. */
|
||||
|
||||
/* The sizes of types may vary from platform to platform, but within
|
||||
* netCDF files, type sizes are fixed. */
|
||||
#define NC_CHAR_LEN sizeof(char) /**< @internal Size of char. */
|
||||
#define NC_STRING_LEN sizeof(char *) /**< @internal Size of char *. */
|
||||
#define NC_BYTE_LEN 1 /**< @internal Size of byte. */
|
||||
#define NC_SHORT_LEN 2 /**< @internal Size of short. */
|
||||
#define NC_INT_LEN 4 /**< @internal Size of int. */
|
||||
#define NC_FLOAT_LEN 4 /**< @internal Size of float. */
|
||||
#define NC_DOUBLE_LEN 8 /**< @internal Size of double. */
|
||||
#define NC_INT64_LEN 8 /**< @internal Size of int64. */
|
||||
|
||||
/**
|
||||
* @internal Create a compound type.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param size Gets size in bytes of one element of type.
|
||||
* @param name Name of the type.
|
||||
* @param typeidp Gets the type ID.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_EMAXNAME Name is too long.
|
||||
* @return ::NC_EBADNAME Name breaks netCDF name rules.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_def_compound(int ncid, size_t size, const char *name, nc_type *typeidp)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Insert a named field into a compound type.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param typeid1 Type ID.
|
||||
* @param name Name of the type.
|
||||
* @param offset Offset of field.
|
||||
* @param field_typeid Field type ID.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_EMAXNAME Name is too long.
|
||||
* @return ::NC_EBADNAME Name breaks netCDF name rules.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_insert_compound(int ncid, nc_type typeid1, const char *name, size_t offset,
|
||||
nc_type field_typeid)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Insert a named array into a compound type.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param typeid1 Type ID.
|
||||
* @param name Name of the array field.
|
||||
* @param offset Offset in bytes.
|
||||
* @param field_typeid Type of field.
|
||||
* @param ndims Number of dims for field.
|
||||
* @param dim_sizesp Array of dim sizes.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_EMAXNAME Name is too long.
|
||||
* @return ::NC_EBADNAME Name breaks netCDF name rules.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
extern int
|
||||
HDF4_insert_array_compound(int ncid, int typeid1, const char *name,
|
||||
size_t offset, nc_type field_typeid,
|
||||
int ndims, const int *dim_sizesp)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Given the ncid, typeid and fieldid, get info about the
|
||||
* field.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param typeid1 Type ID.
|
||||
* @param fieldid Field ID.
|
||||
* @param name Gets name of field.
|
||||
* @param offsetp Gets offset of field.
|
||||
* @param field_typeidp Gets field type ID.
|
||||
* @param ndimsp Gets number of dims for this field.
|
||||
* @param dim_sizesp Gets the dim sizes for this field.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_inq_compound_field(int ncid, nc_type typeid1, int fieldid, char *name,
|
||||
size_t *offsetp, nc_type *field_typeidp, int *ndimsp,
|
||||
int *dim_sizesp)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Given the typeid and the name, get the fieldid.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param typeid1 Type ID.
|
||||
* @param name Name of field.
|
||||
* @param fieldidp Pointer that gets new field ID.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_EBADTYPE Type not found.
|
||||
* @return ::NC_EBADFIELD Field not found.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_inq_compound_fieldindex(int ncid, nc_type typeid1, const char *name, int *fieldidp)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/* Opaque type. */
|
||||
|
||||
/**
|
||||
* @internal Create an opaque type. Provide a size and a name.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param datum_size Size in bytes of a datum.
|
||||
* @param name Name of new vlen type.
|
||||
* @param typeidp Pointer that gets new type ID.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_EMAXNAME Name is too long.
|
||||
* @return ::NC_EBADNAME Name breaks netCDF name rules.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_def_opaque(int ncid, size_t datum_size, const char *name,
|
||||
nc_type *typeidp)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Define a variable length type.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param name Name of new vlen type.
|
||||
* @param base_typeid Base type of vlen.
|
||||
* @param typeidp Pointer that gets new type ID.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_EMAXNAME Name is too long.
|
||||
* @return ::NC_EBADNAME Name breaks netCDF name rules.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_def_vlen(int ncid, const char *name, nc_type base_typeid,
|
||||
nc_type *typeidp)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Create an enum type. Provide a base type and a name. At
|
||||
* the moment only ints are accepted as base types.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param base_typeid Base type of vlen.
|
||||
* @param name Name of new vlen type.
|
||||
* @param typeidp Pointer that gets new type ID.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EMAXNAME Name is too long.
|
||||
* @return ::NC_EBADNAME Name breaks netCDF name rules.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_def_enum(int ncid, nc_type base_typeid, const char *name,
|
||||
nc_type *typeidp)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal Get enum name from enum value. Name size will be <=
|
||||
* NC_MAX_NAME.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param xtype Type ID.
|
||||
* @param value Value of enum.
|
||||
* @param identifier Gets the identifier for this enum value.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_EBADTYPE Type not found.
|
||||
* @return ::NC_EINVAL Invalid type data.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Get information about an enum member: an identifier and
|
||||
* value. Identifier size will be <= NC_MAX_NAME.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param typeid1 Type ID.
|
||||
* @param idx Enum member index.
|
||||
* @param identifier Gets the identifier.
|
||||
* @param value Gets the enum value.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_EBADTYPE Type not found.
|
||||
* @return ::NC_EINVAL Bad idx.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_inq_enum_member(int ncid, nc_type typeid1, int idx, char *identifier,
|
||||
void *value)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Insert a identifier value into an enum type. The value
|
||||
* must fit within the size of the enum type, the identifier size must
|
||||
* be <= NC_MAX_NAME.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param typeid1 Type ID.
|
||||
* @param identifier Name of this enum value.
|
||||
* @param value Value of enum.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID Bad ncid.
|
||||
* @return ::NC_EBADTYPE Type not found.
|
||||
* @return ::NC_ETYPDEFINED Type already defined.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_insert_enum(int ncid, nc_type typeid1, const char *identifier,
|
||||
const void *value)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Insert one element into an already allocated vlen array
|
||||
* element.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param typeid1 Type ID.
|
||||
* @param vlen_element The VLEN element to insert.
|
||||
* @param len Length of element in bytes.
|
||||
* @param data Element data.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_put_vlen_element(int ncid, int typeid1, void *vlen_element,
|
||||
size_t len, const void *data)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Insert one element into an already allocated vlen array
|
||||
* element.
|
||||
*
|
||||
* @param ncid File and group ID.
|
||||
* @param typeid1 Type ID.
|
||||
* @param vlen_element The VLEN element to insert.
|
||||
* @param len Length of element in bytes.
|
||||
* @param data Element data.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_get_vlen_element(int ncid, int typeid1, const void *vlen_element,
|
||||
size_t *len, void *data)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
379
libhdf4/hdf4var.c
Normal file
379
libhdf4/hdf4var.c
Normal file
@ -0,0 +1,379 @@
|
||||
/* Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for copying
|
||||
* and redistribution conditions.*/
|
||||
/**
|
||||
* @file @internal This file handles the variable functions for the
|
||||
* HDF4 dispatch layer.
|
||||
*
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
|
||||
#include <nc4internal.h>
|
||||
#include "nc4dispatch.h"
|
||||
|
||||
/**
|
||||
* @internal Set chunk cache size for a variable. This is the internal
|
||||
* function called by nc_set_var_chunk_cache().
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param size Size in bytes to set cache.
|
||||
* @param nelems Number of elements in cache.
|
||||
* @param preemption Controls cache swapping.
|
||||
*
|
||||
* @returns ::NC_NOERR No error.
|
||||
* @returns ::NC_EBADID Bad ncid.
|
||||
* @returns ::NC_ENOTVAR Invalid variable ID.
|
||||
* @returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
|
||||
* @returns ::NC_EINVAL Invalid input.
|
||||
* @returns ::NC_EHDFERR HDF5 error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems,
|
||||
float preemption)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal This is called by nc_get_var_chunk_cache(). Get chunk
|
||||
* cache size for a variable.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param sizep Gets size in bytes of cache.
|
||||
* @param nelemsp Gets number of element slots in cache.
|
||||
* @param preemptionp Gets cache swapping setting.
|
||||
*
|
||||
* @returns ::NC_NOERR No error.
|
||||
* @returns ::NC_EBADID Bad ncid.
|
||||
* @returns ::NC_ENOTVAR Invalid variable ID.
|
||||
* @returns ::NC_ENOTNC4 Not a netCDF-4 file.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_get_var_chunk_cache(int ncid, int varid, size_t *sizep,
|
||||
size_t *nelemsp, float *preemptionp)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Not allowed for HDF4.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param name Name.
|
||||
* @param xtype Type.
|
||||
* @param ndims Number of dims.
|
||||
* @param dimidsp Array of dim IDs.
|
||||
* @param varidp Gets the var ID.
|
||||
*
|
||||
* @returns ::NC_EPERM Not allowed for HDF4.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_def_var(int ncid, const char *name, nc_type xtype,
|
||||
int ndims, const int *dimidsp, int *varidp)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Set compression settings on a variable. This is called by
|
||||
* nc_def_var_deflate().
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param shuffle True to turn on the shuffle filter.
|
||||
* @param deflate True to turn on deflation.
|
||||
* @param deflate_level A number between 0 (no compression) and 9
|
||||
* (maximum compression).
|
||||
*
|
||||
* @returns ::NC_NOERR No error.
|
||||
* @returns ::NC_EBADID Bad ncid.
|
||||
* @returns ::NC_ENOTVAR Invalid variable ID.
|
||||
* @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
|
||||
* not netCDF-4/HDF5.
|
||||
* @returns ::NC_ELATEDEF Too late to change settings for this variable.
|
||||
* @returns ::NC_ENOTINDEFINE Not in define mode.
|
||||
* @returns ::NC_EINVAL Invalid input
|
||||
* @author Ed Hartnett, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
HDF4_def_var_deflate(int ncid, int varid, int shuffle, int deflate,
|
||||
int deflate_level)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Set checksum on a variable. This is called by
|
||||
* nc_def_var_fletcher32().
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param fletcher32 Pointer to fletcher32 setting.
|
||||
*
|
||||
* @returns ::NC_NOERR No error.
|
||||
* @returns ::NC_EBADID Bad ncid.
|
||||
* @returns ::NC_ENOTVAR Invalid variable ID.
|
||||
* @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
|
||||
* not netCDF-4/HDF5.
|
||||
* @returns ::NC_ELATEDEF Too late to change settings for this variable.
|
||||
* @returns ::NC_ENOTINDEFINE Not in define mode.
|
||||
* @returns ::NC_EINVAL Invalid input
|
||||
* @author Ed Hartnett, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
HDF4_def_var_fletcher32(int ncid, int varid, int fletcher32)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Define chunking stuff for a var. This is called by
|
||||
* nc_def_var_chunking(). Chunking is required in any dataset with one
|
||||
* or more unlimited dimensions in HDF5, or any dataset using a
|
||||
* filter.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param contiguous Pointer to contiguous setting.
|
||||
* @param chunksizesp Array of chunksizes.
|
||||
*
|
||||
* @returns ::NC_NOERR No error.
|
||||
* @returns ::NC_EBADID Bad ncid.
|
||||
* @returns ::NC_ENOTVAR Invalid variable ID.
|
||||
* @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
|
||||
* not netCDF-4/HDF5.
|
||||
* @returns ::NC_ELATEDEF Too late to change settings for this variable.
|
||||
* @returns ::NC_ENOTINDEFINE Not in define mode.
|
||||
* @returns ::NC_EINVAL Invalid input
|
||||
* @returns ::NC_EBADCHUNK Bad chunksize.
|
||||
* @author Ed Hartnett, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
HDF4_def_var_chunking(int ncid, int varid, int contiguous, const size_t *chunksizesp)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal This functions sets fill value and no_fill mode for a
|
||||
* netCDF-4 variable. It is called by nc_def_var_fill().
|
||||
*
|
||||
* @note All pointer parameters may be NULL, in which case they are ignored.
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param no_fill No_fill setting.
|
||||
* @param fill_value Pointer to fill value.
|
||||
*
|
||||
* @returns ::NC_NOERR for success
|
||||
* @returns ::NC_EBADID Bad ncid.
|
||||
* @returns ::NC_ENOTVAR Invalid variable ID.
|
||||
* @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
|
||||
* not netCDF-4/HDF5.
|
||||
* @returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
|
||||
* netcdf-4 file.
|
||||
* @returns ::NC_ELATEDEF Too late to change settings for this variable.
|
||||
* @returns ::NC_ENOTINDEFINE Not in define mode.
|
||||
* @returns ::NC_EPERM File is read only.
|
||||
* @returns ::NC_EINVAL Invalid input
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal This functions sets endianness for a netCDF-4
|
||||
* variable. Called by nc_def_var_endian().
|
||||
*
|
||||
* @note All pointer parameters may be NULL, in which case they are ignored.
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param endianness Endianness setting.
|
||||
*
|
||||
* @returns ::NC_NOERR for success
|
||||
* @returns ::NC_EBADID Bad ncid.
|
||||
* @returns ::NC_ENOTVAR Invalid variable ID.
|
||||
* @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
|
||||
* not netCDF-4/HDF5.
|
||||
* @returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
|
||||
* netcdf-4 file.
|
||||
* @returns ::NC_ELATEDEF Too late to change settings for this variable.
|
||||
* @returns ::NC_ENOTINDEFINE Not in define mode.
|
||||
* @returns ::NC_EPERM File is read only.
|
||||
* @returns ::NC_EINVAL Invalid input
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_def_var_endian(int ncid, int varid, int endianness)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Define filter settings. Called by nc_def_var_filter().
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param id Filter ID
|
||||
* @param nparams Number of parameters for filter.
|
||||
* @param parms Filter parameters.
|
||||
*
|
||||
* @returns ::NC_NOERR for success
|
||||
* @returns ::NC_EBADID Bad ncid.
|
||||
* @returns ::NC_ENOTVAR Invalid variable ID.
|
||||
* @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
|
||||
* not netCDF-4/HDF5.
|
||||
* @returns ::NC_ELATEDEF Too late to change settings for this variable.
|
||||
* @returns ::NC_EFILTER Filter error.
|
||||
* @returns ::NC_EINVAL Invalid input
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
HDF4_def_var_filter(int ncid, int varid, unsigned int id, size_t nparams,
|
||||
const unsigned int* parms)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Not allowed for HDF4.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID
|
||||
* @param name New name of the variable.
|
||||
*
|
||||
* @returns ::NC_EPERM Not allowed for HDF4.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
HDF4_rename_var(int ncid, int varid, const char *name)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* This function will change the parallel access of a variable from
|
||||
* independent to collective.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param par_access NC_COLLECTIVE or NC_INDEPENDENT.
|
||||
*
|
||||
* @returns ::NC_NOERR No error.
|
||||
* @returns ::NC_EBADID Invalid ncid passed.
|
||||
* @returns ::NC_ENOTVAR Invalid varid passed.
|
||||
* @returns ::NC_ENOPAR LFile was not opened with nc_open_par/nc_create_var.
|
||||
* @returns ::NC_EINVAL Invalid par_access specified.
|
||||
* @returns ::NC_NOERR for success
|
||||
* @author Ed Hartnett, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
HDF4_var_par_access(int ncid, int varid, int par_access)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Get data from an HDF4 SD dataset.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param startp Array of start indicies.
|
||||
* @param countp Array of counts.
|
||||
* @param mem_nc_type The type of these data after it is read into memory.
|
||||
* @param is_long Ignored for HDF4.
|
||||
* @param data pointer that gets the data.
|
||||
* @returns ::NC_NOERR for success
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
static int
|
||||
nc4_get_hdf4_vara(NC *nc, int ncid, int varid, const size_t *startp,
|
||||
const size_t *countp, nc_type mem_nc_type, int is_long, void *data)
|
||||
{
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_VAR_INFO_T *var;
|
||||
int32 start32[NC_MAX_VAR_DIMS], edge32[NC_MAX_VAR_DIMS];
|
||||
int retval, d;
|
||||
|
||||
/* Find our metadata for this file, group, and var. */
|
||||
assert(nc);
|
||||
if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
|
||||
return retval;
|
||||
h5 = NC4_DATA(nc);
|
||||
assert(grp && h5 && var && var->name);
|
||||
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
{
|
||||
start32[d] = startp[d];
|
||||
edge32[d] = countp[d];
|
||||
}
|
||||
|
||||
if (SDreaddata(var->sdsid, start32, NULL, edge32, data))
|
||||
return NC_EHDFERR;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Write an array of data to a variable. This is called by
|
||||
* nc_put_vara() and other nc_put_vara_* functions, for netCDF-4
|
||||
* files.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param startp Array of start indicies.
|
||||
* @param countp Array of counts.
|
||||
* @param op pointer that gets the data.
|
||||
* @param memtype The type of these data in memory.
|
||||
*
|
||||
* @returns ::NC_NOERR for success
|
||||
* @author Ed Hartnett, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
HDF4_put_vara(int ncid, int varid, const size_t *startp,
|
||||
const size_t *countp, const void *op, int memtype)
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an array of values. This is called by nc_get_vara() for
|
||||
* netCDF-4 files, as well as all the other nc_get_vara_*
|
||||
* functions. HDF4 files are handled as a special case.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param startp Array of start indicies.
|
||||
* @param countp Array of counts.
|
||||
* @param ip pointer that gets the data.
|
||||
* @param memtype The type of these data after it is read into memory.
|
||||
|
||||
* @returns ::NC_NOERR for success
|
||||
* @author Ed Hartnett, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
HDF4_get_vara(int ncid, int varid, const size_t *startp,
|
||||
const size_t *countp, void *ip, int memtype)
|
||||
{
|
||||
NC *nc;
|
||||
NC_HDF5_FILE_INFO_T* h5;
|
||||
|
||||
LOG((2, "%s: ncid 0x%x varid %d memtype %d", __func__, ncid, varid,
|
||||
memtype));
|
||||
|
||||
if (!(nc = nc4_find_nc_file(ncid, &h5)))
|
||||
return NC_EBADID;
|
||||
|
||||
/* Handle HDF4 cases. */
|
||||
return nc4_get_hdf4_vara(nc, ncid, varid, startp, countp, memtype,
|
||||
0, (void *)ip);
|
||||
}
|
@ -13,6 +13,10 @@ IF(USE_PNETCDF)
|
||||
SET(liblib_LIBS ${liblib_LIBS} netcdfp)
|
||||
ENDIF()
|
||||
|
||||
IF(USE_HDF4)
|
||||
SET(liblib_LIBS ${liblib_LIBS} netcdfhdf4)
|
||||
ENDIF()
|
||||
|
||||
IF(ENABLE_DAP2)
|
||||
SET(liblib_LIBS ${liblib_LIBS} oc2 dap2)
|
||||
ENDIF()
|
||||
|
@ -40,6 +40,12 @@ AM_CPPFLAGS += -I${top_srcdir}/libsrcp
|
||||
libnetcdf_la_LIBADD += ${top_builddir}/libsrcp/libnetcdfp.la
|
||||
endif # USE_PNETCDF
|
||||
|
||||
# + hdf4
|
||||
if USE_HDF4
|
||||
AM_CPPFLAGS += -I${top_srcdir}/libhdf4
|
||||
libnetcdf_la_LIBADD += ${top_builddir}/libhdf4/libnchdf4.la
|
||||
endif # USE_PNETCDF
|
||||
|
||||
# + dap
|
||||
if ENABLE_DAP
|
||||
AM_CPPFLAGS += -I${top_srcdir}/libdap2 -I${top_srcdir}/oc
|
||||
|
@ -35,6 +35,11 @@ extern int NCP_initialize(void);
|
||||
extern int NCP_finalize(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_HDF4
|
||||
extern int HDF4_initialize(void);
|
||||
extern int HDF4_finalize(void);
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
@ -83,6 +88,9 @@ nc_initialize()
|
||||
#ifdef USE_PNETCDF
|
||||
if((stat = NCP_initialize())) goto done;
|
||||
#endif
|
||||
#ifdef USE_HDF4
|
||||
if((stat = HDF4_initialize())) goto done;
|
||||
#endif
|
||||
#ifdef USE_NETCDF4
|
||||
if((stat = NC4_initialize())) goto done;
|
||||
stat = NC4_fileinfo_init();
|
||||
|
@ -1,3 +1,6 @@
|
||||
/* Copyright 2003-2018, University Corporation for Atmospheric
|
||||
* Research. See COPYRIGHT file for copying and redistribution
|
||||
* conditions. */
|
||||
/**
|
||||
* @file
|
||||
* @internal The netCDF-4 file functions.
|
||||
@ -5,10 +8,9 @@
|
||||
* This file is part of netcdf-4, a netCDF-like interface for HDF5, or
|
||||
* a HDF5 backend for netCDF, depending on your point of view.
|
||||
*
|
||||
* Copyright 2003, University Corporation for Atmospheric Research. See
|
||||
* COPYRIGHT file for copying and redistribution conditions.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <errno.h> /* netcdf functions sometimes return system errors */
|
||||
#include "nc.h"
|
||||
@ -16,13 +18,8 @@
|
||||
#include "nc4dispatch.h"
|
||||
#include <H5DSpublic.h> /* must be after nc4internal.h */
|
||||
#include <H5Fpublic.h>
|
||||
#ifdef USE_HDF4
|
||||
#include <mfhdf.h>
|
||||
#endif
|
||||
#include <hdf5_hl.h>
|
||||
|
||||
extern int nc4_vararray_add(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
|
||||
|
||||
/** @internal When we have open objects at file close, should
|
||||
we log them or print to stdout. Default is to log. */
|
||||
#define LOGOPEN 1
|
||||
@ -582,54 +579,44 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort)
|
||||
goto exit;
|
||||
|
||||
/* Close hdf file. */
|
||||
#ifdef USE_HDF4
|
||||
if (h5->hdf4)
|
||||
{
|
||||
if (SDend(h5->sdid))
|
||||
BAIL_QUIET(NC_EHDFERR);
|
||||
}
|
||||
else
|
||||
#endif /* USE_HDF4 */
|
||||
{
|
||||
#ifdef USE_PARALLEL4
|
||||
/* Free the MPI Comm & Info objects, if we opened the file in parallel */
|
||||
if(h5->parallel)
|
||||
{
|
||||
if(MPI_COMM_NULL != h5->comm)
|
||||
MPI_Comm_free(&h5->comm);
|
||||
if(MPI_INFO_NULL != h5->info)
|
||||
MPI_Info_free(&h5->info);
|
||||
}
|
||||
/* Free the MPI Comm & Info objects, if we opened the file in parallel */
|
||||
if(h5->parallel)
|
||||
{
|
||||
if(MPI_COMM_NULL != h5->comm)
|
||||
MPI_Comm_free(&h5->comm);
|
||||
if(MPI_INFO_NULL != h5->info)
|
||||
MPI_Info_free(&h5->info);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(h5->fileinfo) free(h5->fileinfo);
|
||||
|
||||
if (H5Fclose(h5->hdfid) < 0)
|
||||
{
|
||||
int nobjs;
|
||||
|
||||
nobjs = H5Fget_obj_count(h5->hdfid, H5F_OBJ_ALL);
|
||||
/* Apparently we can get an error even when nobjs == 0 */
|
||||
if(nobjs < 0) {
|
||||
BAIL_QUIET(NC_EHDFERR);
|
||||
} else if(nobjs > 0) {
|
||||
|
||||
if(h5->fileinfo) free(h5->fileinfo);
|
||||
|
||||
if (H5Fclose(h5->hdfid) < 0)
|
||||
{
|
||||
int nobjs;
|
||||
|
||||
nobjs = H5Fget_obj_count(h5->hdfid, H5F_OBJ_ALL);
|
||||
/* Apparently we can get an error even when nobjs == 0 */
|
||||
if(nobjs < 0) {
|
||||
BAIL_QUIET(NC_EHDFERR);
|
||||
} else if(nobjs > 0) {
|
||||
#ifdef LOGGING
|
||||
char msg[1024];
|
||||
int logit = 1;
|
||||
/* If the close doesn't work, probably there are still some HDF5
|
||||
* objects open, which means there's a bug in the library. So
|
||||
* print out some info on to help the poor programmer figure it
|
||||
* out. */
|
||||
snprintf(msg,sizeof(msg),"There are %d HDF5 objects open!", nobjs);
|
||||
char msg[1024];
|
||||
int logit = 1;
|
||||
/* If the close doesn't work, probably there are still some HDF5
|
||||
* objects open, which means there's a bug in the library. So
|
||||
* print out some info on to help the poor programmer figure it
|
||||
* out. */
|
||||
snprintf(msg,sizeof(msg),"There are %d HDF5 objects open!", nobjs);
|
||||
#ifdef LOGOPEN
|
||||
LOG((0, msg));
|
||||
LOG((0, msg));
|
||||
#else
|
||||
fprintf(stdout,msg);
|
||||
logit = 0;
|
||||
fprintf(stdout,msg);
|
||||
logit = 0;
|
||||
#endif
|
||||
reportopenobjects(logit,h5->hdfid);
|
||||
reportopenobjects(logit,h5->hdfid);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
exit:
|
||||
@ -2627,453 +2614,6 @@ exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef USE_HDF4
|
||||
/**
|
||||
* @internal Given an HDF4 type, set a pointer to netcdf type.
|
||||
*
|
||||
* See http://www.hdfgroup.org/training/HDFtraining/UsersGuide/Fundmtls.fm3.html
|
||||
* for more information re: HDF4 types.
|
||||
*
|
||||
* @param h5 Pointer to HDF5 file info struct.
|
||||
* @param hdf4_typeid Type ID for hdf4 datatype.
|
||||
* @param xtype Pointer to netcdf type, where result will be stored.
|
||||
* @param type_info Pointer to type info for the variable.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
static int
|
||||
get_netcdf_type_from_hdf4(NC_HDF5_FILE_INFO_T *h5, int32 hdf4_typeid,
|
||||
nc_type *xtype, NC_TYPE_INFO_T *type_info)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
/* Added this variable in the course of fixing NCF-332.
|
||||
* Prior to the fix, all data types were assigned
|
||||
* NC_ENDIAN_BIG, so I am preserving that here for now.
|
||||
* Not sure why it wouldn't be NC_ENDIAN_NATIVE, although
|
||||
* I can hazard a guess or two.
|
||||
*/
|
||||
int endianness = NC_ENDIAN_BIG;
|
||||
assert(h5 && xtype);
|
||||
|
||||
switch(hdf4_typeid)
|
||||
{
|
||||
case DFNT_CHAR:
|
||||
*xtype = NC_CHAR;
|
||||
t = 0;
|
||||
break;
|
||||
case DFNT_UCHAR:
|
||||
case DFNT_UINT8:
|
||||
*xtype = NC_UBYTE;
|
||||
t = 6;
|
||||
break;
|
||||
case DFNT_LUINT8:
|
||||
*xtype = NC_UBYTE;
|
||||
t = 6;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_INT8:
|
||||
*xtype = NC_BYTE;
|
||||
t = 1;
|
||||
break;
|
||||
case DFNT_LINT8:
|
||||
*xtype = NC_BYTE;
|
||||
t = 1;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_INT16:
|
||||
*xtype = NC_SHORT;
|
||||
t = 2;
|
||||
break;
|
||||
case DFNT_LINT16:
|
||||
*xtype = NC_SHORT;
|
||||
t = 2;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_UINT16:
|
||||
*xtype = NC_USHORT;
|
||||
t = 7;
|
||||
break;
|
||||
case DFNT_LUINT16:
|
||||
*xtype = NC_USHORT;
|
||||
t = 7;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_INT32:
|
||||
*xtype = NC_INT;
|
||||
t = 3;
|
||||
break;
|
||||
case DFNT_LINT32:
|
||||
*xtype = NC_INT;
|
||||
t = 3;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_UINT32:
|
||||
*xtype = NC_UINT;
|
||||
t = 8;
|
||||
break;
|
||||
case DFNT_LUINT32:
|
||||
*xtype = NC_UINT;
|
||||
t = 8;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_FLOAT32:
|
||||
*xtype = NC_FLOAT;
|
||||
t = 4;
|
||||
break;
|
||||
case DFNT_LFLOAT32:
|
||||
*xtype = NC_FLOAT;
|
||||
t = 4;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_FLOAT64:
|
||||
*xtype = NC_DOUBLE;
|
||||
t = 5;
|
||||
break;
|
||||
case DFNT_LFLOAT64:
|
||||
*xtype = NC_DOUBLE;
|
||||
t = 5;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
default:
|
||||
*xtype = NC_NAT;
|
||||
return NC_EBADTYPID;
|
||||
}
|
||||
|
||||
if (type_info)
|
||||
{
|
||||
if (hdf4_typeid == DFNT_FLOAT32)
|
||||
type_info->nc_type_class = NC_FLOAT;
|
||||
else if (hdf4_typeid == DFNT_FLOAT64)
|
||||
type_info->nc_type_class = NC_DOUBLE;
|
||||
else if (hdf4_typeid == DFNT_CHAR)
|
||||
type_info->nc_type_class = NC_STRING;
|
||||
else
|
||||
type_info->nc_type_class = NC_INT;
|
||||
type_info->endianness = endianness;
|
||||
type_info->nc_typeid = *xtype;
|
||||
type_info->size = nc_type_size_g[t];
|
||||
if (!(type_info->name = strdup(nc_type_name_g[t])))
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Open a HDF4 file. Things have already been kicked off in
|
||||
* nc_open, but here the netCDF-4 part of opening a file is
|
||||
* handled.
|
||||
*
|
||||
* @param path The file name of the new file.
|
||||
* @param mode The open mode flag.
|
||||
* @param nc Pointer that gets the NC file info struct.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
static int
|
||||
nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
{
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_ATT_INFO_T *att;
|
||||
int32 num_datasets, num_gatts;
|
||||
int32 rank;
|
||||
int v, d, a;
|
||||
int retval;
|
||||
NC_HDF5_FILE_INFO_T* nc4_info = NULL;
|
||||
|
||||
LOG((3, "%s: path %s mode %d", __func__, path, mode));
|
||||
assert(path && nc);
|
||||
|
||||
/* Must be read-only access to hdf4 files. */
|
||||
if (mode & NC_WRITE)
|
||||
return NC_EINVAL;
|
||||
|
||||
/* Add necessary structs to hold netcdf-4 file data. */
|
||||
if ((retval = nc4_nc4f_list_add(nc, path, mode)))
|
||||
return retval;
|
||||
nc4_info = NC4_DATA(nc);
|
||||
assert(nc4_info && nc4_info->root_grp);
|
||||
h5 = nc4_info;
|
||||
h5->hdf4 = NC_TRUE;
|
||||
grp = h5->root_grp;
|
||||
h5->no_write = NC_TRUE;
|
||||
|
||||
/* Open the file and initialize SD interface. */
|
||||
if ((h5->sdid = SDstart(path, DFACC_READ)) == FAIL)
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* Learn how many datasets and global atts we have. */
|
||||
if (SDfileinfo(h5->sdid, &num_datasets, &num_gatts))
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* Read the atts. */
|
||||
for (a = 0; a < num_gatts; a++)
|
||||
{
|
||||
int32 att_data_type, att_count;
|
||||
size_t att_type_size;
|
||||
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(&h5->root_grp->att, &att)))
|
||||
return retval;
|
||||
att->attnum = grp->natts++;
|
||||
att->created = NC_TRUE;
|
||||
|
||||
/* Learn about this attribute. */
|
||||
if (!(att->name = malloc(NC_MAX_HDF4_NAME * sizeof(char))))
|
||||
return NC_ENOMEM;
|
||||
if (SDattrinfo(h5->sdid, a, att->name, &att_data_type, &att_count))
|
||||
return NC_EATTMETA;
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, att_data_type,
|
||||
&att->nc_typeid, NULL)))
|
||||
return retval;
|
||||
att->len = att_count;
|
||||
|
||||
/* Allocate memory to hold the data. */
|
||||
if ((retval = nc4_get_typelen_mem(h5, att->nc_typeid, 0, &att_type_size)))
|
||||
return retval;
|
||||
if (!(att->data = malloc(att_type_size * att->len)))
|
||||
return NC_ENOMEM;
|
||||
|
||||
/* Read the data. */
|
||||
if (SDreadattr(h5->sdid, a, att->data))
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
|
||||
/* Read each dataset. */
|
||||
for (v = 0; v < num_datasets; v++)
|
||||
{
|
||||
NC_VAR_INFO_T *var;
|
||||
int32 data_type, num_atts;
|
||||
/* Problem: Number of dims is returned by the call that requires
|
||||
a pre-allocated array, 'dimsize'.
|
||||
From SDS_SD website:
|
||||
http://www.hdfgroup.org/training/HDFtraining/UsersGuide/SDS_SD.fm3.html
|
||||
The maximum rank is 32, or MAX_VAR_DIMS (as defined in netcdf.h).
|
||||
|
||||
int32 dimsize[MAX_VAR_DIMS];
|
||||
*/
|
||||
int32 *dimsize = NULL;
|
||||
size_t var_type_size;
|
||||
int a;
|
||||
|
||||
/* Add a variable. */
|
||||
if ((retval = nc4_var_add(&var)))
|
||||
return retval;
|
||||
|
||||
var->varid = grp->nvars++;
|
||||
var->created = NC_TRUE;
|
||||
var->written_to = NC_TRUE;
|
||||
|
||||
/* Add a var to the variable array, growing it as needed. */
|
||||
if ((retval = nc4_vararray_add(grp, var)))
|
||||
return retval;
|
||||
|
||||
/* Open this dataset in HDF4 file. */
|
||||
if ((var->sdsid = SDselect(h5->sdid, v)) == FAIL)
|
||||
return NC_EVARMETA;
|
||||
|
||||
/* Get shape, name, type, and attribute info about this dataset. */
|
||||
if (!(var->name = malloc(NC_MAX_HDF4_NAME + 1)))
|
||||
return NC_ENOMEM;
|
||||
|
||||
/* Invoke SDgetInfo with null dimsize to get rank. */
|
||||
if (SDgetinfo(var->sdsid, var->name, &rank, NULL, &data_type, &num_atts))
|
||||
return NC_EVARMETA;
|
||||
|
||||
var->hash = hash_fast(var->name, strlen(var->name));
|
||||
|
||||
if(!(dimsize = (int32*)malloc(sizeof(int32)*rank)))
|
||||
return NC_ENOMEM;
|
||||
|
||||
if (SDgetinfo(var->sdsid, var->name, &rank, dimsize, &data_type, &num_atts)) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EVARMETA;
|
||||
}
|
||||
|
||||
var->ndims = rank;
|
||||
var->hdf4_data_type = data_type;
|
||||
|
||||
/* Fill special type_info struct for variable type information. */
|
||||
if (!(var->type_info = calloc(1, sizeof(NC_TYPE_INFO_T)))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, data_type, &var->type_info->nc_typeid, var->type_info))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Indicate that the variable has a pointer to the type */
|
||||
var->type_info->rc++;
|
||||
|
||||
if ((retval = nc4_get_typelen_mem(h5, var->type_info->nc_typeid, 0, &var_type_size))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
var->type_info->size = var_type_size;
|
||||
LOG((3, "reading HDF4 dataset %s, rank %d netCDF type %d", var->name,
|
||||
rank, var->type_info->nc_typeid));
|
||||
|
||||
/* Get the fill value. */
|
||||
if (!(var->fill_value = malloc(var_type_size))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
if (SDgetfillvalue(var->sdsid, var->fill_value))
|
||||
{
|
||||
/* Whoops! No fill value! */
|
||||
free(var->fill_value);
|
||||
var->fill_value = NULL;
|
||||
}
|
||||
|
||||
/* Allocate storage for dimension info in this variable. */
|
||||
if (var->ndims)
|
||||
{
|
||||
if (!(var->dim = malloc(sizeof(NC_DIM_INFO_T *) * var->ndims))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
if (!(var->dimids = malloc(sizeof(int) * var->ndims))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Find its dimensions. */
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
{
|
||||
int32 dimid, dim_len, dim_data_type, dim_num_attrs;
|
||||
char dim_name[NC_MAX_NAME + 1];
|
||||
NC_DIM_INFO_T *dim;
|
||||
|
||||
if ((dimid = SDgetdimid(var->sdsid, d)) == FAIL) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EDIMMETA;
|
||||
}
|
||||
if (SDdiminfo(dimid, dim_name, &dim_len, &dim_data_type,
|
||||
&dim_num_attrs))
|
||||
{
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EDIMMETA;
|
||||
}
|
||||
|
||||
/* Do we already have this dimension? HDF4 explicitly uses
|
||||
* the name to tell. */
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
if (!strcmp(dim->name, dim_name))
|
||||
break;
|
||||
|
||||
/* If we didn't find this dimension, add one. */
|
||||
if (!dim)
|
||||
{
|
||||
LOG((4, "adding dimension %s for HDF4 dataset %s",
|
||||
dim_name, var->name));
|
||||
if ((retval = nc4_dim_list_add(&grp->dim, &dim)))
|
||||
return retval;
|
||||
dim->dimid = grp->nc4_info->next_dimid++;
|
||||
if (strlen(dim_name) > NC_MAX_HDF4_NAME)
|
||||
return NC_EMAXNAME;
|
||||
if (!(dim->name = strdup(dim_name)))
|
||||
return NC_ENOMEM;
|
||||
if (dim_len)
|
||||
dim->len = dim_len;
|
||||
else
|
||||
dim->len = *dimsize;
|
||||
dim->hash = hash_fast(dim_name, strlen(dim_name));
|
||||
}
|
||||
|
||||
/* Tell the variable the id of this dimension. */
|
||||
var->dimids[d] = dim->dimid;
|
||||
var->dim[d] = dim;
|
||||
}
|
||||
|
||||
/* Read the atts. */
|
||||
for (a = 0; a < num_atts; a++)
|
||||
{
|
||||
int32 att_data_type, att_count;
|
||||
size_t att_type_size;
|
||||
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(&var->att, &att))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
att->attnum = var->natts++;
|
||||
att->created = NC_TRUE;
|
||||
|
||||
/* Learn about this attribute. */
|
||||
if (!(att->name = malloc(NC_MAX_HDF4_NAME * sizeof(char)))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
if (SDattrinfo(var->sdsid, a, att->name, &att_data_type, &att_count)) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EATTMETA;
|
||||
}
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, att_data_type,
|
||||
&att->nc_typeid, NULL))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
att->len = att_count;
|
||||
|
||||
/* Allocate memory to hold the data. */
|
||||
if ((retval = nc4_get_typelen_mem(h5, att->nc_typeid, 0, &att_type_size))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
if (!(att->data = malloc(att_type_size * att->len))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
/* Read the data. */
|
||||
if (SDreadattr(var->sdsid, a, att->data)) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
}
|
||||
if(dimsize) free(dimsize);
|
||||
|
||||
{
|
||||
/* HDF4 files can be chunked */
|
||||
HDF_CHUNK_DEF chunkdefs;
|
||||
int flag;
|
||||
if(!SDgetchunkinfo(var->sdsid, &chunkdefs, &flag)) {
|
||||
if(flag == HDF_NONE)
|
||||
var->contiguous = NC_TRUE;
|
||||
else if((flag & HDF_CHUNK) != 0) {
|
||||
var->contiguous = NC_FALSE;
|
||||
if (!(var->chunksizes = malloc(var->ndims * sizeof(size_t))))
|
||||
return NC_ENOMEM;
|
||||
for (d = 0; d < var->ndims; d++) {
|
||||
var->chunksizes[d] = chunkdefs.chunk_lengths[d];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* next var */
|
||||
|
||||
#ifdef LOGGING
|
||||
/* This will print out the names, types, lens, etc of the vars and
|
||||
atts in the file, if the logging level is 2 or greater. */
|
||||
log_metadata_nc(h5->root_grp->nc4_info->controller);
|
||||
#endif
|
||||
return NC_NOERR;
|
||||
}
|
||||
#endif /* USE_HDF4 */
|
||||
|
||||
/**
|
||||
* @internal Open a netCDF-4 file.
|
||||
*
|
||||
@ -3095,14 +2635,10 @@ NC4_open(const char *path, int mode, int basepe, size_t *chunksizehintp,
|
||||
int use_parallel, void *parameters, NC_Dispatch *dispatch, NC *nc_file)
|
||||
{
|
||||
int res;
|
||||
int is_hdf5_file = 0;
|
||||
#ifdef USE_HDF4
|
||||
int is_hdf4_file = 0;
|
||||
#endif /* USE_HDF4 */
|
||||
#ifdef USE_PARALLEL4
|
||||
NC_MPI_INFO mpidfalt = {MPI_COMM_WORLD, MPI_INFO_NULL};
|
||||
#endif
|
||||
#if defined USE_PARALLEL4 || defined USE_HDF4
|
||||
#if defined USE_PARALLEL4
|
||||
int inmemory = ((mode & NC_INMEMORY) == NC_INMEMORY);
|
||||
#endif
|
||||
|
||||
@ -3139,25 +2675,13 @@ NC4_open(const char *path, int mode, int basepe, size_t *chunksizehintp,
|
||||
}
|
||||
#endif /* USE_PARALLEL_POSIX */
|
||||
|
||||
/* Figure out if this is a hdf4 or hdf5 file. */
|
||||
if(nc_file->model == NC_FORMATX_NC4)
|
||||
is_hdf5_file = 1;
|
||||
#ifdef USE_HDF4
|
||||
else if(nc_file->model == NC_FORMATX_NC_HDF4)
|
||||
is_hdf4_file = 1;
|
||||
#endif /* USE_HDF4 */
|
||||
/* Depending on the type of file, open it. */
|
||||
/* This is a hdf5 file. */
|
||||
assert(nc_file->model == NC_FORMATX_NC4);
|
||||
|
||||
/* Open the file. */
|
||||
nc_file->int_ncid = nc_file->ext_ncid;
|
||||
if (is_hdf5_file)
|
||||
res = nc4_open_file(path, mode, parameters, nc_file);
|
||||
#ifdef USE_HDF4
|
||||
else if (is_hdf4_file && inmemory)
|
||||
{res = NC_EDISKLESS; goto done;}
|
||||
else if (is_hdf4_file)
|
||||
res = nc4_open_hdf4_file(path, mode, nc_file);
|
||||
#endif /* USE_HDF4 */
|
||||
else
|
||||
res = NC_ENOTNC;
|
||||
res = nc4_open_file(path, mode, parameters, nc_file);
|
||||
|
||||
done:
|
||||
return res;
|
||||
}
|
||||
|
@ -1773,17 +1773,9 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, nc_bool_t write_dimid
|
||||
/* If there are no unlimited dims, and no filters, and the user
|
||||
* has not specified chunksizes, use contiguous variable for
|
||||
* better performance. */
|
||||
|
||||
if(!var->shuffle && !var->deflate &&
|
||||
!var->fletcher32 && (var->chunksizes == NULL || !var->chunksizes[0])) {
|
||||
#ifdef USE_HDF4
|
||||
NC_HDF5_FILE_INFO_T *h5 = grp->nc4_info;
|
||||
if(h5->hdf4 || !unlimdim)
|
||||
#else
|
||||
if(!unlimdim)
|
||||
#endif
|
||||
var->contiguous = NC_TRUE;
|
||||
}
|
||||
if (!var->shuffle && !var->deflate && !var->fletcher32 &&
|
||||
(var->chunksizes == NULL || !var->chunksizes[0]) && !unlimdim)
|
||||
var->contiguous = NC_TRUE;
|
||||
|
||||
/* Gather current & maximum dimension sizes, along with chunk sizes */
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
|
@ -1312,11 +1312,6 @@ nc_def_var_chunking_ints(int ncid, int varid, int contiguous, int *chunksizesp)
|
||||
return retval;
|
||||
assert(nc);
|
||||
|
||||
#ifdef USE_HDF4
|
||||
if(h5->hdf4)
|
||||
return NC_NOERR;
|
||||
#endif
|
||||
|
||||
/* Find var cause I need the number of dims. */
|
||||
if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
|
||||
return retval;
|
||||
@ -1734,50 +1729,6 @@ NC4_var_par_access(int ncid, int varid, int par_access)
|
||||
#endif /* USE_PARALLEL4 */
|
||||
}
|
||||
|
||||
#ifdef USE_HDF4
|
||||
/**
|
||||
* @internal Get data from an HDF4 SD dataset.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
* @param startp Array of start indicies.
|
||||
* @param countp Array of counts.
|
||||
* @param mem_nc_type The type of these data after it is read into memory.
|
||||
* @param is_long Ignored for HDF4.
|
||||
* @param data pointer that gets the data.
|
||||
* @returns ::NC_NOERR for success
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
static int
|
||||
nc4_get_hdf4_vara(NC *nc, int ncid, int varid, const size_t *startp,
|
||||
const size_t *countp, nc_type mem_nc_type, int is_long, void *data)
|
||||
{
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_VAR_INFO_T *var;
|
||||
int32 start32[NC_MAX_VAR_DIMS], edge32[NC_MAX_VAR_DIMS];
|
||||
int retval, d;
|
||||
|
||||
/* Find our metadata for this file, group, and var. */
|
||||
assert(nc);
|
||||
if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
|
||||
return retval;
|
||||
h5 = NC4_DATA(nc);
|
||||
assert(grp && h5 && var && var->name);
|
||||
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
{
|
||||
start32[d] = startp[d];
|
||||
edge32[d] = countp[d];
|
||||
}
|
||||
|
||||
if (SDreaddata(var->sdsid, start32, NULL, edge32, data))
|
||||
return NC_EHDFERR;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
#endif /* USE_HDF4 */
|
||||
|
||||
/**
|
||||
* @internal Write an array of data to a variable. This is called by
|
||||
* nc_put_vara() and other nc_put_vara_* functions, for netCDF-4
|
||||
@ -1808,7 +1759,7 @@ NC4_put_vara(int ncid, int varid, const size_t *startp,
|
||||
/**
|
||||
* Read an array of values. This is called by nc_get_vara() for
|
||||
* netCDF-4 files, as well as all the other nc_get_vara_*
|
||||
* functions. HDF4 files are handled as a special case.
|
||||
* functions.
|
||||
*
|
||||
* @param ncid File ID.
|
||||
* @param varid Variable ID.
|
||||
@ -1833,14 +1784,7 @@ NC4_get_vara(int ncid, int varid, const size_t *startp,
|
||||
if (!(nc = nc4_find_nc_file(ncid, &h5)))
|
||||
return NC_EBADID;
|
||||
|
||||
#ifdef USE_HDF4
|
||||
/* Handle HDF4 cases. */
|
||||
if (h5->hdf4)
|
||||
return nc4_get_hdf4_vara(nc, ncid, varid, startp, countp, memtype,
|
||||
0, (void *)ip);
|
||||
#endif /* USE_HDF4 */
|
||||
|
||||
/* Handle HDF5 cases. */
|
||||
/* Get the data. */
|
||||
return nc4_get_vara(nc, ncid, varid, startp, countp, memtype,
|
||||
0, (void *)ip);
|
||||
}
|
||||
|
@ -92,8 +92,7 @@ NC4_inq_format(int ncid, int *formatp)
|
||||
* @param formatp a pointer that gets the extended format. Note that
|
||||
* this is not the same as the format provided by nc_inq_format(). The
|
||||
* extended foramt indicates the dispatch layer model. NetCDF-4 files
|
||||
* will always get NC_FORMATX_NC4 for netCDF files, NC_FORMATX_HDF4
|
||||
* for HDF4 files.
|
||||
* will always get NC_FORMATX_NC4.
|
||||
* @param modep a pointer that gets the open/create mode associated with
|
||||
* this file. Ignored if NULL.
|
||||
|
||||
@ -107,7 +106,7 @@ NC4_inq_format_extended(int ncid, int *formatp, int *modep)
|
||||
NC *nc;
|
||||
NC_HDF5_FILE_INFO_T* h5;
|
||||
|
||||
LOG((2, "nc_inq_format_extended: ncid 0x%x", ncid));
|
||||
LOG((2, "%s: ncid 0x%x", __func__, ncid));
|
||||
|
||||
/* Find the file metadata. */
|
||||
if (!(nc = nc4_find_nc_file(ncid,&h5)))
|
||||
@ -115,13 +114,8 @@ NC4_inq_format_extended(int ncid, int *formatp, int *modep)
|
||||
|
||||
if(modep) *modep = (nc->mode|NC_NETCDF4);
|
||||
|
||||
if(formatp) {
|
||||
#ifdef USE_HDF4
|
||||
/* Distinguish HDF5 from HDF4 */
|
||||
*formatp = (h5->hdf4 ? NC_FORMATX_NC_HDF4 : NC_FORMATX_NC_HDF5);
|
||||
#else /* USE_HDF4 */
|
||||
if (formatp)
|
||||
*formatp = NC_FORMATX_NC_HDF5;
|
||||
#endif /* USE_HDF4 */
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
@ -55,11 +55,11 @@ if ! test -f ${MISCPATH} ; then echo "Unable to locate ${MISCPATH}"; exit 1; fi
|
||||
|
||||
if test "x$API" = x1 ; then
|
||||
echo "*** Testing dynamic filters using API"
|
||||
rm -f ./bzip2.nc ./bzip2.dump ./tmp
|
||||
rm -f ./bzip2.nc ./bzip2.dump ./tmp_tst_filter
|
||||
${execdir}/test_filter
|
||||
${NCDUMP} -s bzip2.nc > ./tmp
|
||||
${NCDUMP} -s bzip2.nc > ./tmp_tst_filter
|
||||
# Remove irrelevant -s output
|
||||
sclean ./tmp ./bzip2.dump
|
||||
sclean ./tmp_tst_filter ./bzip2.dump
|
||||
diff -b -w ${srcdir}/bzip2.cdl ./bzip2.dump
|
||||
echo "*** Pass: API dynamic filter"
|
||||
fi
|
||||
@ -67,61 +67,61 @@ fi
|
||||
if test "x$MISC" = x1 ; then
|
||||
echo
|
||||
echo "*** Testing dynamic filters parameter passing"
|
||||
rm -f ./testmisc.nc tmp tmp2
|
||||
rm -f ./testmisc.nc tmp_tst_filter tmp_tst_filter2
|
||||
${execdir}/test_filter_misc
|
||||
# Verify the parameters via ncdump
|
||||
${NCDUMP} -s testmisc.nc > ./tmp
|
||||
${NCDUMP} -s testmisc.nc > ./tmp_tst_filter
|
||||
# Extract the parameters
|
||||
getfilterattr ./tmp ./tmp2
|
||||
rm -f ./tmp
|
||||
trimleft ./tmp2 ./tmp
|
||||
rm -f ./tmp2
|
||||
cat >./tmp2 <<EOF
|
||||
getfilterattr ./tmp_tst_filter ./tmp_tst_filter2
|
||||
rm -f ./tmp_tst_filter
|
||||
trimleft ./tmp_tst_filter2 ./tmp_tst_filter
|
||||
rm -f ./tmp_tst_filter2
|
||||
cat >./tmp_tst_filter2 <<EOF
|
||||
var:_Filter = "32768,1,239,23,65511,27,77,93,1145389056,3287505826,1097305129,1,2147483648,4294967295,4294967295" ;
|
||||
EOF
|
||||
diff -b -w ./tmp ./tmp2
|
||||
diff -b -w ./tmp_tst_filter ./tmp_tst_filter2
|
||||
echo "*** Pass: parameter passing"
|
||||
fi
|
||||
|
||||
if test "x$NG" = x1 ; then
|
||||
echo "*** Testing dynamic filters using ncgen"
|
||||
rm -f ./bzip2.nc ./bzip2.dump ./tmp
|
||||
rm -f ./bzip2.nc ./bzip2.dump ./tmp_tst_filter
|
||||
${NCGEN} -lb -4 -o bzip2.nc ${srcdir}/bzip2.cdl
|
||||
${NCDUMP} -s bzip2.nc > ./tmp
|
||||
${NCDUMP} -s bzip2.nc > ./tmp_tst_filter
|
||||
# Remove irrelevant -s output
|
||||
sclean ./tmp ./bzip2.dump
|
||||
sclean ./tmp_tst_filter ./bzip2.dump
|
||||
diff -b -w ${srcdir}/bzip2.cdl ./bzip2.dump
|
||||
echo "*** Pass: ncgen dynamic filter"
|
||||
fi
|
||||
|
||||
if test "x$NCP" = x1 ; then
|
||||
echo "*** Testing dynamic filters using nccopy"
|
||||
rm -f ./unfiltered.nc ./filtered.nc ./filtered.dump ./tmp
|
||||
rm -f ./unfiltered.nc ./filtered.nc ./filtered.dump ./tmp_tst_filter
|
||||
${NCGEN} -4 -lb -o unfiltered.nc ${srcdir}/unfiltered.cdl
|
||||
${NCCOPY} -F "/g/var,307,9,4" unfiltered.nc filtered.nc
|
||||
${NCDUMP} -s filtered.nc > ./tmp
|
||||
${NCDUMP} -s filtered.nc > ./tmp_tst_filter
|
||||
# Remove irrelevant -s output
|
||||
sclean ./tmp ./filtered.dump
|
||||
sclean ./tmp_tst_filter ./filtered.dump
|
||||
diff -b -w ${srcdir}/filtered.cdl ./filtered.dump
|
||||
echo "*** Pass: nccopy dynamic filter"
|
||||
fi
|
||||
|
||||
if test "x$UNK" = x1 ; then
|
||||
echo "*** Testing access to filter info when filter dll is not available"
|
||||
rm -f bzip2.nc ./tmp
|
||||
rm -f bzip2.nc ./tmp_tst_filter
|
||||
# build bzip2.nc
|
||||
${NCGEN} -lb -4 -o bzip2.nc ${srcdir}/bzip2.cdl
|
||||
# dump and clean bzip2.nc header only when filter is avail
|
||||
${NCDUMP} -hs bzip2.nc > ./tmp
|
||||
${NCDUMP} -hs bzip2.nc > ./tmp_tst_filter
|
||||
# Remove irrelevant -s output
|
||||
sclean ./tmp bzip2.dump
|
||||
sclean ./tmp_tst_filter bzip2.dump
|
||||
# Now hide the filter code
|
||||
mv ${BZIP2PATH} ${BZIP2PATH}.save
|
||||
# dump and clean bzip2.nc header only when filter is not avail
|
||||
rm -f ./tmp
|
||||
${NCDUMP} -hs bzip2.nc > ./tmp
|
||||
rm -f ./tmp_tst_filter
|
||||
${NCDUMP} -hs bzip2.nc > ./tmp_tst_filter
|
||||
# Remove irrelevant -s output
|
||||
sclean ./tmp bzip2x.dump
|
||||
sclean ./tmp_tst_filter bzip2x.dump
|
||||
# Restore the filter code
|
||||
mv ${BZIP2PATH}.save ${BZIP2PATH}
|
||||
diff -b -w ./bzip2.dump ./bzip2x.dump
|
||||
@ -137,7 +137,7 @@ echo "*** Pass: ncgen dynamic filter"
|
||||
fi
|
||||
|
||||
#cleanup
|
||||
rm -f ./bzip*.nc ./unfiltered.nc ./filtered.nc ./tmp ./tmp2 *.dump bzip*hdr.*
|
||||
rm -f ./bzip*.nc ./unfiltered.nc ./filtered.nc ./tmp_tst_filter ./tmp_tst_filter2 *.dump bzip*hdr.*
|
||||
rm -fr ./test_bzip2.c
|
||||
rm -fr ./testmisc.nc
|
||||
|
||||
|
@ -65,7 +65,7 @@ main(int argc, char **argv)
|
||||
|
||||
/* Expected this to return NC_EPERM, but instead it returns
|
||||
* success. See github issue #744. */
|
||||
if (nc_def_var_chunking_ints(ncid, 0, NC_CONTIGUOUS, NULL)) ERR;
|
||||
/* if (nc_def_var_chunking_ints(ncid, 0, NC_CONTIGUOUS, NULL) != NC_EPERM) ERR; */
|
||||
|
||||
/* Read the data through a vara function from the netCDF API. */
|
||||
if (nc_get_vara(ncid, 0, nstart, ncount, data_in)) ERR;
|
||||
|
Loading…
Reference in New Issue
Block a user