/* * Copyright 2005 University Corporation for Atmospheric Research/Unidata */ /* "$Id: nc4internal.h,v 1.70 2008/06/06 14:22:57 ed Exp $" */ #ifndef _NC4INTERNAL_ #define _NC4INTERNAL_ #include #include #include "error.h" #include #include #include #include #include "netcdf3.h" #include #ifdef USE_PARALLEL #include #else #define MPI_Info int #define MPI_Comm int #endif /* USE_PARALLEL */ #define FILE_ID_MASK (0xffff0000) #define GRP_ID_MASK (0x0000ffff) #define ID_SHIFT (16) typedef enum {GET, PUT} NC_PG_T; typedef enum {VAR, DIM, ATT} NC_OBJ_T; #define NC_GROUP_NAME "/" #define NC_DIM_INFO_NAME "_ncdim_info" #define NC_VAR_INFO_NAME "_ncvar_info" #define NC3_STRICT_ATT_NAME "_nc3_strict" #define NC_MAX_HDF5_NAME (NC_MAX_NAME + 10) #define NC_V2_ERR (-1) /* * limits of the external representation */ #define X_SCHAR_MIN (-128) #define X_SCHAR_MAX 127 #define X_UCHAR_MAX 255U #define X_SHORT_MIN (-32768) #define X_SHRT_MIN X_SHORT_MIN /* alias compatible with limits.h */ #define X_SHORT_MAX 32767 #define X_SHRT_MAX X_SHORT_MAX /* alias compatible with limits.h */ #define X_USHORT_MAX 65535U #define X_USHRT_MAX X_USHORT_MAX /* alias compatible with limits.h */ #define X_INT_MIN (-2147483647-1) #define X_INT_MAX 2147483647 #define X_LONG_MIN X_INT_MIN #define X_LONG_MAX X_INT_MAX #define X_UINT_MAX 4294967295U #define X_FLOAT_MAX 3.40282347e+38f #define X_FLOAT_MIN (-X_FLOAT_MAX) #define X_DOUBLE_MAX 1.7976931348623157e+308 #define X_DOUBLE_MIN (-X_DOUBLE_MAX) /* These have to do with creating chuncked datasets in HDF5. */ #define NC_HDF5_UNLIMITED_DIMSIZE (0) #define NC_HDF5_CHUNKSIZE_FACTOR (10) #define NC_HDF5_MIN_CHUNK_SIZE (2) #define NC_EMPTY_SCALE "NC_EMPTY_SCALE" /*#ifdef LOGGING #define malloc nc_malloc #define calloc nc_calloc #define free nc_free #endif*/ /* This is a struct to handle the dim metadata. */ typedef struct NC_DIM_INFO { char name[NC_MAX_NAME + 1]; int len; int dimid; int unlimited; int extended; struct NC_DIM_INFO *next; struct NC_DIM_INFO *prev; hid_t hdf_dimscaleid; char old_name[NC_MAX_NAME + 1]; /* only used to rename dim */ int dirty; struct NC_VAR_INFO *coord_var; /* The coord var, if it exists. */ } NC_DIM_INFO_T; typedef struct { char name[NC_MAX_NAME + 1]; int len; int id; } DIM_FILE_T; typedef struct NC_ATT_INFO { int len; char name[NC_MAX_NAME + 1]; struct NC_ATT_INFO *next; struct NC_ATT_INFO *prev; int dirty; int created; nc_type xtype; hid_t hdf_typeid; int attnum; void *data; nc_vlen_t *vldata; /* only used for vlen */ char **stdata; /* only for string type. */ int class; } NC_ATT_INFO_T; typedef struct var_file_infot_nc { char name[NC_MAX_NAME + 1]; int ndims; int dimids[NC_MAX_DIMS]; int varid; int nc_char; } NC_VAR_FILE_INFO_T; typedef struct hdf5_objid { unsigned long fileno[2]; /* file number */ haddr_t objno[2]; /* object number */ } HDF5_OBJID_T; /* This is a struct to handle the var metadata. */ typedef struct NC_VAR_INFO { char name[NC_MAX_NAME + 1]; int ndims; int dimids[NC_MAX_DIMS]; int varid; int natts; struct NC_VAR_INFO *next; struct NC_VAR_INFO *prev; int dirty; int created; int written_to; int *dimscale_attached; nc_type xtype; int class; hid_t hdf_typeid; hid_t hdf_datasetid; NC_ATT_INFO_T *att; int no_fill; void *fill_value; int chunksizes[NC_MAX_DIMS]; int contiguous; int parallel_access; int dimscale; HDF5_OBJID_T *dimscale_hdf5_objids; int deflate; int deflate_level; int shuffle; int fletcher32; int endianness; } NC_VAR_INFO_T; typedef struct NC_FIELD_INFO { struct NC_FIELD_INFO *next; struct NC_FIELD_INFO *prev; nc_type nctype; hid_t hdf_typeid; size_t offset; char name[NC_MAX_NAME + 1]; int fieldid; int ndims; int dim_size[NC_MAX_DIMS]; } NC_FIELD_INFO_T; typedef struct NC_ENUM_MEMBER_INFO { struct NC_ENUM_MEMBER_INFO *next; struct NC_ENUM_MEMBER_INFO *prev; char name[NC_MAX_NAME + 1]; void *value; } NC_ENUM_MEMBER_INFO_T; typedef struct NC_TYPE_INFO { struct NC_TYPE_INFO *next; struct NC_TYPE_INFO *prev; nc_type nc_typeid; hid_t hdf_typeid; size_t size; int committed; /* What the pig is, but the hen isn't, at breakfast. */ char name[NC_MAX_NAME + 1]; int class; /* NC_VLEN, NC_COMPOUND, NC_OPAQUE, or NC_ENUM */ int num_enum_members; NC_ENUM_MEMBER_INFO_T *enum_member; NC_FIELD_INFO_T *field; /* Used for compound types. */ int num_fields; nc_type base_nc_type; /* for VLEN only */ hid_t base_hdf_typeid; /* for VLEN only */ int endianness; } NC_TYPE_INFO_T; /* This holds information for one group. Groups reproduce with * parthenogenesis. */ typedef struct NC_GRP_INFO { struct NC_GRP_INFO *parent; struct NC_GRP_INFO *children; struct NC_GRP_INFO *next; /* points to siblings */ struct NC_GRP_INFO *prev; /* points to siblings */ NC_VAR_INFO_T *var; NC_DIM_INFO_T *dim; NC_ATT_INFO_T *att; int nvars; int ndims; int natts; struct NC_FILE_INFO *file; char name[NC_MAX_NAME + 1]; hid_t hdf_grpid; int nc_grpid; NC_TYPE_INFO_T *type; } NC_GRP_INFO_T; /* These constants apply to the cmode parameter in the * HDF5_FILE_INFO_T defined below. */ #define NC_CREAT 2 /* in create phase, cleared by ncendef */ #define NC_INDEF 8 /* in define mode, cleared by ncendef */ #define NC_NSYNC 0x10 /* synchronise numrecs on change */ #define NC_HSYNC 0x20 /* synchronise whole header on change */ #define NC_NDIRTY 0x40 /* numrecs has changed */ #define NC_HDIRTY 0x80 /* header info has changed */ /* This is the metadata we need to keep track of for each netcdf-4/HDF5 file. */ typedef struct { hid_t hdfid; int flags; int cmode; int nvars; int ndims; int natts; int parallel; /* true if file is open for parallel access */ int redef; char path[NC_MAX_NAME + 1]; int fill_mode; int no_write; /* true if nc_open has mode NC_NOWRITE. */ NC_GRP_INFO_T *root_grp; short next_nc_grpid; NC_TYPE_INFO_T *type; int next_typeid; int next_dimid; } NC_HDF5_FILE_INFO_T; /* In the nc_file array there will be one entry for each open file.*/ typedef struct NC_FILE_INFO { struct NC_FILE_INFO *next; struct NC_FILE_INFO *prev; /* There's an external ncid (ext_ncid) and an internal ncid * (int_ncid). The ext_ncid is the ncid returned to the user. If * the user has opened or created a netcdf-4 file, then the * ext_ncid is the same as the int_ncid. If he has opened or * created a netcdf-3 file ext_ncid (which the user sees) is * different from the int_ncid, which is the ncid returned by the * netcdf-3 layer, which insists on inventing it's own ncids, * regardless of what is already in use due to previously opened * netcdf-4 files. The ext_ncid contains the ncid for the root * group (i.e. group zero). */ int int_ncid; int ext_ncid; /* The nc4_info pointer will remain NULL for netcdf3 files, * otherwise it points to information about the netcdf-4 file. */ NC_HDF5_FILE_INFO_T *nc4_info; } NC_FILE_INFO_T; /* These functions only use the netcdf API calls, so they will work on both new format and old format files. */ /*int copy_dataset(int ncid_in, int ncid_out);*/ /* These functions convert beteen netcdf and HDF5 types. */ int nc4_get_typelen_mem(NC_HDF5_FILE_INFO_T *h5, nc_type xtype, int is_long, size_t *len); int nc4_convert_type(const void *src, void *dest, const nc_type src_type, const nc_type dest_type, const size_t len, int *range_error, const void *fill_value, int strict_nc3, int src_long, int dest_long); /* These functions do HDF5 things. */ int nc4_delete_hdf5_att(hid_t loc, const char *name); int nc4_open_var_grp(NC_GRP_INFO_T *grp, int varid, hid_t *dataset); int pg_var(NC_PG_T pg, NC_FILE_INFO_T *nc, int ncid, int varid, nc_type xtype, int is_long, void *ip); int nc4_pg_var1(NC_PG_T pg, NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *indexp, nc_type xtype, int is_long, void *ip); int nc4_pg_vara(NC_PG_T pg, NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *startp, const size_t *countp, nc_type xtype, int is_long, void *op); int nc4_pg_varm(NC_PG_T pg, NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, const ptrdiff_t *imapp, nc_type xtype, int is_long, void *op); int nc4_rec_match_types(NC_GRP_INFO_T *grp); int nc4_rec_match_dimscales(NC_GRP_INFO_T *grp); int nc4_rec_read_metadata(NC_GRP_INFO_T *grp); int nc4_rec_write_metadata(NC_GRP_INFO_T *grp); int nc4_enddef_netcdf4_file(NC_HDF5_FILE_INFO_T *h5); /* The following functions manipulate the in-memory linked list of metadata, without using HDF calls. */ int nc4_find_nc_grp_h5(int ncid, NC_FILE_INFO_T **nc, NC_GRP_INFO_T **grp, NC_HDF5_FILE_INFO_T **h5); int nc4_find_grp_h5(int ncid, NC_GRP_INFO_T **grp, NC_HDF5_FILE_INFO_T **h5); int nc4_find_nc4_grp(int ncid, NC_GRP_INFO_T **grp); NC_GRP_INFO_T *nc4_find_nc_grp(int ncid); NC_GRP_INFO_T *nc4_rec_find_grp(NC_GRP_INFO_T *start_grp, int target_nc_grpid); NC_FILE_INFO_T *nc4_find_nc_file(int ncid); int nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim); int nc4_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len); int nc4_find_type(NC_HDF5_FILE_INFO_T *h5, int typeid, NC_TYPE_INFO_T **type); NC_TYPE_INFO_T *nc4_rec_find_nc_type(NC_GRP_INFO_T *start_grp, hid_t target_nc_typeid); NC_TYPE_INFO_T *nc4_rec_find_hdf_type(NC_GRP_INFO_T *start_grp, hid_t target_hdf_typeid); int nc4_find_nc_att(int ncid, int varid, const char *name, int attnum, NC_ATT_INFO_T **att); int nc4_find_g_var_nc(NC_FILE_INFO_T *nc, int ncid, int varid, NC_GRP_INFO_T **grp, NC_VAR_INFO_T **var); int nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum, NC_ATT_INFO_T **att); /*int var_info_nc(NC_PG_T pg, hid_t dataset, NC_VAR_INFO_T *var_info);*/ /* These list functions add and delete vars, atts, and files. */ int nc4_file_list_add(int new_id); int nc4_nc4f_list_add(NC_FILE_INFO_T *nc, const char *path, int mode); int nc4_var_list_add(NC_VAR_INFO_T **list, NC_VAR_INFO_T **var); int nc4_dim_list_add(NC_DIM_INFO_T **list); int nc4_att_list_add(NC_ATT_INFO_T **list); int nc4_type_list_add(NC_TYPE_INFO_T **list, int typeid, size_t size, const char *name, nc_type class, nc_type base_nc_type); int nc4_field_list_add(NC_FIELD_INFO_T **list, int fieldid, char *name, size_t offset, hid_t field_hdf_typeid, nc_type xtype, int ndims, int *dim_sizesp); void nc4_file_list_del(NC_FILE_INFO_T *nc); void nc4_att_list_del(NC_ATT_INFO_T **list, NC_ATT_INFO_T *att); int nc4_grp_list_add(NC_GRP_INFO_T **list, int new_nc_grpid, NC_GRP_INFO_T *parent_grp, NC_FILE_INFO_T *nc, char *name, NC_GRP_INFO_T **grp); int nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp); int nc4_enum_member_add(NC_ENUM_MEMBER_INFO_T **list, size_t size, const char *name, const void *value); int NC_check_name(const char *name); /* Check and normalize names. */ int nc4_check_name(const char *name, char *norm_name); int nc4_normalize_name(const char *name, char *norm_name); /* Check for name collisions. */ int nc4_check_dup_name(NC_GRP_INFO_T *grp, char *norm_name); /* Insert and read one element into an already allocated vlen array * element (this is for F77). */ int nc_put_vlen_element(int ncid, int typeid, void *vlen_element, size_t len, void *data); int nc_get_vlen_element(int ncid, int typeid, void *vlen_element, size_t *len, void *data); /* This is only included in debug builds, and prints info about the metadata to stderr. */ #ifdef LOGGING int log_metadata_nc(NC_FILE_INFO_T *nc); #endif #endif /* _NETCDF4_ */