Refactored read_scale(), memio_new(), var_create_dataset() and makespecial()

to clean up resources properly on failure.

Refactored doubly-linked list code for objects in the libsrc4 directory,
    cleaning up the add/del routines, breaking out the common next/prev
    pointers into a struct and extracting the add/del operations on them,
    changed the list of dims to add new dims in the same order as the other
    types, made all add routines able to optionally return a pointer to the
    newly created object.

Removed some dead code (pg_var(), nc4_pg_var1(), nc4_pg_varm(), misc. small
    routines, etc)

Fixed fill value handling for string types in nc4_get_vara().

Changed many malloc()+strcpy() pairs into calls to strdup().

Cleaned up misc. other minor Coverity issues.
This commit is contained in:
Quincey Koziol 2013-12-08 03:29:26 -06:00
parent c6cbfb57f5
commit b3044de434
17 changed files with 507 additions and 1071 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -47,12 +47,6 @@ 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 +475,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 (!(grp->dim->name = malloc((strlen(obj_name) + 1) * sizeof(char))))
return NC_ENOMEM;
strcpy(grp->dim->name, obj_name);
if (SIZEOF_SIZE_T < 8 && scale_size > NC_MAX_UINT)
{
grp->dim->len = NC_MAX_UINT;
grp->dim->too_long = 1;
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
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];
{
/* Assign dimid */
new_dim->dimid = grp->nc4_info->next_dimid++;
}
/* 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)
{
new_dim->len = NC_MAX_UINT;
new_dim->too_long = 1;
}
else
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 +542,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 +604,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 +1190,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 +1363,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 +1605,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 +1675,6 @@ 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);
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 +1690,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);
@ -1711,6 +1717,9 @@ read_grp_atts(NC_GRP_INFO_T *grp)
if (type)
att->class = type->class;
}
if (H5Aclose(attid) < 0)
BAIL(NC_EATTMETA);
attid = 0;
}
exit:
@ -1782,7 +1791,6 @@ nc4_rec_read_metadata_cb(hid_t grpid, const char *name, const H5L_info_t *info,
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;
@ -1800,16 +1808,20 @@ nc4_rec_read_metadata_cb(hid_t grpid, const char *name, const H5L_info_t *info,
switch(statbuf.type)
{
case H5G_GROUP:
LOG((3, "found group %s", oname));
{
NC_GRP_INFO_T *child_grp;
/* 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;
LOG((3, "found group %s", oname));
/* Recursively read the child group's metadata */
if (nc4_rec_read_metadata(child_grp))
return H5_ITER_ERROR;
/* 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;
/* Recursively read the child group's metadata */
if (nc4_rec_read_metadata(child_grp))
return H5_ITER_ERROR;
}
break;
case H5G_DATASET:
@ -2137,7 +2149,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 +2187,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 +2216,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 +2231,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 +2329,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 +2338,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 +2363,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 +2393,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 +2904,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 +2929,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;

View File

@ -18,7 +18,7 @@ $Id: nc4grp.c,v 1.44 2010/05/25 17:54:23 dmh Exp $
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);

View File

@ -23,10 +23,6 @@
#include <pnetcdf.h>
#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; i<var->ndims; 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; i<var->ndims; i++)
LOG((4, "start[%d] %d", i, start[i]));
if (edges)
for (i=0; i<var->ndims; i++)
LOG((4, "edges[%d] %d", i, edges[i]));
if (stride)
for (i=0; i<var->ndims; i++)
LOG((4, "stride[%d] %d", i, stride[i]));
if (map)
for (i=0; i<var->ndims; 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;

View File

@ -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 object to the end of a list. */
static void
obj_list_add(NC_LIST_NODE_T **list, NC_LIST_NODE_T *obj)
{
/* 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)
{
NC_LIST_NODE_T *o;
for (o = *list; o; o = o->next)
if (!o->next)
break;
o->next = obj;
obj->prev = o;
}
else
*list = obj;
}
/* 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;
if(obj->next)
((NC_LIST_NODE_T *)obj->next)->prev = obj->prev;
}
/* 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)
{
NC_VAR_INFO_T *v;
NC_VAR_INFO_T *new_var;
/* Allocate storage for new variable. */
if (!(*var = calloc(1, sizeof(NC_VAR_INFO_T))))
if (!(new_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. */
if(*list)
{
for (v = *list; v; v = v->next)
if (!v->next)
break;
v->next = *var;
(*var)->prev = v;
}
else
*list = *var;
/* 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;
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. */
int
nc4_dim_list_add(NC_DIM_INFO_T **list)
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;
/* 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;
}
/* 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)
{
NC_DIM_INFO_T *dim;
if (!(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;
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
{
*list = *grp;
}
/* 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))))
new_grp->nc_grpid = new_nc_grpid;
new_grp->parent = parent_grp;
if (!(new_grp->name = strdup(name)))
{
free(new_grp);
return NC_ENOMEM;
strcpy((*grp)->name, name);
(*grp)->nc4_info = NC4_DATA(nc);
}
new_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)--;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;i<special->nchunks;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;i<special->nchunks;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;