mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-04-12 18:10:24 +08:00
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:
parent
c6cbfb57f5
commit
b3044de434
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();}
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
500
libsrc4/nc4hdf.c
500
libsrc4/nc4hdf.c
@ -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;
|
||||
|
@ -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)--;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
181
ncgen/ncgen.y
181
ncgen/ncgen.y
@ -1172,13 +1172,22 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
|
||||
Symbol* attr = NULL;
|
||||
Datalist* list;
|
||||
NCConstant* con;
|
||||
Specialdata* special = (Specialdata*)malloc(sizeof(Specialdata));
|
||||
NCConstant iconst;
|
||||
int tf = 0;
|
||||
char* sdata = NULL;
|
||||
int idata = -1;
|
||||
|
||||
special->flags = 0;
|
||||
if(tag == _FORMAT) {
|
||||
if(vsym != NULL) {
|
||||
derror("_Format: must be global attribute");
|
||||
vsym = NULL;
|
||||
}
|
||||
} else {
|
||||
if(vsym == NULL) {
|
||||
derror("%s: must have non-NULL vsym", specialname(tag));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
specials_flag += (tag == _FILLVALUE_FLAG ? 0 : 1);
|
||||
|
||||
@ -1191,11 +1200,6 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
|
||||
con = (NCConstant*)list->data;
|
||||
}
|
||||
|
||||
if(tag == _FORMAT && vsym != NULL) {
|
||||
derror("_Format: must be global attribute");
|
||||
vsym = NULL;
|
||||
}
|
||||
|
||||
switch (tag) {
|
||||
case _FLETCHER32_FLAG:
|
||||
case _SHUFFLE_FLAG:
|
||||
@ -1229,14 +1233,13 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
|
||||
default: PANIC1("unexpected special tag: %d",tag);
|
||||
}
|
||||
|
||||
if(vsym != NULL) special = &vsym->var.special;
|
||||
if(tag == _FORMAT_FLAG) {
|
||||
struct Kvalues* kvalue;
|
||||
int found;
|
||||
found = 0;
|
||||
int found = 0;
|
||||
|
||||
/* Use the table in main.c */
|
||||
for(kvalue=legalkinds;kvalue->name;kvalue++) {
|
||||
if(strcmp(sdata,kvalue->name) == 0) {
|
||||
for(kvalue = legalkinds; kvalue->name; kvalue++) {
|
||||
if(strcmp(sdata, kvalue->name) == 0) {
|
||||
format_flag = kvalue->k_flag;
|
||||
found = 1;
|
||||
break;
|
||||
@ -1244,79 +1247,86 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
|
||||
}
|
||||
if(!found)
|
||||
derror("_Format: illegal value: %s",sdata);
|
||||
} else if(tag == _FILLVALUE_FLAG) {
|
||||
special->_Fillvalue = list;
|
||||
/* fillvalue must be a single value*/
|
||||
if(list->length != 1)
|
||||
derror("_FillValue: must be a single (possibly compound) value",
|
||||
vsym->name);
|
||||
/* check that the attribute value contains no fill values*/
|
||||
if(containsfills(list)) {
|
||||
derror("Attribute data may not contain fill values (i.e. _ )");
|
||||
}
|
||||
/* _FillValue is also a real attribute*/
|
||||
if(vsym->objectclass != NC_VAR) {
|
||||
derror("_FillValue attribute not associated with variable: %s",vsym->name);
|
||||
}
|
||||
if(tsym == NULL) tsym = vsym->typ.basetype;
|
||||
else if(vsym->typ.basetype != tsym) {
|
||||
derror("_FillValue attribute type does not match variable type: %s",vsym->name);
|
||||
}
|
||||
attr=makeattribute(install("_FillValue"),vsym,tsym,list,ATTRVAR);
|
||||
} else switch (tag) {
|
||||
case _STORAGE_FLAG:
|
||||
if(strcmp(sdata,"contiguous") == 0)
|
||||
special->_Storage = NC_CONTIGUOUS;
|
||||
else if(strcmp(sdata,"chunked") == 0)
|
||||
special->_Storage = NC_CHUNKED;
|
||||
else
|
||||
derror("_Storage: illegal value: %s",sdata);
|
||||
special->flags |= _STORAGE_FLAG;
|
||||
break;
|
||||
case _FLETCHER32_FLAG:
|
||||
special->_Fletcher32 = tf;
|
||||
special->flags |= _FLETCHER32_FLAG;
|
||||
break;
|
||||
case _DEFLATE_FLAG:
|
||||
special->_DeflateLevel = idata;
|
||||
special->flags |= _DEFLATE_FLAG;
|
||||
break;
|
||||
case _SHUFFLE_FLAG:
|
||||
special->_Shuffle = tf;
|
||||
special->flags |= _SHUFFLE_FLAG;
|
||||
break;
|
||||
case _ENDIAN_FLAG:
|
||||
if(strcmp(sdata,"little") == 0)
|
||||
special->_Endianness = 1;
|
||||
else if(strcmp(sdata,"big") == 0)
|
||||
special->_Endianness = 2;
|
||||
else
|
||||
derror("_Endianness: illegal value: %s",sdata);
|
||||
special->flags |= _ENDIAN_FLAG;
|
||||
break;
|
||||
case _NOFILL_FLAG:
|
||||
special->_Fill = (1 - tf); /* negate */
|
||||
special->flags |= _NOFILL_FLAG;
|
||||
break;
|
||||
case _CHUNKSIZES_FLAG: {
|
||||
int i;
|
||||
special->nchunks = list->length;
|
||||
special->_ChunkSizes = (size_t*)emalloc(sizeof(size_t)*special->nchunks);
|
||||
for(i=0;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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user