diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2c26f4598b..e659a15209 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -7,6 +7,9 @@ Recent releases include references to Jira issue identifiers for more informatio ## 4.3.1 Released TBD +* Corrected behavior of nc_inq_unlimdim and nv_inq_unlimdims to report dimids + in same order as nc_inq_dimids + * Addressed an issue reported by Jeff Whitaker regarding `nc_inq_nvars` returning an incorrect number of dimensions (this issue was introduced in 4.3.1-rc5). Integrated a test contributed by Jeff Whitaker. ### 4.3.1-rc5 Released 2013-12-06 diff --git a/include/nc4internal.h b/include/nc4internal.h index 12dd298641..731839649b 100644 --- a/include/nc4internal.h +++ b/include/nc4internal.h @@ -97,16 +97,22 @@ typedef enum {VAR, DIM, ATT} NC_OBJ_T; * as the netCDF dimid. */ #define NC_DIMID_ATT_NAME "_Netcdf4Dimid" +/* Generic doubly-linked list node */ +typedef struct NC_LIST_NODE +{ + void *next; + void *prev; +} NC_LIST_NODE_T; + /* This is a struct to handle the dim metadata. */ typedef struct NC_DIM_INFO { + NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */ char *name; size_t len; int dimid; int unlimited; int extended; - struct NC_DIM_INFO *next; - struct NC_DIM_INFO *prev; hid_t hdf_dimscaleid; HDF5_OBJID_T hdf5_objid; struct NC_VAR_INFO *coord_var; /* The coord var, if it exists. */ @@ -115,10 +121,9 @@ typedef struct NC_DIM_INFO typedef struct NC_ATT_INFO { + NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */ int len; char *name; - struct NC_ATT_INFO *next; - struct NC_ATT_INFO *prev; int dirty; int created; nc_type xtype; @@ -133,6 +138,7 @@ typedef struct NC_ATT_INFO /* This is a struct to handle the var metadata. */ typedef struct NC_VAR_INFO { + NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */ char *name; char *hdf5_name; /* used if different from name */ int ndims; @@ -140,8 +146,6 @@ typedef struct NC_VAR_INFO NC_DIM_INFO_T **dim; int varid; int natts; - struct NC_VAR_INFO *next; - struct NC_VAR_INFO *prev; int dirty; int created; /* Variable has already been created (_not_ that it was just created) */ int written_to; @@ -174,8 +178,7 @@ typedef struct NC_VAR_INFO typedef struct NC_FIELD_INFO { - struct NC_FIELD_INFO *next; - struct NC_FIELD_INFO *prev; + NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */ nc_type nctype; hid_t hdf_typeid; hid_t native_typeid; @@ -188,16 +191,14 @@ typedef struct NC_FIELD_INFO typedef struct NC_ENUM_MEMBER_INFO { - struct NC_ENUM_MEMBER_INFO *next; - struct NC_ENUM_MEMBER_INFO *prev; + NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */ char *name; void *value; } NC_ENUM_MEMBER_INFO_T; typedef struct NC_TYPE_INFO { - struct NC_TYPE_INFO *next; - struct NC_TYPE_INFO *prev; + NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */ nc_type nc_typeid; hid_t hdf_typeid; hid_t native_typeid; @@ -219,11 +220,10 @@ typedef struct NC_TYPE_INFO * parthenogenesis. */ typedef struct NC_GRP_INFO { + NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */ int nc_grpid; 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; @@ -291,16 +291,10 @@ int nc4_convert_type(const void *src, void *dest, /* These functions do HDF5 things. */ int rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid); int nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset); -int pg_var(NC_PG_T pg, NC *nc, int ncid, int varid, nc_type xtype, int is_long, void *ip); -int nc4_pg_var1(NC_PG_T pg, NC *nc, int ncid, int varid, const size_t *indexp, - nc_type xtype, int is_long, void *ip); int nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp, const size_t *countp, nc_type xtype, int is_long, void *op); int nc4_get_vara(NC *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 *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_dimscales(NC_GRP_INFO_T *grp); int nc4_rec_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grp, int *bad_coord_orderp); int nc4_rec_write_metadata(NC_GRP_INFO_T *grp, int bad_coord_order); @@ -341,9 +335,9 @@ int nc4_get_hdf_typeid(NC_HDF5_FILE_INFO_T *h5, nc_type xtype, int nc4_nc4f_list_add(NC *nc, const char *path, int mode); int nc4_var_list_add(NC_VAR_INFO_T **list, NC_VAR_INFO_T **var); int nc4_var_list_del(NC_VAR_INFO_T **list, NC_VAR_INFO_T *var); -int nc4_dim_list_add(NC_DIM_INFO_T **list); +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); +int nc4_att_list_add(NC_ATT_INFO_T **list, NC_ATT_INFO_T **att); int nc4_type_list_add(NC_TYPE_INFO_T **list, NC_TYPE_INFO_T **new_type); int nc4_field_list_add(NC_FIELD_INFO_T **list, int fieldid, const char *name, size_t offset, hid_t field_hdf_typeid, hid_t native_typeid, diff --git a/libsrc/memio.c b/libsrc/memio.c index 75b71ba445..49f36adfc4 100644 --- a/libsrc/memio.c +++ b/libsrc/memio.c @@ -103,7 +103,6 @@ memio_new(const char* path, int ioflags, off_t initialsize, ncio** nciopp, NCMEM int status = NC_NOERR; ncio* nciop = NULL; NCMEMIO* memio = NULL; - int openfd = -1; if(pagesize == 0) { @@ -156,15 +155,20 @@ memio_new(const char* path, int ioflags, off_t initialsize, ncio** nciopp, NCMEM memio->persist = fIsSet(ioflags,NC_WRITE); if(nciopp) *nciopp = nciop; + else { + free((char*)nciop->path); + free(nciop); + } if(memiop) *memiop = memio; + else free(memio); done: - if(openfd >= 0) close(openfd); return status; fail: if(nciop != NULL) { if(nciop->path != NULL) free((char*)nciop->path); + free(nciop); } goto done; } diff --git a/libsrc4/nc3stub.c b/libsrc4/nc3stub.c index 16d42facba..15fd4cdac3 100644 --- a/libsrc4/nc3stub.c +++ b/libsrc4/nc3stub.c @@ -294,11 +294,6 @@ nc3_inq_unlimdim(int ncid, int *unlimdimidp) {abort();} int nc3_show_metadata(int ncid) {abort();} -#ifdef IGNORE -int -nc3_delete_mp(const char * path, int basepe) {abort();} -#endif - int nc3_put_att_text(int ncid, int varid, const char *name, size_t len, const char *op) {abort();} diff --git a/libsrc4/nc4attr.c b/libsrc4/nc4attr.c index e80b66309b..99801c93be 100644 --- a/libsrc4/nc4attr.c +++ b/libsrc4/nc4attr.c @@ -234,7 +234,7 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name, attlist = &grp->att; else { - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) { attlist = &var->att; @@ -243,7 +243,7 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name, if (!var) return NC_ENOTVAR; } - for (att = *attlist; att; att = att->next) + for (att = *attlist; att; att = att->l.next) if (!strcmp(att->name, norm_name)) break; @@ -299,20 +299,16 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name, if (new_att) { LOG((3, "adding attribute %s to the list...", norm_name)); - if ((res = nc4_att_list_add(attlist))) + if ((res = nc4_att_list_add(attlist, &att))) BAIL (res); - /* Find this att's entry in the list (the last one). */ - for (att=*attlist; att->next; att=att->next) - ; } /* Now fill in the metadata. */ att->dirty++; if (att->name) free(att->name); - if (!(att->name = malloc((strlen(norm_name) + 1) * sizeof(char)))) + if (!(att->name = strdup(norm_name))) return NC_ENOMEM; - strcpy(att->name, norm_name); att->xtype = file_type; /* If this att has vlen or string data, release it before we lose the length value. */ @@ -333,8 +329,8 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name, } att->len = len; - if (att->prev) - att->attnum = att->prev->attnum + 1; + if (att->l.prev) + att->attnum = ((NC_ATT_INFO_T *)att->l.prev)->attnum + 1; else att->attnum = 0; if (type) @@ -415,7 +411,7 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name, /* Mark the var and all its atts as dirty, so they get * rewritten. */ var->dirty++; - for (varatt = var->att; varatt; varatt = varatt->next) + for (varatt = var->att; varatt; varatt = varatt->l.next) varatt->dirty++; } @@ -645,7 +641,7 @@ NC4_rename_att(int ncid, int varid, const char *name, } else { - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) { list = var->att; @@ -654,14 +650,14 @@ NC4_rename_att(int ncid, int varid, const char *name, if (!var) return NC_ENOTVAR; } - for (att = list; att; att = att->next) + for (att = list; att; att = att->l.next) if (!strncmp(att->name, norm_newname, NC_MAX_NAME)) return NC_ENAMEINUSE; /* Normalize name and find the attribute. */ if ((retval = nc4_normalize_name(name, norm_name))) return retval; - for (att = list; att; att = att->next) + for (att = list; att; att = att->l.next) if (!strncmp(att->name, norm_name, NC_MAX_NAME)) break; if (!att) @@ -758,7 +754,7 @@ NC4_del_att(int ncid, int varid, const char *name) } else { - for(var = grp->var; var; var = var->next) + for(var = grp->var; var; var = var->l.next) { if (var->varid == varid) { @@ -775,7 +771,7 @@ NC4_del_att(int ncid, int varid, const char *name) } /* Now find the attribute by name or number. */ - for (att = *attlist; att; att = att->next) + for (att = *attlist; att; att = att->l.next) if (!strcmp(att->name, name)) break; @@ -789,7 +785,7 @@ NC4_del_att(int ncid, int varid, const char *name) BAIL(NC_EATTMETA); /* Renumber all following attributes. */ - for (natt = att->next; natt; natt = natt->next) + for (natt = att->l.next; natt; natt = natt->l.next) natt->attnum--; /* Delete this attribute from this list. */ diff --git a/libsrc4/nc4dim.c b/libsrc4/nc4dim.c index bba1426074..222e78412f 100644 --- a/libsrc4/nc4dim.c +++ b/libsrc4/nc4dim.c @@ -48,7 +48,7 @@ NC4_inq_unlimdim(int ncid, int *unlimdimidp) *unlimdimidp = -1; for (g = grp; g && !found; g = g->parent) { - for (dim = g->dim; dim; dim = dim->next) + for (dim = g->dim; dim; dim = dim->l.next) { if (dim->unlimited) { @@ -98,7 +98,7 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp) { /* Only one limited dimenson for strict nc3. */ if (len == NC_UNLIMITED) - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) if (dim->unlimited) return NC_EUNLIMIT; @@ -123,26 +123,25 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp) return NC_EDIMSIZE; /* Make sure the name is not already in use. */ - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) if (!strncmp(dim->name, norm_name, NC_MAX_NAME)) return NC_ENAMEINUSE; /* Add a dimension to the list. The ID must come from the file * information, since dimids are visible in more than one group. */ - nc4_dim_list_add(&grp->dim); - grp->dim->dimid = grp->nc4_info->next_dimid++; + nc4_dim_list_add(&grp->dim, &dim); + dim->dimid = grp->nc4_info->next_dimid++; /* Initialize the metadata for this dimension. */ - if (!(grp->dim->name = malloc((strlen(norm_name) + 1) * sizeof(char)))) + if (!(dim->name = strdup(norm_name))) return NC_ENOMEM; - strcpy(grp->dim->name, norm_name); - grp->dim->len = len; + dim->len = len; if (len == NC_UNLIMITED) - grp->dim->unlimited++; + dim->unlimited++; /* Pass back the dimid. */ if (idp) - *idp = grp->dim->dimid; + *idp = dim->dimid; return retval; } @@ -180,7 +179,7 @@ NC4_inq_dimid(int ncid, const char *name, int *idp) /* Go through each dim and check for a name match. */ for (g = grp; g && !finished; g = g->parent) - for (dim = g->dim; dim; dim = dim->next) + for (dim = g->dim; dim; dim = dim->l.next) if (!strncmp(dim->name, norm_name, NC_MAX_NAME)) { if (idp) @@ -301,12 +300,12 @@ NC4_rename_dim(int ncid, int dimid, const char *name) return retval; /* Make sure the new name is not already in use in this group. */ - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) if (!strncmp(dim->name, norm_name, NC_MAX_NAME)) return NC_ENAMEINUSE; /* Find the dim. */ - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) if (dim->dimid == dimid) break; if (!dim) @@ -393,7 +392,7 @@ NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp) /* Get our dim info. */ assert(h5); { - for (dim=grp->dim; dim; dim=dim->next) + for (dim=grp->dim; dim; dim=dim->l.next) { if (dim->unlimited) { diff --git a/libsrc4/nc4file.c b/libsrc4/nc4file.c index 0f38c1bafe..eba0437aeb 100644 --- a/libsrc4/nc4file.c +++ b/libsrc4/nc4file.c @@ -42,17 +42,29 @@ extern int num_spaces; #define DIMENSION_LIST "DIMENSION_LIST" #define NAME "NAME" +/* Struct to track information about objects in a group, for nc4_rec_read_metadata() */ +typedef struct NC4_rec_read_metadata_obj_info +{ + hid_t oid; /* HDF5 object ID */ + char oname[NC_MAX_NAME + 1]; /* Name of object */ + H5G_stat_t statbuf; /* Information about the object */ + struct NC4_rec_read_metadata_obj_info *next; /* Pointer to next node in list */ +} NC4_rec_read_metadata_obj_info_t; + +/* User data struct for call to H5Literate() in nc4_rec_read_metadata() */ +/* Tracks the groups, named datatypes and datasets in the group, for later use */ +typedef struct NC4_rec_read_metadata_ud +{ + NC4_rec_read_metadata_obj_info_t *types_head, *types_tail; /* Pointers to head & tail of list of named datatypes */ + NC4_rec_read_metadata_obj_info_t *dsets_head, *dsets_tail; /* Pointers to head & tail of list of datasets */ + NC4_rec_read_metadata_obj_info_t *grps_head, *grps_tail; /* Pointers to head & tail of list of groups */ +} NC4_rec_read_metadata_ud_t; + /* Forward */ static int NC4_enddef(int ncid); static int nc4_rec_read_metadata(NC_GRP_INFO_T *grp); static int close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort); -#ifdef IGNORE -/* This extern points to the pointer that holds the list of open - * netCDF files. */ -extern NC *nc_file; -#endif - /* These are the default chunk cache sizes for HDF5 files created or * opened with netCDF-4. */ size_t nc4_chunk_cache_size = CHUNK_CACHE_SIZE; @@ -481,58 +493,64 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, const H5G_stat_t *statbuf, hsize_t scale_size, hsize_t max_scale_size, NC_DIM_INFO_T **dim) { - char dimscale_name_att[NC_MAX_NAME + 1] = ""; - htri_t attr_exists; + NC_DIM_INFO_T *new_dim; /* Dimension added to group */ + char dimscale_name_att[NC_MAX_NAME + 1] = ""; /* Dimscale name, for checking if dim without var */ + htri_t attr_exists = -1; /* Flag indicating hidden attribute exists */ + hid_t attid = -1; /* ID of hidden attribute (to store dim ID) */ + int dimscale_created = 0; /* Remember if a dimension was created (for error recovery) */ + int initial_grp_ndims = grp->ndims; /* Retain for error recovery */ + short initial_next_dimid = grp->nc4_info->next_dimid;/* Retain for error recovery */ int retval; /* Add a dimension for this scale. */ - if ((retval = nc4_dim_list_add(&grp->dim))) - return retval; - - /* Assign dimid and increment number of dimensions. */ - grp->dim->dimid = grp->nc4_info->next_dimid++; - grp->ndims++; + if ((retval = nc4_dim_list_add(&grp->dim, &new_dim))) + BAIL(retval); + dimscale_created++; /* Does this dataset have a hidden attribute that tells us its * dimid? If so, read it. */ if ((attr_exists = H5Aexists(datasetid, NC_DIMID_ATT_NAME)) < 0) - return NC_EHDFERR; + BAIL(NC_EHDFERR); if (attr_exists) { - hid_t attid; - if ((attid = H5Aopen_by_name(datasetid, ".", NC_DIMID_ATT_NAME, - H5P_DEFAULT, H5P_DEFAULT)) > 0) - { - if (H5Aread(attid, H5T_NATIVE_INT, &grp->dim->dimid) < 0) - { - H5Aclose(attid); - return NC_EHDFERR; - } - if (H5Aclose(attid) < 0) - return NC_EHDFERR; - } + H5P_DEFAULT, H5P_DEFAULT)) < 0) + BAIL(NC_EHDFERR); + + if (H5Aread(attid, H5T_NATIVE_INT, &new_dim->dimid) < 0) + BAIL(NC_EHDFERR); + + /* Check if scale's dimid should impact the group's next dimid */ + if (new_dim->dimid >= grp->nc4_info->next_dimid) + grp->nc4_info->next_dimid = new_dim->dimid + 1; + } + else + { + /* Assign dimid */ + new_dim->dimid = grp->nc4_info->next_dimid++; } - if (!(grp->dim->name = malloc((strlen(obj_name) + 1) * sizeof(char)))) - return NC_ENOMEM; - strcpy(grp->dim->name, obj_name); + /* Increment number of dimensions. */ + grp->ndims++; + + if (!(new_dim->name = strdup(obj_name))) + BAIL(NC_ENOMEM); if (SIZEOF_SIZE_T < 8 && scale_size > NC_MAX_UINT) { - grp->dim->len = NC_MAX_UINT; - grp->dim->too_long = 1; + new_dim->len = NC_MAX_UINT; + new_dim->too_long = 1; } else - grp->dim->len = scale_size; - grp->dim->hdf5_objid.fileno[0] = statbuf->fileno[0]; - grp->dim->hdf5_objid.fileno[1] = statbuf->fileno[1]; - grp->dim->hdf5_objid.objno[0] = statbuf->objno[0]; - grp->dim->hdf5_objid.objno[1] = statbuf->objno[1]; + new_dim->len = scale_size; + new_dim->hdf5_objid.fileno[0] = statbuf->fileno[0]; + new_dim->hdf5_objid.fileno[1] = statbuf->fileno[1]; + new_dim->hdf5_objid.objno[0] = statbuf->objno[0]; + new_dim->hdf5_objid.objno[1] = statbuf->objno[1]; /* If the dimscale has an unlimited dimension, then this dimension * is unlimited. */ if (max_scale_size == H5S_UNLIMITED) - grp->dim->unlimited++; + new_dim->unlimited++; /* If the scale name is set to DIM_WITHOUT_VARIABLE, then this is a * dimension, but not a variable. (If get_scale_name returns an @@ -542,24 +560,42 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, if (!strncmp(dimscale_name_att, DIM_WITHOUT_VARIABLE, strlen(DIM_WITHOUT_VARIABLE))) { - if (grp->dim->unlimited) + if (new_dim->unlimited) { size_t len = 0, *lenp = &len; - if ((retval = nc4_find_dim_len(grp, grp->dim->dimid, &lenp))) - return retval; - grp->dim->len = *lenp; + + if ((retval = nc4_find_dim_len(grp, new_dim->dimid, &lenp))) + BAIL(retval); + new_dim->len = *lenp; } /* Hold open the dataset, since the dimension doesn't have a coordinate variable */ - grp->dim->hdf_dimscaleid = datasetid; - H5Iinc_ref(grp->dim->hdf_dimscaleid); /* Increment number of objects using ID */ + new_dim->hdf_dimscaleid = datasetid; + H5Iinc_ref(new_dim->hdf_dimscaleid); /* Increment number of objects using ID */ } } /* Set the dimension created */ - *dim = grp->dim; + *dim = new_dim; - return NC_NOERR; +exit: + /* Close the hidden attribute, if it was opened (error, or no error) */ + if (attid > 0 && H5Aclose(attid) < 0) + BAIL2(NC_EHDFERR); + + /* On error, undo any dimscale creation */ + if (retval < 0 && dimscale_created) + { + /* Delete the dimension */ + if ((retval = nc4_dim_list_del(&grp->dim, new_dim))) + BAIL2(retval); + + /* Reset the group's information */ + grp->ndims = initial_grp_ndims; + grp->nc4_info->next_dimid = initial_next_dimid; + } + + return retval; } /* This function reads the hacked in coordinates attribute I use for @@ -586,7 +622,7 @@ read_coord_dimids(NC_VAR_INFO_T *var) /* Check that the number of points is the same as the number of dimensions * for the variable */ - if (npoints != var->ndims) ret++; + if (!ret && npoints != var->ndims) ret++; if (!ret && H5Aread(coord_attid, coord_att_typeid, var->dimids) < 0) ret++; LOG((4, "dimscale %s is multidimensional and has coords", var->name)); @@ -1172,14 +1208,12 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name) /* Add to the list for this new type, and get a local pointer to it. */ if ((retval = nc4_type_list_add(&grp->type, &type))) return retval; - assert(type); /* Remember info about this type. */ type->nc_typeid = grp->nc4_info->next_typeid++; type->size = type_size; - if (!(type->name = malloc((strlen(type_name) + 1) * sizeof(char)))) + if (!(type->name = strdup(type_name))) return NC_ENOMEM; - strcpy(type->name, type_name); type->class = ud_type_type; type->base_nc_type = base_nc_type; type->committed++; @@ -1347,9 +1381,6 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, if ((retval = nc4_var_list_add(&grp->var, &var))) return retval; - if(!var) - return NC_ENOMEM; - /* Fill in what we already know. */ var->hdf_datasetid = datasetid; H5Iinc_ref(var->hdf_datasetid); /* Increment number of objects using ID */ @@ -1592,16 +1623,13 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, strcmp(att_name, NC_DIMID_ATT_NAME)) { /* Add to the end of the list of atts for this var. */ - if ((retval = nc4_att_list_add(&var->att))) + if ((retval = nc4_att_list_add(&var->att, &att))) BAIL(retval); - for (att = var->att; att->next; att = att->next) - ; /* Fill in the information we know. */ att->attnum = var->natts++; - if (!(att->name = malloc((strlen(att_name) + 1) * sizeof(char)))) + if (!(att->name = strdup(att_name))) BAIL(NC_ENOMEM); - strcpy(att->name, att_name); /* Read the rest of the info about the att, * including its values. */ @@ -1665,8 +1693,11 @@ read_grp_atts(NC_GRP_INFO_T *grp) num_obj = H5Aget_num_attrs(grp->hdf_grpid); for (i = 0; i < num_obj; i++) { - if (attid > 0) - H5Aclose(attid); + /* Close an attribute from previous loop iteration */ + /* (Should be from 'continue' statement, below) */ + if (attid && H5Aclose(attid) < 0) + BAIL(NC_EHDFERR); + if ((attid = H5Aopen_idx(grp->hdf_grpid, (unsigned int)i)) < 0) BAIL(NC_EATTMETA); if (H5Aget_name(attid, NC_MAX_NAME + 1, obj_name) < 0) @@ -1682,10 +1713,8 @@ read_grp_atts(NC_GRP_INFO_T *grp) else { /* Add an att struct at the end of the list, and then go to it. */ - if ((retval = nc4_att_list_add(&grp->att))) + if ((retval = nc4_att_list_add(&grp->att, &att))) BAIL(retval); - for (att = grp->att; att->next; att = att->next) - ; /* Add the info about this attribute. */ max_len = strlen(obj_name) > NC_MAX_NAME ? NC_MAX_NAME : strlen(obj_name); @@ -1775,108 +1804,120 @@ read_dataset(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, return retval; } +static int +nc4_iter_list_add(NC4_rec_read_metadata_obj_info_t **head, + NC4_rec_read_metadata_obj_info_t **tail, + NC4_rec_read_metadata_obj_info_t *oinfo) +{ + if (*tail) + { + assert(*head); + (*tail)->next = oinfo; + *tail = oinfo; + } + else + { + assert(NULL == *head); + *head = *tail = oinfo; + } + + return (NC_NOERR); +} + static int nc4_rec_read_metadata_cb(hid_t grpid, const char *name, const H5L_info_t *info, void *_op_data) { - hid_t oid=-1; - H5G_stat_t statbuf; - char oname[NC_MAX_NAME + 1]; - NC_GRP_INFO_T *child_grp; - NC_GRP_INFO_T *grp = (NC_GRP_INFO_T *) (_op_data); - NC_HDF5_FILE_INFO_T *h5 = grp->nc4_info; - - /* Open this critter. */ - if ((oid = H5Oopen(grpid, name, H5P_DEFAULT)) < 0) - return H5_ITER_ERROR; + NC4_rec_read_metadata_ud_t *udata = (NC4_rec_read_metadata_ud_t *)_op_data; /* Pointer to user data for callback */ + NC4_rec_read_metadata_obj_info_t *oinfo; /* Pointer to info for object */ + int retval = H5_ITER_CONT; + + /* Allocate memory for the object's info */ + if (!(oinfo = calloc(1, sizeof(NC4_rec_read_metadata_obj_info_t)))) + return NC_ENOMEM; + + /* Open this critter. */ + if ((oinfo->oid = H5Oopen(grpid, name, H5P_DEFAULT)) < 0) + return H5_ITER_ERROR; - /* Get more info about the object.*/ - if (H5Gget_objinfo(oid, ".", 1, &statbuf) < 0) - return H5_ITER_ERROR; + /* Get info about the object.*/ + if (H5Gget_objinfo(oinfo->oid, ".", 1, &oinfo->statbuf) < 0) + return H5_ITER_ERROR; - strncpy(oname, name, NC_MAX_NAME); + strncpy(oinfo->oname, name, NC_MAX_NAME); - /* Deal with objects. */ - switch(statbuf.type) - { - case H5G_GROUP: - LOG((3, "found group %s", oname)); + /* Add object to list, for later */ + switch(oinfo->statbuf.type) + { + case H5G_GROUP: + LOG((3, "found group %s", oinfo->oname)); + if (nc4_iter_list_add(&udata->grps_head, &udata->grps_tail, oinfo)) + BAIL(H5_ITER_ERROR); + break; - /* Add group to file's hierarchy */ - if (nc4_grp_list_add(&(grp->children), h5->next_nc_grpid++, - grp, grp->nc4_info->controller, oname, &child_grp)) - return H5_ITER_ERROR; + case H5G_DATASET: + LOG((3, "found dataset %s", oinfo->oname)); + if (nc4_iter_list_add(&udata->dsets_head, &udata->dsets_tail, oinfo)) + BAIL(H5_ITER_ERROR); + break; - /* Recursively read the child group's metadata */ - if (nc4_rec_read_metadata(child_grp)) - return H5_ITER_ERROR; - break; + case H5G_TYPE: + LOG((3, "found datatype %s", oinfo->oname)); + if (nc4_iter_list_add(&udata->types_head, &udata->types_tail, oinfo)) + BAIL(H5_ITER_ERROR); + break; - case H5G_DATASET: - { - int retval = NC_NOERR; - - LOG((3, "found dataset %s", oname)); - - /* Learn all about this dataset, which may be a dimscale - * (i.e. dimension metadata), or real data. */ - if ((retval = read_dataset(grp, oid, oname, &statbuf))) - { - /* Allow NC_EBADTYPID to transparently skip over datasets - * which have a datatype that netCDF-4 doesn't undertand - * (currently), but break out of iteration for other - * errors. - */ - if(NC_EBADTYPID != retval) - return H5_ITER_ERROR; - } - } - break; + default: + LOG((0, "Unknown object class %d in %s!", oinfo->statbuf.type, __func__)); + BAIL(H5_ITER_ERROR); + } - case H5G_TYPE: - LOG((3, "found datatype %s", oname)); - if (read_type(grp, oid, oname)) - return H5_ITER_ERROR; - break; +exit: + if (retval) + { + if (oinfo) + { + if (oinfo->oid > 0 && H5Oclose(oinfo->oid) < 0) + BAIL2(H5_ITER_ERROR); + free(oinfo); + } + } - default: - LOG((0, "Unknown object class %d in %s!", statbuf.type, __func__)); - } - - /* Close the object */ - if (H5Oclose(oid) < 0) - return H5_ITER_ERROR; - - return (H5_ITER_CONT); + return (retval); } static int nc4_rec_read_metadata(NC_GRP_INFO_T *grp) { + NC4_rec_read_metadata_ud_t udata; /* User data for iteration */ + NC4_rec_read_metadata_obj_info_t *oinfo; /* Pointer to info for object */ hsize_t idx=0; - int retval; hid_t pid = 0; unsigned crt_order_flags = 0; H5_index_t iter_index; + int retval = NC_NOERR; /* everything worked! */ assert(grp && grp->name); LOG((3, "%s: grp->name %s", __func__, grp->name)); + /* Portably initialize user data for iteration */ + memset(&udata, 0, sizeof(udata)); + /* Open this HDF5 group and retain its grpid. It will remain open * with HDF5 until this file is nc_closed. */ if (!grp->hdf_grpid) { if (grp->parent) { - if ((grp->hdf_grpid = H5Gopen2(grp->parent->hdf_grpid, + if ((grp->hdf_grpid = H5Gopen2(grp->parent->hdf_grpid, grp->name, H5P_DEFAULT)) < 0) - return NC_EHDFERR; + BAIL(NC_EHDFERR); } else { if ((grp->hdf_grpid = H5Gopen2(grp->nc4_info->hdfid, "/", H5P_DEFAULT)) < 0) - return NC_EHDFERR; + BAIL(NC_EHDFERR); } } assert(grp->hdf_grpid > 0); @@ -1885,7 +1926,7 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp) pid = H5Gget_create_plist(grp->hdf_grpid); H5Pget_link_creation_order(pid, &crt_order_flags); if (H5Pclose(pid) < 0) - return NC_EHDFERR; + BAIL(NC_EHDFERR); /* Set the iteration index to use */ if (crt_order_flags & H5P_CRT_ORDER_TRACKED) @@ -1896,23 +1937,125 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp) /* Without creation ordering, file must be read-only. */ if (!h5->no_write) - return NC_ECANTWRITE; + BAIL(NC_ECANTWRITE); iter_index = H5_INDEX_NAME; } - /* Iterate over links in this group, processing all the objects - * and recursively handling the types encountered + /* Iterate over links in this group, building lists for the types, + * datasets and groups encountered */ if (H5Literate(grp->hdf_grpid, iter_index, H5_ITER_INC, &idx, - nc4_rec_read_metadata_cb, (void *)grp) < 0) - return NC_EHDFERR; + nc4_rec_read_metadata_cb, (void *)&udata) < 0) + BAIL(NC_EHDFERR); + + /* Process the types, datasets and groups found */ + /* (Make certain it's in this order, so that the types are available for + * future datasets & child groups) + */ + for (oinfo = udata.types_head; oinfo; oinfo = udata.types_head) + { + /* Process the named datatype */ + if ((retval = read_type(grp, oinfo->oid, oinfo->oname))) + BAIL(retval); + + /* Close the object */ + if (H5Oclose(oinfo->oid) < 0) + BAIL(NC_EHDFERR); + + /* Advance to next node, free current node */ + udata.types_head = oinfo->next; + free(oinfo); + } + for (oinfo = udata.dsets_head; oinfo; oinfo = udata.dsets_head) + { + /* Learn all about this dataset, which may be a dimscale + * (i.e. dimension metadata), or real data. */ + if ((retval = read_dataset(grp, oinfo->oid, oinfo->oname, &oinfo->statbuf))) + { + /* Allow NC_EBADTYPID to transparently skip over datasets + * which have a datatype that netCDF-4 doesn't undertand + * (currently), but break out of iteration for other + * errors. + */ + if(NC_EBADTYPID != retval) + BAIL(retval); + else + retval = NC_NOERR; + } + + /* Close the object */ + if (H5Oclose(oinfo->oid) < 0) + BAIL(NC_EHDFERR); + + /* Advance to next node, free current node */ + udata.dsets_head = oinfo->next; + free(oinfo); + } + for (oinfo = udata.grps_head; oinfo; oinfo = udata.grps_head) + { + NC_GRP_INFO_T *child_grp; + NC_HDF5_FILE_INFO_T *h5 = grp->nc4_info; + + /* Add group to file's hierarchy */ + if ((retval = nc4_grp_list_add(&(grp->children), h5->next_nc_grpid++, + grp, grp->nc4_info->controller, oinfo->oname, &child_grp))) + BAIL(retval); + + /* Recursively read the child group's metadata */ + if ((retval = nc4_rec_read_metadata(child_grp))) + BAIL(retval); + + /* Close the object */ + if (H5Oclose(oinfo->oid) < 0) + BAIL(NC_EHDFERR); + + /* Advance to next node, free current node */ + udata.grps_head = oinfo->next; + free(oinfo); + } /* Scan the group for global (i.e. group-level) attributes. */ if ((retval = read_grp_atts(grp))) - return retval; + BAIL(retval); - return NC_NOERR; /* everything worked! */ +exit: + /* Clean up local information on error, if anything remains */ + if (retval) + { + for (oinfo = udata.types_head; oinfo; oinfo = udata.types_head) + { + /* Close the object */ + if (H5Oclose(oinfo->oid) < 0) + BAIL(NC_EHDFERR); + + /* Advance to next node, free current node */ + udata.types_head = oinfo->next; + free(oinfo); + } + for (oinfo = udata.dsets_head; oinfo; oinfo = udata.dsets_head) + { + /* Close the object */ + if (H5Oclose(oinfo->oid) < 0) + BAIL(NC_EHDFERR); + + /* Advance to next node, free current node */ + udata.dsets_head = oinfo->next; + free(oinfo); + } + for (oinfo = udata.grps_head; oinfo; oinfo = udata.grps_head) + { + /* Close the object */ + if (H5Oclose(oinfo->oid) < 0) + BAIL(NC_EHDFERR); + + /* Advance to next node, free current node */ + udata.grps_head = oinfo->next; + free(oinfo); + } + } + + return retval; } /* Open a netcdf-4 file. Things have already been kicked off in @@ -2137,7 +2280,6 @@ 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; - NC_VAR_INFO_T *var; int32 num_datasets, num_gatts; int32 rank; int v, d, a; @@ -2176,10 +2318,8 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc) 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))) + if ((retval = nc4_att_list_add(&h5->root_grp->att, &att))) return retval; - for (att = h5->root_grp->att; att->next; att = att->next) - ; att->attnum = grp->natts++; att->created++; @@ -2207,6 +2347,7 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc) /* 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'. @@ -2221,32 +2362,27 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc) int a; /* Add a variable to the end of the group's var list. */ - if ((retval = nc4_var_list_add(&grp->var, &var))) { + if ((retval = nc4_var_list_add(&grp->var, &var))) return retval; - } var->varid = grp->nvars++; var->created = 1; var->written_to = 1; /* Open this dataset in HDF4 file. */ - if ((var->sdsid = SDselect(h5->sdid, v)) == FAIL) { + 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))) { + 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; - if(!(dimsize = (int32*)malloc(sizeof(int32)*rank))) { + 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); @@ -2324,7 +2460,7 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc) /* Do we already have this dimension? HDF4 explicitly uses * the name to tell. */ - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) if (!strcmp(dim->name, dim_name)) break; @@ -2333,16 +2469,14 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc) { LOG((4, "adding dimension %s for HDF4 dataset %s", dim_name, var->name)); - if ((retval = nc4_dim_list_add(&grp->dim))) + if ((retval = nc4_dim_list_add(&grp->dim, &dim))) return retval; grp->ndims++; - dim = grp->dim; dim->dimid = grp->nc4_info->next_dimid++; if (strlen(dim_name) > NC_MAX_HDF4_NAME) return NC_EMAXNAME; - if (!(dim->name = malloc(NC_MAX_HDF4_NAME + 1))) + if (!(dim->name = strdup(dim_name))) return NC_ENOMEM; - strcpy(dim->name, dim_name); if (dim_len) dim->len = dim_len; else @@ -2360,12 +2494,10 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc) 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))) { + if ((retval = nc4_att_list_add(&var->att, &att))) { if(dimsize) free(dimsize); return retval; } - for (att = var->att; att->next; att = att->next) - ; att->attnum = var->natts++; att->created++; @@ -2392,8 +2524,8 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc) return retval; } if (!(att->data = malloc(att_type_size * att->len))) { - if(dimsize) free(dimsize); - return NC_ENOMEM; + if(dimsize) free(dimsize); + return NC_ENOMEM; } /* Read the data. */ @@ -2903,19 +3035,19 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp) if (ndimsp) { *ndimsp = 0; - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) (*ndimsp)++; } if (nvarsp) { *nvarsp = 0; - for (var = grp->var; var; var= var->next) + for (var = grp->var; var; var= var->l.next) (*nvarsp)++; } if (nattsp) { *nattsp = 0; - for (att = grp->att; att; att = att->next) + for (att = grp->att; att; att = att->l.next) (*nattsp)++; } @@ -2928,7 +3060,7 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp) with netcdf-3, then only the last unlimited one will be reported back in xtendimp. */ /* Note that this code is inconsistent with nc_inq_unlimid() */ - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) if (dim->unlimited) { *unlimdimidp = dim->dimid; diff --git a/libsrc4/nc4grp.c b/libsrc4/nc4grp.c index a58a3ecc6c..a858eee6de 100644 --- a/libsrc4/nc4grp.c +++ b/libsrc4/nc4grp.c @@ -18,7 +18,7 @@ conditions. int NC4_def_grp(int parent_ncid, const char *name, int *new_ncid) { - NC_GRP_INFO_T *grp, *g; + NC_GRP_INFO_T *grp; NC_HDF5_FILE_INFO_T *h5; char norm_name[NC_MAX_NAME + 1]; int retval; @@ -52,7 +52,7 @@ NC4_def_grp(int parent_ncid, const char *name, int *new_ncid) * group creation will be done when metadata is written by a * sync. */ if ((retval = nc4_grp_list_add(&(grp->children), h5->next_nc_grpid, - grp, grp->nc4_info->controller, norm_name, &g))) + grp, grp->nc4_info->controller, norm_name, NULL))) return retval; if (new_ncid) *new_ncid = grp->nc4_info->controller->ext_ncid | h5->next_nc_grpid; @@ -154,7 +154,7 @@ NC4_inq_ncid(int ncid, const char *name, int *grp_ncid) return retval; /* Look through groups for one of this name. */ - for (g = grp->children; g; g = g->next) + for (g = grp->children; g; g = g->l.next) if (!strcmp(norm_name, g->name)) /* found it! */ { if (grp_ncid) @@ -191,7 +191,7 @@ NC4_inq_grps(int ncid, int *numgrps, int *ncids) } /* Count the number of groups in this group. */ - for (g = grp->children; g; g = g->next) + for (g = grp->children; g; g = g->l.next) { if (ncids) { @@ -415,7 +415,7 @@ NC4_inq_varids(int ncid, int *nvars, int *varids) * 'em. The list is in correct (i.e. creation) order. */ if (grp->var) { - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) { if (varids) varids[num_vars] = var->varid; @@ -473,11 +473,11 @@ NC4_inq_dimids(int ncid, int *ndims, int *dimids, int include_parents) else { /* First count them. */ - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) num++; if (include_parents) for (g = grp->parent; g; g = g->parent) - for (dim = g->dim; dim; dim = dim->next) + for (dim = g->dim; dim; dim = dim->l.next) num++; /* If the user wants the dimension ids, get them. */ @@ -486,13 +486,13 @@ NC4_inq_dimids(int ncid, int *ndims, int *dimids, int include_parents) int n = 0; /* Get dimension ids from this group. */ - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) dimids[n++] = dim->dimid; /* Get dimension ids from parent groups. */ if (include_parents) for (g = grp->parent; g; g = g->parent) - for (dim = g->dim; dim; dim = dim->next) + for (dim = g->dim; dim; dim = dim->l.next) dimids[n++] = dim->dimid; qsort(dimids, num, sizeof(int), int_cmp); diff --git a/libsrc4/nc4hdf.c b/libsrc4/nc4hdf.c index bc5a8ebbfe..84d2d49e8c 100644 --- a/libsrc4/nc4hdf.c +++ b/libsrc4/nc4hdf.c @@ -23,10 +23,6 @@ #include #endif -#ifdef IGNORE -extern NC_FILE_INFO_T *nc_file; -#endif - #define NC3_STRICT_ATT_NAME "_nc3_strict" /* This is to track opened HDF5 objects to make sure they are @@ -54,12 +50,12 @@ rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid) LOG((3, "%s: grp->name %s", __func__, grp->name)); /* If there are any child groups, attach dimscale there, if needed. */ - for (child_grp = grp->children; child_grp; child_grp = child_grp->next) + for (child_grp = grp->children; child_grp; child_grp = child_grp->l.next) if ((retval = rec_reattach_scales(child_grp, dimid, dimscaleid))) return retval; /* Find any vars that use this dimension id. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) for (d = 0; d < var->ndims; d++) if (var->dimids[d] == dimid && !var->dimscale) { @@ -94,12 +90,12 @@ rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid) LOG((3, "%s: grp->name %s", __func__, grp->name)); /* If there are any child groups, detach dimscale there, if needed. */ - for (child_grp = grp->children; child_grp; child_grp = child_grp->next) + for (child_grp = grp->children; child_grp; child_grp = child_grp->l.next) if ((retval = rec_detach_scales(child_grp, dimid, dimscaleid))) return retval; /* Find any vars that use this dimension id. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) for (d = 0; d < var->ndims; d++) if (var->dimids[d] == dimid && !var->dimscale) { @@ -124,7 +120,7 @@ nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset) NC_VAR_INFO_T *var; /* Find the requested varid. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) break; if (!var) @@ -141,67 +137,6 @@ nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset) return NC_NOERR; } -/* Write or read one element of data. - - Oh, better far to live and die - Under the brave black flag I fly, - Than play a sanctimonious part, - With a pirate head and a pirate heart. - - Away to the cheating world go you, - Where pirates all are well-to-do. - But I'll be true to the song I sing, - And live and die a Pirate king. -*/ -int -nc4_pg_var1(NC_PG_T pg, NC *nc, int ncid, int varid, - const size_t *indexp, nc_type xtype, int is_long, void *ip) -{ - NC_GRP_INFO_T *grp; - NC_VAR_INFO_T *var; - int i; - size_t *start = NULL; - size_t *count = NULL; - int res = 0; - - int retval; - - /* Find file and var, cause I need the number of dims. */ - assert(nc); - if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var))) - return retval; - assert(grp && var && var->name); - - if(!(start = (size_t*)malloc(sizeof(size_t)*var->ndims))) { - return NC_ENOMEM; - } - - if(!(count = (size_t*)malloc(sizeof(size_t)*var->ndims))) { - free(start); - return NC_ENOMEM; - } - - - /* Set up the count and start arrays. */ - for (i=0; indims; i++) - { - start[i] = indexp[i]; - count[i] = 1; - } - - /* Get or put this data. */ - if (pg == GET) { - res = nc4_get_vara(nc, ncid, varid, start, count, xtype, - is_long, ip); - } else { - res = nc4_put_vara(nc, ncid, varid, start, count, xtype, - is_long, ip); - } - free(start); - free(count); - return res; -} - /* Get the default fill value for an atomic type. Memory for * fill_value must already be allocated, or you are DOOMED!!!*/ int @@ -295,9 +230,7 @@ get_fill_value(NC_HDF5_FILE_INFO_T *h5, NC_VAR_INFO_T *var, void **fillp) memcpy(fv_vlen->p, in_vlen->p, in_vlen->len * size); } else if (var->xtype == NC_STRING) - { - strcpy(*(char **)fillp, (char *)var->fill_value); - } + strcpy(*(char **)fillp, (char *)var->fill_value); else memcpy((*fillp), var->fill_value, size); } @@ -609,7 +542,7 @@ nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp, * put data beyond their current length. */ for (d2 = 0; d2 < var->ndims; d2++) { - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) { if (dim->dimid == var->dimids[d2]) { @@ -926,12 +859,12 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp, log_dim_info(var, fdims, fmaxdims, start, count); #endif - /* Check dimension bounds. Remember that unlimited dimnsions can + /* Check dimension bounds. Remember that unlimited dimensions can * put data beyond their current length. */ for (d2 = 0, break_it = 0; d2 < var->ndims; d2++) { for (g = grp; g && !break_it; g = g->parent) - for (dim = g->dim; dim; dim = dim->next) + for (dim = g->dim; dim; dim = dim->l.next) { if (dim->dimid == var->dimids[d2]) { @@ -946,7 +879,7 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp, { size_t ulen; - /* We can't go beyond the latgest current extent of + /* We can't go beyond the largest current extent of the unlimited dim. */ if ((retval = NC4_inq_dim(ncid, dim->dimid, NULL, &ulen))) BAIL(retval); @@ -957,7 +890,7 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp, if (start[d2] + count[d2] > ulen) BAIL_QUIET(NC_EEDGE); - /* THings get a little tricky here. If we're getting + /* Things get a little tricky here. If we're getting a GET request beyond the end of this var's current length in an unlimited dimension, we'll later need to return the fill value for the @@ -1156,15 +1089,12 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp, { if (var->xtype == NC_STRING) { - if (!(*(char **)filldata = malloc(sizeof(*(char **)fillvalue)))) + if (!(*(char **)filldata = strdup(*(char **)fillvalue))) return NC_ENOMEM; - strcpy(*(char **)filldata, *(char **)fillvalue); } else - { memcpy(filldata, fillvalue, file_type_size); - filldata = (char *)filldata + file_type_size; - } + filldata = (char *)filldata + file_type_size; } } @@ -1202,15 +1132,7 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp, if (xtend_size) free(xtend_size); if (fillvalue) - { - if (var->xtype == NC_STRING) - { - if (nc_free_string(1, (char **)fillvalue)) - return NC_ENOMEM; - } - else - free(fillvalue); - } + free(fillvalue); /* If there was an error return it, otherwise return any potential range error value. If none, return NC_NOERR as usual.*/ @@ -1310,6 +1232,7 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) hid_t plistid = 0, access_plistid = 0, typeid = 0, spaceid = 0; hsize_t *chunksize = NULL, *dimsize = NULL, *maxdimsize = NULL; int d; + void *fillp = NULL; NC_DIM_INFO_T *dim = NULL; int dims_found = 0; char *name_to_use; @@ -1337,8 +1260,6 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) /* Figure out what fill value to set, if any. */ if (!var->no_fill) { - void *fillp = NULL; - if ((retval = get_fill_value(grp->nc4_info, var, &fillp))) BAIL(retval); @@ -1368,7 +1289,6 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) if (H5Tclose(fill_typeid) < 0) BAIL(NC_EHDFERR); } - free(fillp); } } else { /* Required to truly turn HDF5 fill values off */ @@ -1430,7 +1350,7 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) { for (g = grp; g && (dims_found < var->ndims); g = g->parent) { - for (dim = g->dim; dim; dim = dim->next) + for (dim = g->dim; dim; dim = dim->l.next) { if (dim->dimid == var->dimids[d]) { @@ -1561,6 +1481,7 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) if (maxdimsize) free(maxdimsize); if (dimsize) free(dimsize); if (chunksize) free(chunksize); + if (fillp) free(fillp); return retval; } @@ -1757,7 +1678,7 @@ commit_type(NC_GRP_INFO_T *grp, NC_TYPE_INFO_T *type) return NC_EHDFERR; LOG((4, "creating compound type %s hdf_typeid 0x%x", type->name, type->hdf_typeid)); - for (field = type->field; field; field = field->next) + for (field = type->field; field; field = field->l.next) { if ((retval = nc4_get_hdf_typeid(grp->nc4_info, field->nctype, &hdf_base_typeid, type->endianness))) @@ -1822,7 +1743,7 @@ commit_type(NC_GRP_INFO_T *grp, NC_TYPE_INFO_T *type) return NC_EHDFERR; /* Add all the members to the HDF5 type. */ - for (enum_m = type->enum_member; enum_m; enum_m = enum_m->next) + for (enum_m = type->enum_member; enum_m; enum_m = enum_m->l.next) if (H5Tenum_insert(type->hdf_typeid, enum_m->name, enum_m->value) < 0) return NC_EHDFERR; @@ -1966,7 +1887,7 @@ attach_dimscales(NC_GRP_INFO_T *grp) int retval = NC_NOERR; /* Attach dimension scales. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) { /* Scales themselves do not attach. But I really wish they * would. */ @@ -1987,7 +1908,7 @@ attach_dimscales(NC_GRP_INFO_T *grp) if (!var->dimscale_attached[d]) { for (g = grp; g && !var->dimscale_attached[d]; g = g->parent) - for (dim1 = g->dim; dim1; dim1 = dim1->next) + for (dim1 = g->dim; dim1; dim1 = dim1->l.next) if (var->dimids[d] == dim1->dimid) { hid_t dim_datasetid; /* Dataset ID for dimension */ @@ -2035,7 +1956,7 @@ write_attlist(NC_ATT_INFO_T *attlist, int varid, NC_GRP_INFO_T *grp) NC_ATT_INFO_T *att; int retval; - for (att = attlist; att; att = att->next) + for (att = attlist; att; att = att->l.next) { if (att->dirty) { @@ -2113,7 +2034,7 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) * same name in this group. If there is one, check to see if * this object exists in the HDF group. */ if (var->dimscale) - for (d1 = grp->dim; d1; d1 = d1->next) + for (d1 = grp->dim; d1; d1 = d1->l.next) if (!strcmp(d1->name, var->name)) { if ((retval = var_exists(grp->hdf_grpid, var->name, &exists))) @@ -2158,7 +2079,7 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) for (d = 0; d < var->ndims; d++) if (var->dimscale_attached[d]) for (g = grp; g && !finished; g = g->parent) - for (dim1 = g->dim; dim1; dim1 = dim1->next) + for (dim1 = g->dim; dim1; dim1 = dim1->l.next) if (var->dimids[d] == dim1->dimid) { hid_t dim_datasetid; /* Dataset ID for dimension */ @@ -2295,7 +2216,7 @@ write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, int write_dimid) /* If this is a dimension without a variable, then update * the secret length information at the end of the NAME * attribute. */ - for (v1 = grp->var; v1; v1 = v1->next) + for (v1 = grp->var; v1; v1 = v1->l.next) if (!strcmp(v1->name, dim->name)) break; @@ -2318,7 +2239,7 @@ write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, int write_dimid) { int break_it = 0; for (g = grp; g && !break_it; g = g->parent) - for (dim1 = g->dim; dim1; dim1 = dim1->next) + for (dim1 = g->dim; dim1; dim1 = dim1->l.next) if (dim1->dimid == v1->dimids[d1]) { new_size[d1] = dim1->len; @@ -2361,7 +2282,7 @@ nc4_rec_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grp, int *bad_coord_orderp int retval; /* Iterate over variables in this group */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) { /* Only matters for dimension scale variables, with non-scalar dimensionality */ if (var->dimscale && var->ndims) @@ -2401,7 +2322,7 @@ nc4_rec_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grp, int *bad_coord_orderp } /* If there are any child groups, check them also for this condition. */ - for (child_grp = grp->children; child_grp; child_grp = child_grp->next) + for (child_grp = grp->children; child_grp; child_grp = child_grp->l.next) if ((retval = nc4_rec_detect_need_to_preserve_dimids(child_grp, bad_coord_orderp))) return retval; @@ -2429,13 +2350,9 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, int bad_coord_order) if ((retval = write_attlist(grp->att, NC_GLOBAL, grp))) return retval; - /* For some stupid reason, the dim list is stored backwards! Get to - * the back of the list. */ - for (dim = grp->dim; dim && dim->next; dim = dim->next) - ; - - /* Set the pointer to the beginning of the list of vars in this + /* Set the pointerito the beginning of the list of dims & vars in this * group. */ + dim = grp->dim; var = grp->var; /* Because of HDF5 ordering the dims and vars have to be stored in @@ -2445,7 +2362,7 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, int bad_coord_order) { /* Write non-coord dims in order, stopping at the first one that * has an associated coord var. */ - for (found_coord = 0; dim && !found_coord; dim = dim->prev) + for (found_coord = 0; dim && !found_coord; dim = dim->l.next) { if (!dim->coord_var) { @@ -2461,7 +2378,7 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, int bad_coord_order) /* Write each var. When we get to the coord var we are waiting * for (if any), then we break after writing it. */ - for (wrote_coord = 0; var && !wrote_coord; var = var->next) + for (wrote_coord = 0; var && !wrote_coord; var = var->l.next) { if ((retval = write_var(var, grp, bad_coord_order))) return retval; @@ -2474,7 +2391,7 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, int bad_coord_order) return retval; /* If there are any child groups, write their metadata. */ - for (child_grp = grp->children; child_grp; child_grp = child_grp->next) + for (child_grp = grp->children; child_grp; child_grp = child_grp->l.next) if ((retval = nc4_rec_write_metadata(child_grp, bad_coord_order))) return retval; @@ -2504,351 +2421,18 @@ nc4_rec_write_groups_types(NC_GRP_INFO_T *grp) return retval; /* If there are any user-defined types, write them now. */ - for (type = grp->type; type; type = type->next) + for (type = grp->type; type; type = type->l.next) if ((retval = commit_type(grp, type))) return retval; /* If there are any child groups, write their groups and types. */ - for (child_grp = grp->children; child_grp; child_grp = child_grp->next) + for (child_grp = grp->children; child_grp; child_grp = child_grp->l.next) if ((retval = nc4_rec_write_groups_types(child_grp))) return retval; return NC_NOERR; } -/* This reads/writes a whole var at a time. If the file has an - unlimited dimension, then we will look at the number of records - currently existing for this var, and read/write that many. This - this is not what the user intended, particularly with writing, then - that is there look-out! So we will not be extending datasets - here. */ -int -pg_var(NC_PG_T pg, NC *nc, int ncid, int varid, nc_type xtype, - int is_long, void *ip) -{ - NC_GRP_INFO_T *grp; - NC_VAR_INFO_T *var; - size_t start[NC_MAX_VAR_DIMS], count[NC_MAX_VAR_DIMS]; - int i; - int retval; - - assert(nc); - if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var))) - return retval; - assert(grp && var && var->name); - - /* For each dimension, the start will be 0, and the count will be - * the length of the dimension. */ - for (i = 0; i < var->ndims; i++) - { - start[i] = 0; - if ((retval = NC4_inq_dim(ncid, var->dimids[i], NULL, &(count[i])))) - return retval; - } - - /* Read or write the data. */ - if (pg == GET) - return nc4_get_vara(nc, ncid, varid, start, count, xtype, - is_long, ip); - else - return nc4_put_vara(nc, ncid, varid, start, count, xtype, - is_long, ip); -} - -/* Write or read some mapped data. Yea, like I even understand what it - is! - - I stole this code, lock, stock, and semicolons, from the netcdf - 3.5.1 beta release. It walks through the stride and map arrays, and - converts them to a series of calles to the varm function. - - I had to modify the code a little to fit it in, and generalize it - for all data types, and for both puts and gets. - - Ed Hartnett, 9/43/03 -*/ -int -nc4_pg_varm(NC_PG_T pg, NC *nc, int ncid, int varid, const size_t *start, - const size_t *edges, const ptrdiff_t *stride, - const ptrdiff_t *map, nc_type xtype, int is_long, void *data) -{ - NC_GRP_INFO_T *grp; - NC_HDF5_FILE_INFO_T *h5; - NC_VAR_INFO_T *var; - int maxidim; /* maximum dimensional index */ - size_t mem_type_size; - int convert_map = 0; - ptrdiff_t new_map[NC_MAX_VAR_DIMS]; - int i; - int retval = NC_NOERR; - - LOG((3, "%s: ncid 0x%x varid %d xtype %d", __func__, ncid, varid, xtype)); - - /* Find metadata for this file and var. */ - assert(nc); - h5 = NC4_DATA(nc); - assert(h5); - - if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var))) - return retval; - assert(grp && var && var->name); - - /* If mem_nc_type is NC_NAT, it means we were called by - * nc_get|put_varm, the old V2 API call! In this case we want to - * use the file type as the mem type as well. Also, for these two - * functions only, we interpret the map array as referring to - * numbers of bytes rather than number of elements. (This is - * something that changed between V2 and V3.) Also we do not allow - * mapped access to user-defined vars in nc4. */ - if (xtype == NC_NAT) - { - if (var->xtype > NC_STRING) - return NC_EMAPTYPE; - xtype = var->xtype; - convert_map++; - } - assert(xtype); - - /* What is the size of this type? */ - if ((retval = nc4_get_typelen_mem(h5, xtype, is_long, &mem_type_size))) - return retval; - - if(map != NULL && var->ndims && convert_map) - { - /* convert map units from bytes to units of sizeof(type) */ - for(i = 0; i < var->ndims; i++) - { - if(map[i] % mem_type_size != 0) - return NC_EINVAL; - new_map[i] = map[i] / mem_type_size; - } - map = new_map; - } - - /* No text to number hanky-panky is allowed for those observing - * strict netcdf-3 rules! It's sick. */ - if ((h5->cmode & NC_CLASSIC_MODEL) && (xtype == NC_CHAR || var->xtype == NC_CHAR) && - (xtype != var->xtype)) - return NC_ECHAR; - - /* If the file is read-only, return an error. */ - if (pg == PUT && h5->no_write) - return NC_EPERM; - - /* If we're in define mode, we can't read or write data. If strict - * nc3 rules are in effect, return an error, otherwise leave define - * mode. */ - if (h5->flags & NC_INDEF) - { - if (h5->cmode & NC_CLASSIC_MODEL) - return NC_EINDEFINE; - if ((retval = NC4__enddef(ncid,0,0,0,0))) - BAIL(retval); - } - -#ifdef LOGGING - { - int i; - if (start) - for (i=0; indims; i++) - LOG((4, "start[%d] %d", i, start[i])); - if (edges) - for (i=0; indims; i++) - LOG((4, "edges[%d] %d", i, edges[i])); - if (stride) - for (i=0; indims; i++) - LOG((4, "stride[%d] %d", i, stride[i])); - if (map) - for (i=0; indims; i++) - LOG((4, "map[%d] %d", i, map[i])); - } -#endif /* LOGGING */ - - /* The code below was stolen from netcdf-3. Some comments by Ed. */ - maxidim = (int) var->ndims - 1; - if (maxidim < 0) - { - /* The variable is a scalar; consequently, there is only one - thing to get and only one place to put it. (Why was I - called?) */ - return pg_var(pg, nc, ncid, varid, xtype, is_long, data); - } - - /* The variable is an array. */ - { - int idim; - size_t *mystart = NULL; - size_t *myedges; - size_t *iocount; /* count vector */ - size_t *stop; /* stop indexes */ - size_t *length; /* edge lengths in bytes */ - ptrdiff_t *mystride; - ptrdiff_t *mymap; - - /* Verify stride argument. */ - for (idim = 0; idim <= maxidim; ++idim) - { - if (stride != NULL - && (stride[idim] == 0 - /* cast needed for braindead systems with signed size_t */ - || (unsigned long) stride[idim] >= X_INT_MAX)) - { - return NC_ESTRIDE; - } - } - - /* The mystart array of pointer info is needed to walk our way - through the dimensions as specified by the start, edges, - stride and (gulp!) map parameters. */ - if (!(mystart = (size_t *)calloc((size_t)var->ndims * 7, sizeof(ptrdiff_t)))) - return NC_ENOMEM; - myedges = mystart + var->ndims; - iocount = myedges + var->ndims; - stop = iocount + var->ndims; - length = stop + var->ndims; - mystride = (ptrdiff_t *)(length + var->ndims); - mymap = mystride + var->ndims; - - /* Initialize I/O parameters. */ - for (idim = maxidim; idim >= 0; --idim) - { - /* Get start value, use 0 if non provided. */ - mystart[idim] = start != NULL ? start[idim] : 0; - - /* If any edges are 0, return NC_NOERR and forget it. */ - if (edges[idim] == 0) - { - retval = NC_NOERR; - goto done; - } - - /* If edges not provided, use the current dimlen. */ - if (edges) - myedges[idim] = edges[idim]; - else - { - size_t len; - if ((retval = NC4_inq_dim(ncid, var->dimids[idim], NULL, &len))) - goto done; - myedges[idim] = len - mystart[idim]; - } - - /* If stride not provided, use 1. */ - mystride[idim] = stride != NULL ? stride[idim] : 1; - - /* If map is not provided, do something dark and - mysterious. */ - if (map) - mymap[idim] = map[idim]; - else - mymap[idim] = idim == maxidim ? 1 : - mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; - - iocount[idim] = 1; - length[idim] = mymap[idim] * myedges[idim]; - stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; - } - - /* Check start, edges */ - for (idim = maxidim; idim >= 0; --idim) - { - size_t dimlen; - if ((retval = NC4_inq_dim(ncid, var->dimids[idim], NULL, &dimlen))) - goto done; - /* Don't check unlimited dimension on PUTs. */ - if (pg == PUT) - { - int stop = 0, d, num_unlim_dim; - int *unlim_dimids = NULL; - - NC4_inq_unlimdims(ncid, &num_unlim_dim, NULL); - if(!(unlim_dimids=(int*)malloc(sizeof(int)*num_unlim_dim))) - return errno; - - if ((retval = NC4_inq_unlimdims(ncid, &num_unlim_dim, unlim_dimids))) - { - free(unlim_dimids); - goto done; - } - - for (d = 0; d < num_unlim_dim; d++) - if (var->dimids[idim] == unlim_dimids[d]) - stop++; - if (stop) - break; - } - LOG((4, "idim=%d mystart[idim]=%d myedge[idim]=%d dimlen=%d", - idim, mystart[idim], myedges[idim], dimlen)); - if (mystart[idim] >= dimlen) - { - retval = NC_EINVALCOORDS; - goto done; - } - - if (mystart[idim] + myedges[idim] > dimlen) - { - retval = NC_EEDGE; - goto done; - } - } - - /* OK, now we're just getting too fancy... As an optimization, - adjust I/O parameters when the fastest dimension has unity - stride both externally and internally. In this case, the user - could have called a simpler routine - (i.e. ncvarnc_get_vara_text).*/ - if (mystride[maxidim] == 1 - && mymap[maxidim] == 1) - { - iocount[maxidim] = myedges[maxidim]; - mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; - mymap[maxidim] = (ptrdiff_t) length[maxidim]; - } - - /* Perform I/O. Exit when done. */ - for (;;) - { - int lretval; - if (pg == GET) - lretval = nc4_get_vara(nc, ncid, varid, mystart, iocount, xtype, - is_long, data); - else - lretval = nc4_put_vara(nc, ncid, varid, mystart, iocount, xtype, - is_long, data); - if (lretval != NC_NOERR - && (retval == NC_NOERR || lretval != NC_ERANGE)) - retval = lretval; - - /* - * The following code permutes through the variable s - * external start-index space and it s internal address - * space. At the UPC, this algorithm is commonly - * called "odometer code". - */ - idim = maxidim; - carry: - data = (char *)data + (mymap[idim] * mem_type_size); - LOG((4, "data=0x%x mymap[%d]=%d", data, idim, (int)mymap[idim])); - mystart[idim] += mystride[idim]; - LOG((4, "mystart[%d]=%d length[%d]=%d", idim, (int)mystart[idim], - idim, (int)length[idim])); - if (mystart[idim] == stop[idim]) - { - mystart[idim] = start[idim]; - data = (char *)data - (length[idim] * mem_type_size); - if (--idim < 0) - break; /* normal return */ - goto carry; - } - } /* I/O loop */ - done: - free(mystart); - } /* variable is array */ - - exit: - return retval; -} - /* This function will copy data from one buffer to another, in accordance with the types. Range errors will be noted, and the fill value used (or the default fill value if none is supplied) for @@ -3826,13 +3410,13 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp) LOG((4, "%s: grp->name %s", __func__, grp->name)); /* Perform var dimscale match for child groups. */ - for (g = grp->children; g; g = g->next) + for (g = grp->children; g; g = g->l.next) if ((retval = nc4_rec_match_dimscales(g))) return retval; /* Check all the vars in this group. If they have dimscale info, * try and find a dimension for them. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) { /* Skip dimension scale variables */ if (!var->dimscale) @@ -3851,7 +3435,7 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp) * match. */ for (g = grp; g && !finished; g = g->parent) { - for (dim = g->dim; dim; dim = dim->next) + for (dim = g->dim; dim; dim = dim->l.next) { if (var->dimscale_hdf5_objids[d].fileno[0] == dim->hdf5_objid.fileno[0] && var->dimscale_hdf5_objids[d].objno[0] == dim->hdf5_objid.objno[0] && @@ -3919,7 +3503,7 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp) for (d = 0; d < var->ndims; d++) { /* Is there already a phony dimension of the correct size? */ - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) if ((dim->len == h5dimlen[d]) && ((h5dimlenmax[d] == H5S_UNLIMITED && dim->unlimited) || (h5dimlenmax[d] != H5S_UNLIMITED && !dim->unlimited))) @@ -3931,15 +3515,13 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp) char phony_dim_name[NC_MAX_NAME + 1]; LOG((3, "%s: creating phony dim for var %s", __func__, var->name)); - if ((retval = nc4_dim_list_add(&grp->dim))) + if ((retval = nc4_dim_list_add(&grp->dim, &dim))) return retval; grp->ndims++; - dim = grp->dim; dim->dimid = grp->nc4_info->next_dimid++; sprintf(phony_dim_name, "phony_dim_%d", dim->dimid); - if (!(dim->name = malloc((strlen(phony_dim_name) + 1) * sizeof(char)))) + if (!(dim->name = strdup(phony_dim_name))) return NC_ENOMEM; - strcpy(dim->name, phony_dim_name); dim->len = h5dimlen[d]; if (h5dimlenmax[d] == H5S_UNLIMITED) dim->unlimited = 1; diff --git a/libsrc4/nc4internal.c b/libsrc4/nc4internal.c index ad0e597a24..5e4ef0f651 100644 --- a/libsrc4/nc4internal.c +++ b/libsrc4/nc4internal.c @@ -85,7 +85,7 @@ find_var_dim_max_length(NC_GRP_INFO_T *grp, int varid, int dimid, size_t *maxlen *maxlen = 0; /* Find this var. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) break; if (!var) @@ -153,7 +153,6 @@ int nc4_nc4f_list_add(NC *nc, const char *path, int mode) { NC_HDF5_FILE_INFO_T *h5; - NC_GRP_INFO_T *grp; assert(nc && !NC4_DATA(nc) && path); @@ -175,7 +174,7 @@ nc4_nc4f_list_add(NC *nc, const char *path, int mode) * group. Allocate space for one group's worth of information. Set * its hdf id, name, and a pointer to it's file structure. */ return nc4_grp_list_add(&(h5->root_grp), h5->next_nc_grpid++, - NULL, nc, NC_GROUP_NAME, &grp); + NULL, nc, NC_GROUP_NAME, NULL); } /* Given an ncid, find the relevant group and return a pointer to it, @@ -280,7 +279,7 @@ nc4_rec_find_grp(NC_GRP_INFO_T *start_grp, int target_nc_grpid) /* Shake down the kids. */ if (start_grp->children) - for (g = start_grp->children; g; g = g->next) + for (g = start_grp->children; g; g = g->l.next) if ((res = nc4_rec_find_grp(g, target_nc_grpid))) return res; @@ -306,7 +305,7 @@ nc4_find_g_var_nc(NC *nc, int ncid, int varid, return NC_ENOTVAR; /* Find the var info. */ - for ((*var) = (*grp)->var; (*var); (*var) = (*var)->next) + for ((*var) = (*grp)->var; (*var); (*var) = (*var)->l.next) if ((*var)->varid == varid) break; if (!(*var)) @@ -327,7 +326,7 @@ nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim, /* Find the dim info. */ for (g = grp; g && !finished; g = g->parent) - for ((*dim) = g->dim; (*dim); (*dim) = (*dim)->next) + for ((*dim) = g->dim; (*dim); (*dim) = (*dim)->l.next) if ((*dim)->dimid == dimid) { dg = g; @@ -353,7 +352,7 @@ nc4_find_var(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var) assert(grp && var && name); /* Find the var info. */ - for ((*var) = grp->var; (*var); (*var) = (*var)->next) + for ((*var) = grp->var; (*var); (*var) = (*var)->l.next) if (0 == strcmp(name, (*var)->name)) break; @@ -371,7 +370,7 @@ nc4_rec_find_hdf_type(NC_GRP_INFO_T *start_grp, hid_t target_hdf_typeid) assert(start_grp); /* Does this group have the type we are searching for? */ - for (type = start_grp->type; type; type = type->next) + for (type = start_grp->type; type; type = type->l.next) { if ((equal = H5Tequal(type->native_typeid ? type->native_typeid : type->hdf_typeid, target_hdf_typeid)) < 0) return NULL; @@ -381,7 +380,7 @@ nc4_rec_find_hdf_type(NC_GRP_INFO_T *start_grp, hid_t target_hdf_typeid) /* Shake down the kids. */ if (start_grp->children) - for (g = start_grp->children; g; g = g->next) + for (g = start_grp->children; g; g = g->l.next) if ((res = nc4_rec_find_hdf_type(g, target_hdf_typeid))) return res; @@ -399,13 +398,13 @@ nc4_rec_find_nc_type(NC_GRP_INFO_T *start_grp, nc_type target_nc_typeid) assert(start_grp); /* Does this group have the type we are searching for? */ - for (type = start_grp->type; type; type = type->next) + for (type = start_grp->type; type; type = type->l.next) if (type->nc_typeid == target_nc_typeid) return type; /* Shake down the kids. */ if (start_grp->children) - for (g = start_grp->children; g; g = g->next) + for (g = start_grp->children; g; g = g->l.next) if ((res = nc4_rec_find_nc_type(g, target_nc_typeid))) return res; @@ -423,13 +422,13 @@ nc4_rec_find_named_type(NC_GRP_INFO_T *start_grp, char *name) assert(start_grp); /* Does this group have the type we are searching for? */ - for (type = start_grp->type; type; type = type->next) + for (type = start_grp->type; type; type = type->l.next) if (!strcmp(type->name, name)) return type; /* Search subgroups. */ if (start_grp->children) - for (g = start_grp->children; g; g = g->next) + for (g = start_grp->children; g; g = g->l.next) if ((res = nc4_rec_find_named_type(g, name))) return res; @@ -476,13 +475,13 @@ nc4_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len) /* If there are any groups, call this function recursively on * them. */ - for (g = grp->children; g; g = g->next) + for (g = grp->children; g; g = g->l.next) if ((retval = nc4_find_dim_len(g, dimid, len))) return retval; /* For all variables in this group, find the ones that use this * dimension, and remember the max length. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) { /* Find max length of dim in this variable... */ if ((retval = find_var_dim_max_length(grp, var->varid, dimid, &mylen))) @@ -511,7 +510,7 @@ nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum, attlist = grp->att; else { - for(var = grp->var; var; var = var->next) + for(var = grp->var; var; var = var->l.next) { if (var->varid == varid) { @@ -525,7 +524,7 @@ nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum, /* Now find the attribute by name or number. If a name is provided, * ignore the attnum. */ - for (*att = attlist; *att; *att = (*att)->next) + for (*att = attlist; *att; *att = (*att)->l.next) if ((name && !strcmp((*att)->name, name)) || (!name && (*att)->attnum == attnum)) return NC_NOERR; @@ -559,7 +558,7 @@ nc4_find_nc_att(int ncid, int varid, const char *name, int attnum, attlist = grp->att; else { - for(var = grp->var; var; var = var->next) + for(var = grp->var; var; var = var->l.next) { if (var->varid == varid) { @@ -572,7 +571,7 @@ nc4_find_nc_att(int ncid, int varid, const char *name, int attnum, } /* Now find the attribute by name or number. If a name is provided, ignore the attnum. */ - for (*att = attlist; *att; *att = (*att)->next) + for (*att = attlist; *att; *att = (*att)->l.next) if ((name && !strcmp((*att)->name, name)) || (!name && (*att)->attnum == attnum)) return NC_NOERR; @@ -589,6 +588,7 @@ nc4_find_nc_file(int ext_ncid, NC_HDF5_FILE_INFO_T** h5p) { NC* nc; int stat; + stat = NC_check_id(ext_ncid,&nc); if(stat != NC_NOERR) nc = NULL; @@ -599,92 +599,100 @@ nc4_find_nc_file(int ext_ncid, NC_HDF5_FILE_INFO_T** h5p) return nc; } -/* Add to the end of a var list. Return a pointer to the newly - * added var. */ -int -nc4_var_list_add(NC_VAR_INFO_T **list, NC_VAR_INFO_T **var) +/* Add object to the end of a list. */ +static void +obj_list_add(NC_LIST_NODE_T **list, NC_LIST_NODE_T *obj) { - NC_VAR_INFO_T *v; - - /* Allocate storage for new variable. */ - if (!(*var = calloc(1, sizeof(NC_VAR_INFO_T)))) - return NC_ENOMEM; - - /* Go to the end of the list and set the last one to point at our - * new var, or, if the list is empty, our new var becomes the - * list. */ + /* Go to the end of the list and set the last one to point at object, + * or, if the list is empty, our new object becomes the list. */ if(*list) { - for (v = *list; v; v = v->next) - if (!v->next) + NC_LIST_NODE_T *o; + + for (o = *list; o; o = o->next) + if (!o->next) break; - v->next = *var; - (*var)->prev = v; + o->next = obj; + obj->prev = o; } else - *list = *var; + *list = obj; +} - /* These are the HDF5-1.8.4 defaults. */ - (*var)->chunk_cache_size = nc4_chunk_cache_size; - (*var)->chunk_cache_nelems = nc4_chunk_cache_nelems; - (*var)->chunk_cache_preemption = nc4_chunk_cache_preemption; +/* Remove object from a list. */ +static void +obj_list_del(NC_LIST_NODE_T **list, NC_LIST_NODE_T *obj) +{ + /* Remove the var from the linked list. */ + if(*list == obj) + *list = obj->next; + else + ((NC_LIST_NODE_T *)obj->prev)->next = obj->next; - return NC_NOERR; + if(obj->next) + ((NC_LIST_NODE_T *)obj->next)->prev = obj->prev; } -/* Add to the beginning of a dim list. */ +/* Add to the end of a var list. Return a pointer to the newly + * added var. */ int -nc4_dim_list_add(NC_DIM_INFO_T **list) +nc4_var_list_add(NC_VAR_INFO_T **list, NC_VAR_INFO_T **var) { - NC_DIM_INFO_T *dim; - if (!(dim = calloc(1, sizeof(NC_DIM_INFO_T)))) + NC_VAR_INFO_T *new_var; + + /* Allocate storage for new variable. */ + if (!(new_var = calloc(1, sizeof(NC_VAR_INFO_T)))) return NC_ENOMEM; - if(*list) - (*list)->prev = dim; - dim->next = *list; - *list = dim; + + /* These are the HDF5-1.8.4 defaults. */ + new_var->chunk_cache_size = nc4_chunk_cache_size; + new_var->chunk_cache_nelems = nc4_chunk_cache_nelems; + new_var->chunk_cache_preemption = nc4_chunk_cache_preemption; + + /* Add object to list */ + obj_list_add((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)new_var); + + /* Set the var pointer, if one was given */ + if (var) + *var = new_var; + return NC_NOERR; } /* Add to the beginning of a dim list. */ -#ifdef EXTERN_UNUSED int -nc4_dim_list_add2(NC_DIM_INFO_T **list, NC_DIM_INFO_T **new_dim) +nc4_dim_list_add(NC_DIM_INFO_T **list, NC_DIM_INFO_T **dim) { - NC_DIM_INFO_T *dim; - if (!(dim = calloc(1, sizeof(NC_DIM_INFO_T)))) + NC_DIM_INFO_T *new_dim; + + if (!(new_dim = calloc(1, sizeof(NC_DIM_INFO_T)))) return NC_ENOMEM; - if(*list) - (*list)->prev = dim; - dim->next = *list; - *list = dim; - /* Return pointer to new dimension. */ - if (new_dim) - *new_dim = dim; + /* Add object to list */ + obj_list_add((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)new_dim); + + /* Set the dim pointer, if one was given */ + if (dim) + *dim = new_dim; + return NC_NOERR; } -#endif /* Add to the end of an att list. */ int -nc4_att_list_add(NC_ATT_INFO_T **list) +nc4_att_list_add(NC_ATT_INFO_T **list, NC_ATT_INFO_T **att) { - NC_ATT_INFO_T *att, *a1; - if (!(att = calloc(1, sizeof(NC_ATT_INFO_T)))) + NC_ATT_INFO_T *new_att; + + if (!(new_att = calloc(1, sizeof(NC_ATT_INFO_T)))) return NC_ENOMEM; - if (*list) - { - for (a1 = *list; a1; a1 = a1->next) - if (!a1->next) - break; - a1->next = att; - att->prev = a1; - } - else - { - *list = att; - } + + /* Add object to list */ + obj_list_add((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)new_att); + + /* Set the attribute pointer, if one was given */ + if (att) + *att = new_att; return NC_NOERR; } @@ -696,37 +704,30 @@ nc4_grp_list_add(NC_GRP_INFO_T **list, int new_nc_grpid, NC_GRP_INFO_T *parent_grp, NC *nc, char *name, NC_GRP_INFO_T **grp) { - NC_GRP_INFO_T *g; + NC_GRP_INFO_T *new_grp; LOG((3, "%s: new_nc_grpid %d name %s ", __func__, new_nc_grpid, name)); /* Get the memory to store this groups info. */ - if (!(*grp = calloc(1, sizeof(NC_GRP_INFO_T)))) + if (!(new_grp = calloc(1, sizeof(NC_GRP_INFO_T)))) return NC_ENOMEM; - /* If the list is not NULL, add this group to it. Otherwise, this - * group structure becomes the list. */ - if (*list) - { - /* Move to end of the list. */ - for (g = *list; g; g = g->next) - if (!g->next) - break; - g->next = *grp; /* Add grp to end of list. */ - (*grp)->prev = g; - } - else + /* Fill in this group's information. */ + new_grp->nc_grpid = new_nc_grpid; + new_grp->parent = parent_grp; + if (!(new_grp->name = strdup(name))) { - *list = *grp; + free(new_grp); + return NC_ENOMEM; } + new_grp->nc4_info = NC4_DATA(nc); - /* Fill in this group's information. */ - (*grp)->nc_grpid = new_nc_grpid; - (*grp)->parent = parent_grp; - if (!((*grp)->name = malloc((strlen(name) + 1) * sizeof(char)))) - return NC_ENOMEM; - strcpy((*grp)->name, name); - (*grp)->nc4_info = NC4_DATA(nc); + /* Add object to list */ + obj_list_add((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)new_grp); + + /* Set the group pointer, if one was given */ + if (grp) + *grp = new_grp; return NC_NOERR; } @@ -743,17 +744,17 @@ nc4_check_dup_name(NC_GRP_INFO_T *grp, char *name) NC_VAR_INFO_T *var; /* Any types of this name? */ - for (type = grp->type; type; type = type->next) + for (type = grp->type; type; type = type->l.next) if (!strcmp(type->name, name)) return NC_ENAMEINUSE; /* Any child groups of this name? */ - for (g = grp->children; g; g = g->next) + for (g = grp->children; g; g = g->l.next) if (!strcmp(g->name, name)) return NC_ENAMEINUSE; /* Any variables of this name? */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (!strcmp(var->name, name)) return NC_ENAMEINUSE; @@ -762,28 +763,18 @@ nc4_check_dup_name(NC_GRP_INFO_T *grp, char *name) /* Add to the end of a type list. */ int -nc4_type_list_add(NC_TYPE_INFO_T **list, NC_TYPE_INFO_T **new_type) +nc4_type_list_add(NC_TYPE_INFO_T **list, NC_TYPE_INFO_T **type) { - NC_TYPE_INFO_T *type, *t; + NC_TYPE_INFO_T *new_type; - if (!(type = calloc(1, sizeof(NC_TYPE_INFO_T)))) + if (!(new_type = calloc(1, sizeof(NC_TYPE_INFO_T)))) return NC_ENOMEM; - if (*list) - { - for (t = *list; t; t = t->next) - if (!t->next) - break; - t->next = type; - type->prev = t; - } - else - { - *list = type; - } + /* Add object to list */ + obj_list_add((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)new_type); - if (new_type) - *new_type = type; + if (type) + *type = new_type; return NC_NOERR; } @@ -794,8 +785,7 @@ nc4_field_list_add(NC_FIELD_INFO_T **list, int fieldid, const char *name, size_t offset, hid_t field_hdf_typeid, hid_t native_typeid, nc_type xtype, int ndims, const int *dim_sizesp) { - NC_FIELD_INFO_T *field, *f; - int i; + NC_FIELD_INFO_T *field; /* Name has already been checked and UTF8 normalized. */ if (!name) @@ -805,25 +795,13 @@ nc4_field_list_add(NC_FIELD_INFO_T **list, int fieldid, const char *name, if (!(field = calloc(1, sizeof(NC_FIELD_INFO_T)))) return NC_ENOMEM; - /* Add this field to list. */ - if (*list) - { - for (f = *list; f; f = f->next) - if (!f->next) - break; - f->next = field; - field->prev = f; - } - else - { - *list = field; - } - /* Store the information about this field. */ field->fieldid = fieldid; - if (!(field->name = malloc((strlen(name) + 1) * sizeof(char)))) + if (!(field->name = strdup(name))) + { + free(field); return NC_ENOMEM; - strcpy(field->name, name); + } field->hdf_typeid = field_hdf_typeid; field->native_typeid = native_typeid; field->nctype = xtype; @@ -831,12 +809,21 @@ nc4_field_list_add(NC_FIELD_INFO_T **list, int fieldid, const char *name, field->ndims = ndims; if (ndims) { + int i; + if (!(field->dim_size = malloc(ndims * sizeof(int)))) + { + free(field->name); + free(field); return NC_ENOMEM; + } for (i = 0; i < ndims; i++) field->dim_size[i] = dim_sizesp[i]; } + /* Add object to list */ + obj_list_add((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)field); + return NC_NOERR; } @@ -845,43 +832,31 @@ int nc4_enum_member_add(NC_ENUM_MEMBER_INFO_T **list, size_t size, const char *name, const void *value) { - NC_ENUM_MEMBER_INFO_T *member = NULL, *m = NULL; + NC_ENUM_MEMBER_INFO_T *member; /* Name has already been checked. */ assert(name && size > 0 && value); - LOG((4, "nc4_enum_member_add: size %d name %s", size, name)); + LOG((4, "%s: size %d name %s", __func__, size, name)); /* Allocate storage for this field information. */ if (!(member = calloc(1, sizeof(NC_ENUM_MEMBER_INFO_T)))) return NC_ENOMEM; - if (!(member->value = calloc(1, size))) { + if (!(member->value = malloc(size))) { free(member); return NC_ENOMEM; } - if (!(member->name = malloc((strlen(name) + 1) * sizeof(char)))) { + if (!(member->name = strdup(name))) { free(member->value); free(member); return NC_ENOMEM; } - /* Add this field to list. */ - if (*list) - { - for (m = *list; m; m = m->next) - if (!m->next) - break; - m->next = member; - member->prev = m; - } - else - { - *list = member; - } - - /* Store the information about this member. */ - strcpy(member->name, name); + /* Store the value for this member. */ memcpy(member->value, value, size); + /* Add object to list */ + obj_list_add((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)member); + return NC_NOERR; } @@ -892,15 +867,17 @@ nc4_var_list_del(NC_VAR_INFO_T **list, NC_VAR_INFO_T *var) NC_ATT_INFO_T *a, *att; int ret; - if(var == NULL) { + if(var == NULL) return NC_NOERR; - } + + /* Remove the var from the linked list. */ + obj_list_del((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)var); /* First delete all the attributes attached to this var. */ att = var->att; while (att) { - a = att->next; + a = att->l.next; if ((ret = nc4_att_list_del(&var->att, att))) return ret; att = a; @@ -922,15 +899,6 @@ nc4_var_list_del(NC_VAR_INFO_T **list, NC_VAR_INFO_T *var) if (var->dim) {free(var->dim); var->dim = NULL;} - /* Remove the var from the linked list. */ - if(*list == var) - *list = var->next; - else - var->prev->next = var->next; - - if(var->next) - var->next->prev = var->prev; - /* Delete any fill value allocation. This must be done before the * type_info is freed. */ if (var->fill_value) @@ -979,7 +947,6 @@ nc4_var_list_del(NC_VAR_INFO_T **list, NC_VAR_INFO_T *var) /* Delete the var. */ free(var); - var = NULL; return NC_NOERR; } @@ -988,15 +955,8 @@ nc4_var_list_del(NC_VAR_INFO_T **list, NC_VAR_INFO_T *var) static void field_list_del(NC_FIELD_INFO_T **list, NC_FIELD_INFO_T *field) { - /* Take this field out of the list. */ - if(*list == field) - *list = field->next; - else - field->prev->next = field->next; - - if(field->next) - field->next->prev = field->prev; + obj_list_del((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)field); /* Free some stuff. */ if (field->name) @@ -1015,6 +975,9 @@ type_list_del(NC_TYPE_INFO_T **list, NC_TYPE_INFO_T *type) NC_FIELD_INFO_T *field, *f; NC_ENUM_MEMBER_INFO_T *enum_member, *em; + /* Take this type out of the list. */ + obj_list_del((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)type); + /* Close any open user-defined HDF5 typieds. */ if (type->hdf_typeid) { @@ -1036,7 +999,7 @@ type_list_del(NC_TYPE_INFO_T **list, NC_TYPE_INFO_T *type) field = type->field; while (field) { - f = field->next; + f = field->l.next; field_list_del(&type->field, field); field = f; } @@ -1045,22 +1008,13 @@ type_list_del(NC_TYPE_INFO_T **list, NC_TYPE_INFO_T *type) enum_member = type->enum_member; while (enum_member) { - em = enum_member->next; + em = enum_member->l.next; free(enum_member->value); free(enum_member->name); free(enum_member); enum_member = em; } - /* Take this type out of the list. */ - if(*list == type) - *list = type->next; - else - type->prev->next = type->next; - - if(type->next) - type->next->prev = type->prev; - /* Nc_Free the memory. */ free(type); @@ -1072,13 +1026,7 @@ int nc4_dim_list_del(NC_DIM_INFO_T **list, NC_DIM_INFO_T *dim) { /* Take this dimension out of the list. */ - if(*list == dim) - *list = dim->next; - else - dim->prev->next = dim->next; - - if(dim->next) - dim->next->prev = dim->prev; + obj_list_del((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)dim); /* Free memory allocated for names. */ if (dim->name) @@ -1093,13 +1041,8 @@ nc4_dim_list_del(NC_DIM_INFO_T **list, NC_DIM_INFO_T *dim) static void grp_list_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) { - if(*list == grp) - *list = grp->next; - else - grp->prev->next = grp->next; - - if(grp->next) - grp->next->prev = grp->prev; + /* Take this group out of the list. */ + obj_list_del((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)grp); free(grp); } @@ -1124,7 +1067,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) g = grp->children; while(g) { - c = g->next; + c = g->l.next; if ((retval = nc4_rec_grp_del(&(grp->children), g))) return retval; g = c; @@ -1136,7 +1079,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) while (att) { LOG((4, "%s: deleting att %s", __func__, att->name)); - a = att->next; + a = att->l.next; if ((retval = nc4_att_list_del(&grp->att, att))) return retval; att = a; @@ -1151,7 +1094,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) * scale. */ if (var->hdf_datasetid && H5Dclose(var->hdf_datasetid) < 0) return NC_EHDFERR; - v = var->next; + v = var->l.next; if ((retval = nc4_var_list_del(&grp->var, var))) return retval; var = v; @@ -1165,7 +1108,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) /* Close HDF5 dataset associated with this dim. */ if (dim->hdf_dimscaleid && H5Dclose(dim->hdf_dimscaleid) < 0) return NC_EHDFERR; - d = dim->next; + d = dim->l.next; if ((retval = nc4_dim_list_del(&grp->dim, dim))) return retval; dim = d; @@ -1176,7 +1119,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) while (type) { LOG((4, "%s: deleting type %s", __func__, type->name)); - t = type->next; + t = type->l.next; if ((retval = type_list_del(&grp->type, type))) return retval; type = t; @@ -1206,13 +1149,7 @@ nc4_att_list_del(NC_ATT_INFO_T **list, NC_ATT_INFO_T *att) int i; /* Take this att out of the list. */ - if(*list == att) - *list = att->next; - else - att->prev->next = att->next; - - if(att->next) - att->next->prev = att->prev; + obj_list_del((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)att); /* Free memory that was malloced to hold data for this * attribute. */ @@ -1319,7 +1256,7 @@ nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, NC_DIM_INFO_T *dim) { NC_DIM_INFO_T *dim1; - for (dim1 = g->dim; dim1 && !finished; dim1 = dim1->next) + for (dim1 = g->dim; dim1 && !finished; dim1 = dim1->l.next) if (var->dimids[d] == dim1->dimid) { hid_t dim_datasetid; /* Dataset ID for dimension */ @@ -1436,23 +1373,15 @@ rec_print_metadata(NC_GRP_INFO_T *grp, int *tab_count) LOG((2, "%s GROUP - %s nc_grpid: %d nvars: %d natts: %d", tabs, grp->name, grp->nc_grpid, grp->nvars, grp->natts)); - for(att = grp->att; att; att = att->next) + for(att = grp->att; att; att = att->l.next) LOG((2, "%s GROUP ATTRIBUTE - attnum: %d name: %s type: %d len: %d", tabs, att->attnum, att->name, att->xtype, att->len)); - /* To display dims starting with 0 and going up, go through list is - * reverse order. */ - for(dim = grp->dim; dim && dim->next; dim = dim->next) - ; - for( ; dim; dim = dim->prev) + for(dim = grp->dim; dim; dim = dim->l.next) LOG((2, "%s DIMENSION - dimid: %d name: %s len: %d unlimited: %d", tabs, dim->dimid, dim->name, dim->len, dim->unlimited)); - /* To display vars starting with 0 and going up, go through list is - * reverse order. */ - for(var = grp->var; var && var->next; var = var->next) - ; - for( ; var; var = var->prev) + for(var = grp->var; var; var = var->l.next) { if(var->ndims > 0) { @@ -1467,7 +1396,7 @@ rec_print_metadata(NC_GRP_INFO_T *grp, int *tab_count) LOG((2, "%s VARIABLE - varid: %d name: %s type: %d ndims: %d dimscale: %d dimids:%s", tabs, var->varid, var->name, var->xtype, var->ndims, var->dimscale, (dims_string ? dims_string : " -"))); - for(att = var->att; att; att = att->next) + for(att = var->att; att; att = att->l.next) LOG((2, "%s VAR ATTRIBUTE - attnum: %d name: %s type: %d len: %d", tabs, att->attnum, att->name, att->xtype, att->len)); if(dims_string) @@ -1477,7 +1406,7 @@ rec_print_metadata(NC_GRP_INFO_T *grp, int *tab_count) } } - for (type = grp->type; type; type = type->next) + for (type = grp->type; type; type = type->l.next) { LOG((2, "%s TYPE - nc_typeid: %d hdf_typeid: 0x%x size: %d committed: %d " "name: %s num_fields: %d base_nc_type: %d", tabs, type->nc_typeid, @@ -1487,7 +1416,7 @@ rec_print_metadata(NC_GRP_INFO_T *grp, int *tab_count) if (type->class == NC_COMPOUND) { LOG((3, "compound type")); - for (field = type->field; field; field = field->next) + for (field = type->field; field; field = field->l.next) LOG((4, "field %s offset %d nctype %d ndims %d", field->name, field->offset, field->nctype, field->ndims)); } @@ -1508,7 +1437,7 @@ rec_print_metadata(NC_GRP_INFO_T *grp, int *tab_count) if (grp->children) { (*tab_count)++; - for (g = grp->children; g; g = g->next) + for (g = grp->children; g; g = g->l.next) if ((retval = rec_print_metadata(g, tab_count))) return retval; (*tab_count)--; diff --git a/libsrc4/nc4type.c b/libsrc4/nc4type.c index 5c2900981c..fe231fc6e8 100644 --- a/libsrc4/nc4type.c +++ b/libsrc4/nc4type.c @@ -121,7 +121,7 @@ NC4_inq_typeid(int ncid, const char *name, nc_type *typeidp) } /* Is the type in this group? If not, search parents. */ for (grp2 = grp; grp2; grp2 = grp2->parent) - for (type = grp2->type; type; type = type->next) + for (type = grp2->type; type; type = type->l.next) if (!strcmp(norm_name, type->name)) { if (typeidp) @@ -164,7 +164,7 @@ NC4_inq_typeids(int ncid, int *ntypes, int *typeids) /* If this is a netCDF-4 file, count types. */ if (h5 && grp->type) - for (type = grp->type; type; type = type->next) + for (type = grp->type; type; type = type->l.next) { if (typeids) typeids[num] = type->nc_typeid; @@ -232,9 +232,8 @@ add_user_type(int ncid, size_t size, const char *name, nc_type base_typeid, /* Remember info about this type. */ type->nc_typeid = grp->nc4_info->next_typeid++; type->size = size; - if (!(type->name = malloc((strlen(norm_name) + 1) * sizeof(char)))) + if (!(type->name = strdup(norm_name))) return NC_ENOMEM; - strcpy(type->name, norm_name); type->class = type_class; type->base_nc_type = base_typeid; @@ -393,7 +392,7 @@ NC4_inq_user_type(int ncid, nc_type typeid1, char *name, size_t *size, { *nfieldsp = 0; if (type->class == NC_COMPOUND) - for (field = type->field; field; field = field->next) + for (field = type->field; field; field = field->l.next) (*nfieldsp)++; else if (type->class == NC_ENUM) *nfieldsp = type->num_enum_members; @@ -443,7 +442,7 @@ NC4_inq_compound_field(int ncid, nc_type typeid1, int fieldid, char *name, return NC_EBADTYPE; /* Find the field. */ - for (field = type->field; field; field = field->next) + for (field = type->field; field; field = field->l.next) if (field->fieldid == fieldid) { if (name) @@ -510,7 +509,7 @@ NC4_inq_compound_fieldindex(int ncid, nc_type typeid1, const char *name, int *fi return retval; /* Find the field with this name. */ - for (field = type->field; field; field = field->next) + for (field = type->field; field; field = field->l.next) if (!strcmp(field->name, norm_name)) break; @@ -616,7 +615,7 @@ NC4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier) break; } else - enum_member = enum_member->next; + enum_member = enum_member->l.next; } /* If we didn't find it, life sucks for us. :-( */ @@ -659,7 +658,7 @@ NC4_inq_enum_member(int ncid, nc_type typeid1, int idx, char *identifier, /* Move to the desired enum member in the list. */ enum_member = type->enum_member; for (i = 0; i < idx; i++) - enum_member = enum_member->next; + enum_member = enum_member->l.next; /* Give the people what they want. */ if (identifier) @@ -710,7 +709,7 @@ NC4_insert_enum(int ncid, nc_type typeid1, const char *identifier, norm_name, value))) return retval; - type->num_enum_members++; + type->num_enum_members++; return NC_NOERR; } diff --git a/libsrc4/nc4var.c b/libsrc4/nc4var.c index 768c07710c..2dc25e1405 100644 --- a/libsrc4/nc4var.c +++ b/libsrc4/nc4var.c @@ -98,7 +98,7 @@ NC4_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems, assert(nc && grp && h5); /* Find the var. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) break; if (!var) @@ -161,7 +161,7 @@ NC4_get_var_chunk_cache(int ncid, int varid, size_t *sizep, assert(nc && grp && h5); /* Find the var. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) break; if (!var) @@ -524,7 +524,7 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype, * is not a coordinate variable. I need to change its HDF5 name, * because the dimension will cause a HDF5 dataset to be created, * and this var has the same name. */ - for (dim = grp->dim; dim; dim = dim->next) + for (dim = grp->dim; dim; dim = dim->l.next) if (!strcmp(dim->name, norm_name) && (!var->ndims || dimidsp[0] != dim->dimid)) { @@ -636,7 +636,7 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep, { if (nattsp) { - for (att = grp->att; att; att = att->next) + for (att = grp->att; att; att = att->l.next) natts++; *nattsp = natts; } @@ -644,7 +644,7 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep, } /* Find the var. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) break; @@ -664,7 +664,7 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep, dimidsp[d] = var->dimids[d]; if (nattsp) { - for (att = var->att; att; att = att->next) + for (att = var->att; att; att = att->l.next) natts++; *nattsp = natts; } @@ -757,7 +757,7 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate, assert(nc && grp && h5); /* Find the var. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) break; @@ -811,7 +811,7 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate, { #ifndef USE_SZIP return NC_EINVAL; -#endif +#else /* USE_SZIP */ if (var->deflate) return NC_EINVAL; if ((*options_mask != NC_SZIP_EC_OPTION_MASK) && @@ -823,6 +823,7 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate, var->options_mask = *options_mask; var->pixels_per_block = *pixels_per_block; var->contiguous = 0; +#endif /* USE_SZIP */ } /* Shuffle filter? */ @@ -1108,7 +1109,7 @@ NC4_inq_varid(int ncid, const char *name, int *varidp) return retval; /* Find var of this name. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (!(strcmp(var->name, norm_name))) { *varidp = var->varid; @@ -1160,12 +1161,12 @@ NC4_rename_var(int ncid, int varid, const char *name) return retval; /* Is name in use? */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (!strncmp(var->name, name, NC_MAX_NAME)) return NC_ENAMEINUSE; /* Find the var. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) break; if (!var) @@ -1270,7 +1271,7 @@ NC4_var_par_access(int ncid, int varid, int par_access) return NC_ENOPAR; /* Find the var, and set its preference. */ - for (var = grp->var; var; var = var->next) + for (var = grp->var; var; var = var->l.next) if (var->varid == varid) break; if (!var) diff --git a/libsrc4/ncfunc.c b/libsrc4/ncfunc.c index 4cfbd14e7d..bc13370ae9 100644 --- a/libsrc4/ncfunc.c +++ b/libsrc4/ncfunc.c @@ -14,29 +14,6 @@ conditions. #include "nc4internal.h" #include "nc3dispatch.h" -#ifdef IGNORE -/* Keep a linked list of file info objects. */ -extern NC_FILE_INFO_T *nc_file; -#endif - -#ifdef IGNORE -/* This function deletes a member of parliment. Be careful! Last time - * this function was used, Labor got in! This function only does - * anything for netcdf-3 files. */ - -int -nc_delete(const char *path) -{ - return NC3_delete_mp(path, 0); -} - -int -nc_delete_mp(const char *path, int basepe) -{ - return NC3_delete_mp(path, basepe); -} -#endif - /* This will return the length of a netcdf data type in bytes. Since we haven't added any new types, I just call the v3 function. Ed Hartnett 10/43/03 @@ -46,32 +23,14 @@ nc_delete_mp(const char *path, int basepe) int NC4_set_base_pe(int ncid, int pe) { -#if 0 - NC *nc; - if (!(nc = nc4_find_nc_file(ncid))) - return NC_EBADID; - if (nc->nc4_info) - return NC_ENOTNC3; - return NC3_set_base_pe(nc->int_ncid, pe); -#else return NC_ENOTNC3; -#endif } /* This function only does anything for netcdf-3 files. */ int NC4_inq_base_pe(int ncid, int *pe) { -#if 0 - NC *nc; - if (!(nc = nc4_find_nc_file(ncid))) - return NC_EBADID; - if (nc->nc4_info) - return NC_ENOTNC3; - return NC3_inq_base_pe(nc->int_ncid, pe); -#else return NC_ENOTNC3; -#endif } /* Get the format (i.e. classic, 64-bit-offset, or netcdf-4) of an @@ -80,7 +39,7 @@ int NC4_inq_format(int ncid, int *formatp) { NC *nc; - NC_HDF5_FILE_INFO_T* h5; + NC_HDF5_FILE_INFO_T* nc4_info; LOG((2, "nc_inq_format: ncid 0x%x", ncid)); @@ -88,25 +47,18 @@ NC4_inq_format(int ncid, int *formatp) return NC_NOERR; /* Find the file metadata. */ - if (!(nc = nc4_find_nc_file(ncid,&h5))) + if (!(nc = nc4_find_nc_file(ncid,&nc4_info))) return NC_EBADID; #if 0 /*def USE_PNETCDF*/ /* Take care of files created/opened with parallel-netcdf library. */ - if (h5->pnetcdf_file) + if (nc4_info->pnetcdf_file) return ncmpi_inq_format(nc->int_ncid, formatp); #endif /* USE_PNETCDF */ -#if 0 - /* If this isn't a netcdf-4 file, pass this call on to the netcdf-3 - * library. */ - if (!nc->nc4_info) - return NC3_inq_format(nc->int_ncid, formatp); -#endif - /* Otherwise, this is a netcdf-4 file. Check if classic NC3 rules * are in effect for this file. */ - if (h5->cmode & NC_CLASSIC_MODEL) + if (nc4_info->cmode & NC_CLASSIC_MODEL) *formatp = NC_FORMAT_NETCDF4_CLASSIC; else *formatp = NC_FORMAT_NETCDF4; @@ -114,4 +66,3 @@ NC4_inq_format(int ncid, int *formatp) return NC_NOERR; } - diff --git a/nc_test/test_write.c b/nc_test/test_write.c index 4a34304f8a..4e0e818951 100644 --- a/nc_test/test_write.c +++ b/nc_test/test_write.c @@ -193,69 +193,47 @@ test_nc_redef(void) error("nc_close: %s", nc_strerror(err)); /* check scratch file written as expected */ - - /* These checks don't work for the HDF5 alpha releases so far, but - * Quincey tells me this will eventually work. Until then, block - * out the tests with the HDF5_ALPHA_RELEASE macro. */ -#ifndef HDF5_ALPHA_RELEASE check_file(scratch); /* checks all except "abc" stuff added above */ -#endif - err = nc_open(scratch, NC_NOWRITE, &ncid); - IF (err) + + IF ((err = nc_open(scratch, NC_NOWRITE, &ncid))) error("nc_open: %s", nc_strerror(err)); - err = nc_inq_dim(ncid, dimid, name, &length); - IF (err) + IF ((err = nc_inq_dim(ncid, dimid, name, &length))) error("nc_inq_dim: %s", nc_strerror(err)); IF (strcmp(name, "abc") != 0) error("Unexpected dim name"); IF (length != sizehint) error("Unexpected dim length"); - err = nc_get_var1_double(ncid, varid, NULL, &var); - IF (err) + IF ((err = nc_get_var1_double(ncid, varid, NULL, &var))) error("nc_get_var1_double: %s", nc_strerror(err)); IF (var != 1.0) error("nc_get_var1_double: unexpected value"); - err = nc_close(ncid); - IF (err) + IF ((err = nc_close(ncid))) error("nc_close: %s", nc_strerror(err)); /* open scratch file for writing, add another dim, var, att, then check */ - err = nc_open(scratch, NC_WRITE, &ncid); - IF (err) + IF ((err = nc_open(scratch, NC_WRITE, &ncid))) error("nc_open: %s", nc_strerror(err)); - err = nc_redef(ncid); - IF (err) + IF ((err = nc_redef(ncid))) error("nc_redef: %s", nc_strerror(err)); - err = nc_def_dim(ncid, "def", sizehint, &dimid); - IF (err) + IF ((err = nc_def_dim(ncid, "def", sizehint, &dimid))) error("nc_def_dim: %s", nc_strerror(err)); - err = nc_def_var(ncid, "defScalar", NC_INT, 0, NULL, &varid); - IF (err) + IF ((err = nc_def_var(ncid, "defScalar", NC_INT, 0, NULL, &varid))) error("nc_def_var: %s", nc_strerror(err)); - err = nc_def_var(ncid, "def", NC_INT, 1, &dimid, &varid1); - IF (err) + IF ((err = nc_def_var(ncid, "def", NC_INT, 1, &dimid, &varid1))) error("nc_def_var: %s", nc_strerror(err)); - err = nc_put_att_text(ncid, NC_GLOBAL, "Credits", 1+strlen("Thanks!"), - "Thanks!"); - IF (err) + IF ((err = nc_put_att_text(ncid, NC_GLOBAL, "Credits", 1+strlen("Thanks!"), "Thanks!"))) error("nc_put_att_text: %s", nc_strerror(err)); - err = nc_enddef(ncid); - IF (err) + IF ((err = nc_enddef(ncid))) error("nc_enddef: %s", nc_strerror(err)); var = 2.0; - err = nc_put_var1_double(ncid, varid, NULL, &var); - IF (err) + IF ((err = nc_put_var1_double(ncid, varid, NULL, &var))) error("nc_put_var1_double: %s", nc_strerror(err)); - err = nc_close(ncid); - IF (err) + IF ((err = nc_close(ncid))) error("nc_close: %s", nc_strerror(err)); - /* These checks don't work for the HDF5 alpha releases so far, but - * Quincey tells me this will eventually work. Until then, block - * out the tests with the HDF5_ALPHA_RELEASE macro. */ -#ifndef HDF5_ALPHA_RELEASE + /* check scratch file written as expected */ check_file(scratch); -#endif + err = nc_open(scratch, NC_NOWRITE, &ncid); IF (err) error("nc_open: %s", nc_strerror(err)); diff --git a/nc_test/util.c b/nc_test/util.c index 67cd195db5..916dc6174c 100644 --- a/nc_test/util.c +++ b/nc_test/util.c @@ -756,9 +756,9 @@ check_dims(int ncid) IF (err) error("nc_inq_dim: %s", nc_strerror(err)); IF (strcmp(name, dim_name[i]) != 0) - error("Unexpected name of dimension %d", i); + error("Unexpected name of dimension %d: '%s', expected: '%s'", i, name, dim_name[i]); IF (length != dim_len[i]) - error("Unexpected length %d of dimension %d", length, i); + error("Unexpected length %d of dimension %d, expected %zu", length, i, dim_len[i]); } } diff --git a/nc_test4/Makefile.am b/nc_test4/Makefile.am index 4da5992d2f..f1bac2ae4a 100644 --- a/nc_test4/Makefile.am +++ b/nc_test4/Makefile.am @@ -21,7 +21,7 @@ tst_chunks tst_chunks2 tst_utf8 tst_fills tst_fills2 tst_fillbug \ tst_xplatform tst_xplatform2 tst_h_atts2 tst_endian_fill tst_atts \ t_type cdm_sea_soundings tst_camrun tst_vl tst_atts1 tst_atts2 \ tst_vars2 tst_files5 tst_files6 tst_sync tst_h_strbug tst_h_refs \ -tst_h_scalar tst_nvars +tst_h_scalar check_PROGRAMS = $(NC4_TESTS) renamegroup @@ -120,7 +120,7 @@ run_get_hdf4_files.sh run_valgrind_tests.sh run_valgrind_tests2.sh \ run_bm_ar4.sh ref_tst_compounds.nc run_hdf4_valgrind_tests.sh \ ref_tst_xplatform2_1.nc ref_tst_xplatform2_2.nc ref_tst_dims.nc \ ref_tst_interops4.nc run_get_knmi_files.sh CMakeLists.txt \ -run_grp_rename.sh ref_tst_nvars.nc +run_grp_rename.sh CLEANFILES = tst_mpi_parallel.bin cdm_sea_soundings.nc bm_chunking.nc \ bm_radar.nc bm_radar1.nc radar_3d_compression_test.txt \ diff --git a/nc_test4/ref_tst_nvars.nc b/nc_test4/ref_tst_nvars.nc deleted file mode 100644 index 65ae660486..0000000000 Binary files a/nc_test4/ref_tst_nvars.nc and /dev/null differ diff --git a/nc_test4/tst_atts1.c b/nc_test4/tst_atts1.c index e0fef7a40d..719bc2a870 100644 --- a/nc_test4/tst_atts1.c +++ b/nc_test4/tst_atts1.c @@ -683,13 +683,11 @@ main(int argc, char **argv) { int ncid; - /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/ - /* Create a file with a global attribute of each type of zero length. */ if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL)) ERR; if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL)) ERR; -/* if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UCHAR, ATT_LEN, uchar_out)) ERR;*/ + if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UBYTE, 0, uchar_out)) ERR; if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL)) ERR; if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL)) ERR; if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL)) ERR; @@ -701,8 +699,8 @@ main(int argc, char **argv) { int ncid; signed char schar_in[ATT_LEN]; + unsigned char uchar_in[ATT_LEN]; short short_in[ATT_LEN]; - /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/ int int_in[ATT_LEN]; float float_in[ATT_LEN]; double double_in[ATT_LEN]; @@ -716,6 +714,9 @@ main(int argc, char **argv) if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR; if (nc_inq_att(ncid, NC_GLOBAL, ATT_SCHAR_NAME, &xtype, &len)) ERR; if (len || xtype != NC_BYTE) ERR; + if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, uchar_in)) ERR; + if (nc_inq_att(ncid, NC_GLOBAL, ATT_UCHAR_NAME, &xtype, &len)) ERR; + if (len || xtype != NC_UBYTE) ERR; if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR; if (nc_inq_att(ncid, NC_GLOBAL, ATT_SHORT_NAME, &xtype, &len)) ERR; if (len || xtype != NC_SHORT) ERR; @@ -737,10 +738,11 @@ main(int argc, char **argv) } SUMMARIZE_ERR; - printf("*** testing zero-length attributes and redef...(this test skipped for HDF5-1.8.0 beta1"); + printf("*** testing zero-length attributes and redef..."); { int ncid; signed char schar_in[ATT_LEN]; + unsigned char uchar_in[ATT_LEN]; short short_in[ATT_LEN]; int int_in[ATT_LEN]; float float_in[ATT_LEN]; @@ -753,7 +755,7 @@ main(int argc, char **argv) if (nc_redef(ncid)) ERR; if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL)) ERR; if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL)) ERR; -/* if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UCHAR, ATT_LEN, uchar_out)) ERR;*/ + if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UBYTE, 0, uchar_out)) ERR; if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL)) ERR; if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL)) ERR; if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL)) ERR; @@ -765,6 +767,7 @@ main(int argc, char **argv) if (nc_open(FILE_NAME, 0, &ncid)) ERR; if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, NULL)) ERR; if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR; + if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, uchar_in)) ERR; if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR; if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR; if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR; diff --git a/nc_test4/tst_converts2.c b/nc_test4/tst_converts2.c index 8b3370da09..f6e6b94454 100644 --- a/nc_test4/tst_converts2.c +++ b/nc_test4/tst_converts2.c @@ -179,6 +179,7 @@ main(int argc, char **argv) unsigned short usvalue_in; long long int64_in; unsigned long long uint64_in; + float float_in; double double_in; /* Write a scalar NC_INT with value X_MAX_INT. */ @@ -210,9 +211,8 @@ main(int argc, char **argv) if (int64_in != ivalue) ERR; if (nc_get_var_ulonglong(ncid, varid, &uint64_in)) ERR; if (uint64_in != ivalue) ERR; -/* if (nc_get_var_float(ncid, varid, &float_in)) ERR; - f2 = (float)ivalue; - if (float_in != f2) ERR;*/ + if (nc_get_var_float(ncid, varid, &float_in)) ERR; + if (float_in != (float)ivalue) ERR; if (nc_get_var_double(ncid, varid, &double_in)) ERR; if (double_in != (double)ivalue) ERR; if (nc_close(ncid)) ERR; diff --git a/nc_test4/tst_dims.c b/nc_test4/tst_dims.c index 03a550b544..a60d0511cc 100644 --- a/nc_test4/tst_dims.c +++ b/nc_test4/tst_dims.c @@ -384,9 +384,9 @@ main(int argc, char **argv) if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR; if (ndims_in != 2 || dimids_in[0] != 0 || dimids_in[1] != 1) ERR; if (nc_inq_unlimdim(ncid, &unlimdimid_in[0])) ERR; - if (unlimdimid_in[0] != 1) ERR; + if (unlimdimid_in[0] != 0) ERR; if (nc_inq_unlimdims(ncid, &nunlimdims_in, unlimdimid_in)) ERR; - if (nunlimdims_in != 2 || unlimdimid_in[0] != 1 || unlimdimid_in[1] != 0) ERR; + if (nunlimdims_in != 2 || unlimdimid_in[0] != 0 || unlimdimid_in[1] != 1) ERR; /* Automatically enddef and close. */ if (nc_close(ncid)) ERR; @@ -986,12 +986,28 @@ main(int argc, char **argv) dimids_in, &natts_in)) ERR; if (nc_inq_dim(ncid, dimids_in[3], NULL, &len_in)) ERR; if (len_in != 0) ERR; -/* if (nc_get_var_double(ncid, pres_varid, (double *)pres_in)) ERR;*/ + memset(pres_in, 0, sizeof(pres_in)); + if (nc_get_var_double(ncid, pres_varid, (double *)pres_in)) ERR; + + /* Check our pressure values. */ + for (i = 0; i < LAT_LEN; i++) + for (j = 0; j < LON_LEN; j++) + for (k = 0; k < LEVEL_LEN; k++) + for (l = 0; l -#include -#include -#include -#define FILE_NAME "ref_tst_nvars.nc" -#define GRP_NAME "phony_group" - -void -check_err(const int stat, const int line, const char *file) { - if (stat != NC_NOERR) { - (void)fprintf(stderr,"line %d of %s: %s\n", line, file, nc_strerror(stat)); - fflush(stderr); - exit(1); - } -} - -int -main() -{ - - int ncid, varid, grpid, numvars, retval; - - if ((retval = nc_open(FILE_NAME, NC_NOWRITE, &ncid))) - check_err(retval,__LINE__,__FILE__); - - if ((retval = nc_inq_grp_ncid(ncid, GRP_NAME, &grpid))) - check_err(retval,__LINE__,__FILE__); - - if ((retval = nc_inq_nvars(grpid, &numvars))) - check_err(retval,__LINE__,__FILE__); - - (void)fprintf(stdout,"number of vars %d\n", numvars); - - - return (numvars != 1); -} diff --git a/ncgen/generate.c b/ncgen/generate.c index 443699ddd4..1d947c70ee 100644 --- a/ncgen/generate.c +++ b/ncgen/generate.c @@ -453,7 +453,7 @@ normalizeopaquelength(NCConstant* prim, unsigned long nbytes) } else {/* prim->value.opaquev.len < nnibs => expand*/ char* s; s = (char*)emalloc(nnibs+1); - memset(s,'0',nnibs); + memset(s,'0',nnibs); /* Fill with '0' characters */ memcpy(s,prim->value.opaquev.stringv,prim->value.opaquev.len); s[nnibs] = '\0'; efree(prim->value.opaquev.stringv); diff --git a/ncgen/getfill.c b/ncgen/getfill.c index 161fe1e57d..c3e5c15dc7 100644 --- a/ncgen/getfill.c +++ b/ncgen/getfill.c @@ -51,10 +51,9 @@ static void fill(Symbol* tsym, Datalist* filler) { int i; - NCConstant con; + NCConstant con = nullconstant; Datalist* sublist; - con.filled = 0; ASSERT(tsym->objectclass == NC_TYPE); switch (tsym->subclass) { case NC_ENUM: case NC_OPAQUE: case NC_PRIM: @@ -87,8 +86,7 @@ filllist(Symbol* tsym, Datalist* dl) { int i; Datalist* sublist; - NCConstant con; - con.filled = 0; + NCConstant con = nullconstant; ASSERT(tsym->objectclass == NC_TYPE); switch (tsym->subclass) { diff --git a/ncgen/ncgen.y b/ncgen/ncgen.y index e66a8e01f4..e5ade0724e 100644 --- a/ncgen/ncgen.y +++ b/ncgen/ncgen.y @@ -1172,13 +1172,22 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst) Symbol* attr = NULL; Datalist* list; NCConstant* con; - Specialdata* special = (Specialdata*)malloc(sizeof(Specialdata)); NCConstant iconst; int tf = 0; char* sdata = NULL; int idata = -1; - special->flags = 0; + if(tag == _FORMAT) { + if(vsym != NULL) { + derror("_Format: must be global attribute"); + vsym = NULL; + } + } else { + if(vsym == NULL) { + derror("%s: must have non-NULL vsym", specialname(tag)); + return NULL; + } + } specials_flag += (tag == _FILLVALUE_FLAG ? 0 : 1); @@ -1191,11 +1200,6 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst) con = (NCConstant*)list->data; } - if(tag == _FORMAT && vsym != NULL) { - derror("_Format: must be global attribute"); - vsym = NULL; - } - switch (tag) { case _FLETCHER32_FLAG: case _SHUFFLE_FLAG: @@ -1229,14 +1233,13 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst) default: PANIC1("unexpected special tag: %d",tag); } - if(vsym != NULL) special = &vsym->var.special; if(tag == _FORMAT_FLAG) { struct Kvalues* kvalue; - int found; - found = 0; + int found = 0; + /* Use the table in main.c */ - for(kvalue=legalkinds;kvalue->name;kvalue++) { - if(strcmp(sdata,kvalue->name) == 0) { + for(kvalue = legalkinds; kvalue->name; kvalue++) { + if(strcmp(sdata, kvalue->name) == 0) { format_flag = kvalue->k_flag; found = 1; break; @@ -1244,79 +1247,86 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst) } if(!found) derror("_Format: illegal value: %s",sdata); - } else if(tag == _FILLVALUE_FLAG) { - special->_Fillvalue = list; - /* fillvalue must be a single value*/ - if(list->length != 1) - derror("_FillValue: must be a single (possibly compound) value", - vsym->name); - /* check that the attribute value contains no fill values*/ - if(containsfills(list)) { - derror("Attribute data may not contain fill values (i.e. _ )"); - } - /* _FillValue is also a real attribute*/ - if(vsym->objectclass != NC_VAR) { - derror("_FillValue attribute not associated with variable: %s",vsym->name); - } - if(tsym == NULL) tsym = vsym->typ.basetype; - else if(vsym->typ.basetype != tsym) { - derror("_FillValue attribute type does not match variable type: %s",vsym->name); - } - attr=makeattribute(install("_FillValue"),vsym,tsym,list,ATTRVAR); - } else switch (tag) { - case _STORAGE_FLAG: - if(strcmp(sdata,"contiguous") == 0) - special->_Storage = NC_CONTIGUOUS; - else if(strcmp(sdata,"chunked") == 0) - special->_Storage = NC_CHUNKED; - else - derror("_Storage: illegal value: %s",sdata); - special->flags |= _STORAGE_FLAG; - break; - case _FLETCHER32_FLAG: - special->_Fletcher32 = tf; - special->flags |= _FLETCHER32_FLAG; - break; - case _DEFLATE_FLAG: - special->_DeflateLevel = idata; - special->flags |= _DEFLATE_FLAG; - break; - case _SHUFFLE_FLAG: - special->_Shuffle = tf; - special->flags |= _SHUFFLE_FLAG; - break; - case _ENDIAN_FLAG: - if(strcmp(sdata,"little") == 0) - special->_Endianness = 1; - else if(strcmp(sdata,"big") == 0) - special->_Endianness = 2; - else - derror("_Endianness: illegal value: %s",sdata); - special->flags |= _ENDIAN_FLAG; - break; - case _NOFILL_FLAG: - special->_Fill = (1 - tf); /* negate */ - special->flags |= _NOFILL_FLAG; - break; - case _CHUNKSIZES_FLAG: { - int i; - special->nchunks = list->length; - special->_ChunkSizes = (size_t*)emalloc(sizeof(size_t)*special->nchunks); - for(i=0;inchunks;i++) { - iconst.nctype = NC_INT; - convert1(&list->data[i],&iconst); - if(iconst.nctype == NC_INT) { - special->_ChunkSizes[i] = (size_t)iconst.value.int32v; - } else - derror("%s: illegal value",specialname(tag)); + } else { + Specialdata* special; + + /* Set up special info */ + special = &vsym->var.special; + special->flags = 0; + + if(tag == _FILLVALUE_FLAG) { + special->_Fillvalue = list; + /* fillvalue must be a single value*/ + if(list->length != 1) + derror("_FillValue: must be a single (possibly compound) value", + vsym->name); + /* check that the attribute value contains no fill values*/ + if(containsfills(list)) { + derror("Attribute data may not contain fill values (i.e. _ )"); } - special->flags |= _CHUNKSIZES_FLAG; - /* Chunksizes => storage == chunked */ - special->flags |= _STORAGE_FLAG; - special->_Storage = NC_CHUNKED; - } break; - default: PANIC1("makespecial: illegal token: %d",tag); - } + /* _FillValue is also a real attribute*/ + if(vsym->objectclass != NC_VAR) { + derror("_FillValue attribute not associated with variable: %s",vsym->name); + } + if(tsym == NULL) tsym = vsym->typ.basetype; + else if(vsym->typ.basetype != tsym) { + derror("_FillValue attribute type does not match variable type: %s",vsym->name); + } + attr=makeattribute(install("_FillValue"),vsym,tsym,list,ATTRVAR); + } else switch (tag) { + case _STORAGE_FLAG: + if(strcmp(sdata,"contiguous") == 0) + special->_Storage = NC_CONTIGUOUS; + else if(strcmp(sdata,"chunked") == 0) + special->_Storage = NC_CHUNKED; + else + derror("_Storage: illegal value: %s",sdata); + special->flags |= _STORAGE_FLAG; + break; + case _FLETCHER32_FLAG: + special->_Fletcher32 = tf; + special->flags |= _FLETCHER32_FLAG; + break; + case _DEFLATE_FLAG: + special->_DeflateLevel = idata; + special->flags |= _DEFLATE_FLAG; + break; + case _SHUFFLE_FLAG: + special->_Shuffle = tf; + special->flags |= _SHUFFLE_FLAG; + break; + case _ENDIAN_FLAG: + if(strcmp(sdata,"little") == 0) + special->_Endianness = 1; + else if(strcmp(sdata,"big") == 0) + special->_Endianness = 2; + else + derror("_Endianness: illegal value: %s",sdata); + special->flags |= _ENDIAN_FLAG; + break; + case _NOFILL_FLAG: + special->_Fill = (1 - tf); /* negate */ + special->flags |= _NOFILL_FLAG; + break; + case _CHUNKSIZES_FLAG: { + int i; + special->nchunks = list->length; + special->_ChunkSizes = (size_t*)emalloc(sizeof(size_t)*special->nchunks); + for(i=0;inchunks;i++) { + iconst.nctype = NC_INT; + convert1(&list->data[i],&iconst); + if(iconst.nctype == NC_INT) { + special->_ChunkSizes[i] = (size_t)iconst.value.int32v; + } else + derror("%s: illegal value",specialname(tag)); + } + special->flags |= _CHUNKSIZES_FLAG; + /* Chunksizes => storage == chunked */ + special->flags |= _STORAGE_FLAG; + special->_Storage = NC_CHUNKED; + } break; + default: PANIC1("makespecial: illegal token: %d",tag); + } return attr; } @@ -1403,11 +1413,10 @@ be returned. static NCConstant evaluate(Symbol* fcn, Datalist* arglist) { - NCConstant result; + NCConstant result = nullconstant; /* prepare the result */ result.lineno = fcn->lineno; - result.filled = 0; if(strcasecmp(fcn->name,"time") == 0) { char* timekind = NULL;