Merge pull request #868 from Unidata/gh849.wif

Pull #849 plus a note in the release notes.
This commit is contained in:
Ward Fisher 2018-02-16 14:30:14 -07:00 committed by GitHub
commit db41b2a653
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 2290 additions and 656 deletions

View File

@ -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)

View File

@ -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 \

View File

@ -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.

View File

@ -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

View File

@ -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
View 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 */

View File

@ -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);

View File

@ -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];

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

View File

@ -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()

View File

@ -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

View File

@ -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();

View File

@ -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;
}

View File

@ -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++)

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;