/** @param ncid - only needed for a compound type @param xtype - type for which alignment is requested */ EXTERNL size_t ncaux_type_alignment(int xtype, int ncid) { if(!NC_alignments_computed) { NC_compute_alignments(); ncaux_initialized = 1; } if(xtype <= NC_MAX_ATOMIC_TYPE) return NC_class_alignment(xtype); /* type == class */ #ifdef USE_NETCDF4 else {/* Presumably a user type */ int klass = NC_NAT; int stat = nc_inq_user_type(ncid,xtype,NULL,NULL,NULL,NULL,&klass); if(stat) goto done; switch(klass) { case NC_VLEN: return NC_class_alignment(klass); case NC_OPAQUE: return NC_class_alignment(klass); case NC_COMPOUND: {/* get alignment of the first field of the compound */ int fieldtype = NC_NAT; if((stat=nc_inq_compound_fieldtype(ncid,xtype,0,&fieldtype))) goto done; return ncaux_type_alignment(fieldtype,ncid); /* may recurse repeatedly */ } break; default: break; } } done: #endif /*USE_NETCDF4 */ return 0; /* fail */ }
static int reclaim_usertype(int ncid, int xtype, Position* offset) { int stat = NC_NOERR; size_t size; nc_type basetype; size_t nfields; int klass; /* Get info about the xtype */ stat = nc_inq_user_type(ncid, xtype, NULL, &size, &basetype, &nfields, &klass); switch (klass) { case NC_OPAQUE: stat = reclaim_opaque(ncid,xtype,size,offset); break; case NC_ENUM: stat = reclaim_enum(ncid,xtype,basetype,size,offset); break; case NC_COMPOUND: stat = reclaim_compound(ncid,xtype,size,nfields,offset); break; case NC_VLEN: stat = reclaim_vlen(ncid,xtype,basetype,offset); break; default: stat = NC_EINVAL; break; } return stat; }
int main(int argc, char **argv) { int ncid; size_t size_in; nc_type xtype; unsigned char data[DIM_LEN][BASE_SIZE], data_in[DIM_LEN][BASE_SIZE]; int i, j; printf("\n*** Testing netcdf-4 opaque type.\n"); for (i=0; i<DIM_LEN; i++) for (j=0; j<BASE_SIZE; j++) data[i][j] = 0; printf("*** testing scalar opaque variable..."); { int varid; char name_in[NC_MAX_NAME+1]; size_t nfields_in, base_size_in; nc_type base_nc_type_in, var_type; int class_in; char var_name[NC_MAX_NAME+1]; int nvars, natts, ndims, unlimdimid; /* Create a file that has an opaque variable. */ if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLOBBER, &ncid)) ERR; if (nc_def_opaque(ncid, BASE_SIZE, TYPE_NAME, &xtype)) ERR; if (nc_inq_user_type(ncid, xtype, name_in, &base_size_in, &base_nc_type_in, &nfields_in, &class_in)) ERR; if (strcmp(name_in, TYPE_NAME) || base_size_in != BASE_SIZE || base_nc_type_in != 0 || nfields_in != 0 || class_in != NC_OPAQUE) ERR; if (nc_inq_opaque(ncid, xtype, name_in, &base_size_in)) ERR; if (strcmp(name_in, TYPE_NAME) || base_size_in != BASE_SIZE) ERR; if (nc_def_var(ncid, VAR_NAME, xtype, 0, NULL, &varid)) ERR; if (nc_put_var(ncid, varid, &data[0])) ERR; if (nc_close(ncid)) ERR; /* Check it out. */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 0 || nvars != 1 || natts != 0 || unlimdimid != -1) ERR; if (nc_inq_var(ncid, 0, var_name, &var_type, &ndims, NULL, &natts)) ERR; if (ndims != 0 || strcmp(var_name, VAR_NAME) || natts != 0) ERR; if (nc_get_var(ncid, 0, &data_in[0])) ERR; for (j = 0; j < BASE_SIZE; j++) if (data_in[0][j] != data[0][j]) ERR; if (nc_close(ncid)) ERR; } SUMMARIZE_ERR; printf("*** testing opaque variable..."); { int dimid, varid, dimids[] = {0}; char name_in[NC_MAX_NAME+1]; nc_type base_nc_type_in, var_type; size_t nfields_in, base_size_in; int class_in; char var_name[NC_MAX_NAME+1]; int nvars, natts, ndims, unlimdimid, dimids_var[1]; /* Create a file that has an opaque variable. */ if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLOBBER, &ncid)) ERR; if (nc_def_opaque(ncid, BASE_SIZE, TYPE_NAME, &xtype)) ERR; if (nc_inq_user_type(ncid, xtype, name_in, &base_size_in, &base_nc_type_in, &nfields_in, &class_in)) ERR; if (strcmp(name_in, TYPE_NAME) || base_size_in != BASE_SIZE || base_nc_type_in != 0 || nfields_in != 0 || class_in != NC_OPAQUE) ERR; if (nc_inq_opaque(ncid, xtype, name_in, &base_size_in)) ERR; if (strcmp(name_in, TYPE_NAME) || base_size_in != BASE_SIZE) ERR; if (nc_def_dim(ncid, DIM_NAME, DIM_LEN, &dimid)) ERR; if (nc_def_var(ncid, VAR_NAME, xtype, 1, dimids, &varid)) ERR; if (nc_put_var(ncid, varid, data)) ERR; if (nc_close(ncid)) ERR; /* Check it out. */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 1 || nvars != 1 || natts != 0 || unlimdimid != -1) ERR; if (nc_inq_var(ncid, 0, var_name, &var_type, &ndims, dimids_var, &natts)) ERR; if (ndims != 1 || strcmp(var_name, VAR_NAME) || dimids_var[0] != dimids[0] || natts != 0) ERR; if (nc_get_var(ncid, 0, data_in)) ERR; for (i=0; i<DIM_LEN; i++) for (j=0; j<BASE_SIZE; j++) if (data_in[i][j] != data[i][j]) ERR; if (nc_close(ncid)) ERR; } SUMMARIZE_ERR; printf("*** testing *really* simple opaque attribute..."); { /* Create a file that has an opaque attribute. */ if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; if (nc_def_opaque(ncid, BASE_SIZE, TYPE_NAME, &xtype)) ERR; /* Write an att. */ if (nc_put_att(ncid, NC_GLOBAL, ATT_NAME, xtype, DIM_LEN, data)) ERR; if (nc_close(ncid)) ERR; /* Reopen. */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; if (nc_close(ncid)) ERR; } SUMMARIZE_ERR; printf("*** testing opaque attribute..."); { char name_in[NC_MAX_NAME+1]; nc_type base_nc_type_in; size_t base_size_in; size_t nfields_in; int class_in; /* Create a file that has an opaque attribute. */ if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; if (nc_def_opaque(ncid, BASE_SIZE, TYPE_NAME, &xtype)) ERR; /* Check it out. */ if (nc_inq_user_type(ncid, xtype, name_in, &base_size_in, &base_nc_type_in, &nfields_in, &class_in)) ERR; if (strcmp(name_in, TYPE_NAME) || base_size_in != BASE_SIZE || base_nc_type_in != 0 || nfields_in != 0 || class_in != NC_OPAQUE) ERR; if (nc_inq_opaque(ncid, xtype, name_in, &base_size_in)) ERR; if (strcmp(name_in, TYPE_NAME) || base_size_in != BASE_SIZE) ERR; /* Write an att. */ if (nc_put_att(ncid, NC_GLOBAL, ATT_NAME, xtype, DIM_LEN, data)) ERR; if (nc_close(ncid)) ERR; /* Reopen. */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; /* Check it out. */ if (nc_inq_att(ncid, NC_GLOBAL, ATT_NAME, &xtype, &size_in)) ERR; if (size_in != DIM_LEN) ERR; if (nc_inq_user_type(ncid, xtype, name_in, &base_size_in, &base_nc_type_in, &nfields_in, &class_in)) ERR; if (strcmp(name_in, TYPE_NAME) || base_size_in != BASE_SIZE || base_nc_type_in != 0 || nfields_in != 0 || class_in != NC_OPAQUE) ERR; if (nc_inq_opaque(ncid, xtype, name_in, &base_size_in)) ERR; if (strcmp(name_in, TYPE_NAME) || base_size_in != BASE_SIZE) ERR; if (nc_get_att(ncid, NC_GLOBAL, ATT_NAME, data_in)) ERR; for (i=0; i<DIM_LEN; i++) for (j=0; j<BASE_SIZE; j++) if (data_in[i][j] != data[i][j]) ERR; if (nc_close(ncid)) ERR; } SUMMARIZE_ERR; printf("*** testing 3 opaque types..."); { #define TYPE_SIZE1 20 #define NUM_TYPES 3 char name_in[NC_MAX_NAME+1]; nc_type base_nc_type_in; size_t nfields_in, base_size_in; nc_type otid[3]; int class_in; char type_name[NUM_TYPES][NC_MAX_NAME + 1] = {"o1", "o2", "o3"}; int nvars, natts, ndims, unlimdimid; int ntypes, typeids[NUM_TYPES]; int i; /* Create a file that has three opaque types. */ if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLOBBER, &ncid)) ERR; for (i = 0; i < NUM_TYPES; i++) { if (nc_def_opaque(ncid, TYPE_SIZE1, type_name[i], &otid[i])) ERR; if (nc_inq_user_type(ncid, otid[i], name_in, &base_size_in, &base_nc_type_in, &nfields_in, &class_in)) ERR; if (strcmp(name_in, type_name[i]) || base_size_in != TYPE_SIZE1 || base_nc_type_in != 0 || nfields_in != 0 || class_in != NC_OPAQUE) ERR; if (nc_inq_opaque(ncid, otid[i], name_in, &base_size_in)) ERR; if (strcmp(name_in, type_name[i]) || base_size_in != TYPE_SIZE1) ERR; } if (nc_close(ncid)) ERR; /* Check it out. */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 0 || nvars != 0 || natts != 0 || unlimdimid != -1) ERR; if (nc_inq_typeids(ncid, &ntypes, typeids)) ERR; if (ntypes != NUM_TYPES) ERR; for (i = 0; i < NUM_TYPES; i++) { if (nc_inq_user_type(ncid, otid[i], name_in, &base_size_in, &base_nc_type_in, &nfields_in, &class_in)) ERR; if (strcmp(name_in, type_name[i]) || base_size_in != TYPE_SIZE1 || base_nc_type_in != 0 || nfields_in != 0 || class_in != NC_OPAQUE) ERR; if (nc_inq_opaque(ncid, otid[i], name_in, &base_size_in)) ERR; if (strcmp(name_in, type_name[i]) || base_size_in != TYPE_SIZE1) ERR; } if (nc_close(ncid)) ERR; } SUMMARIZE_ERR; FINAL_RESULTS; }
/* Given an ncid, check the file to make sure it has all the objects I * expect. */ int check_nc4_file(int ncid) { int varid, dimid, attnum, grpid, grpid2, grpid3, numgrps; int numtypes, enum_typeid, comp_typeid; int class_in; size_t att_len, size_in, num_mem, nfields_in; nc_type att_type, base_type_in; char name_in[NC_MAX_NAME + 1], strings_in[NC_MAX_NAME + 1], value; /* Check the group. */ if (nc_inq_grps(ncid, &numgrps, &grpid)) ERR; if (numgrps != 1) ERR; name_in[0] = 0; if (nc_inq_grpname(grpid, name_in)) ERR; if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR; /* Check the variable. */ if (nc_inq_varid(grpid, name_utf8, &varid)) ERR; if (nc_inq_varname(grpid, varid, name_in)) ERR; if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR; if (nc_inq_varid(grpid, norm_utf8, &varid)) ERR; name_in[0] = 0; if (nc_inq_varname(grpid, varid, name_in)) ERR; if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR; if (nc_get_var(grpid, varid, strings_in)) ERR; if (strncmp(name_utf8, strings_in, sizeof(name_utf8))) ERR; strings_in[0] = '\0'; /* Reset my string buffer. */ /* Check the dimension. */ if (nc_inq_dimid(grpid, name_utf8, &dimid)) ERR; if (nc_inq_dimname(grpid, dimid, name_in)) ERR; if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR; if (nc_inq_dimid(grpid, norm_utf8, &dimid)) ERR; if (nc_inq_dimname(grpid, dimid, name_in)) ERR; if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR; /* Check the attribute. We don't normalize data or attribute * values, so get exactly what was put for the value, but * normalized values for names. */ if (nc_inq_attid(grpid, varid, norm_utf8, &attnum)) ERR; if (attnum) ERR; attnum = 99; /* Reset. */ if (nc_inq_attid(grpid, varid, name_utf8, &attnum)) ERR; if (attnum) ERR; if (nc_inq_att(grpid, varid, norm_utf8, &att_type, &att_len)) ERR; if (att_type != NC_CHAR || att_len != sizeof(name_utf8)) ERR; if (nc_get_att_text(grpid, varid, norm_utf8, strings_in)) ERR; if (strncmp(name_utf8, strings_in, sizeof(name_utf8))) ERR; /* Check the enum type. */ if (nc_inq_grps(grpid, &numgrps, &grpid2)) ERR; if (numgrps != 1) ERR; if (nc_inq_typeids(grpid2, &numtypes, &enum_typeid)) ERR; if (numtypes != 1) ERR; if (nc_inq_user_type(grpid2, enum_typeid, name_in, &size_in, &base_type_in, &nfields_in, &class_in)) ERR; if (strncmp(norm_utf8, name_in, strlen(norm_utf8)) || size_in != 1 || base_type_in != NC_BYTE || nfields_in != 1 || class_in != NC_ENUM) ERR; name_in[0] = size_in = base_type_in = 0; if (nc_inq_enum(grpid2, enum_typeid, name_in, &base_type_in, &size_in, &num_mem)) ERR; if (strncmp(norm_utf8, name_in, strlen(norm_utf8)) || size_in != 1 || base_type_in != NC_BYTE || num_mem != 1) ERR; if (nc_inq_enum_member(grpid2, enum_typeid, 0, name_in, &value)) ERR; if (strncmp(norm_utf8, name_in, sizeof(norm_utf8)) || value != ENUM_VALUE) ERR; /* Check the compound type. */ if (nc_inq_grps(grpid2, &numgrps, &grpid3)) ERR; if (numgrps != 1) ERR; if (nc_inq_typeids(grpid3, &numtypes, &comp_typeid)) ERR; if (numtypes != 1) ERR; name_in[0] = 0; if (nc_inq_user_type(grpid3, comp_typeid, name_in, &size_in, &base_type_in, &nfields_in, &class_in)) ERR; if (strncmp(norm_utf8, name_in, sizeof(norm_utf8)) || size_in != sizeof(struct comp) || base_type_in != NC_NAT || nfields_in != 1 || class_in != NC_COMPOUND) ERR; size_in = nfields_in = 999; if (nc_inq_compound(grpid3, comp_typeid, name_in, &size_in, &nfields_in)) ERR; if (strncmp(norm_utf8, name_in, sizeof(norm_utf8)) || size_in != sizeof(struct comp) || nfields_in != 1) ERR; name_in[0] = 0; if (nc_inq_compound_fieldname(grpid3, comp_typeid, 0, name_in)) ERR; if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR; return NC_NOERR; }
static int NC_meta_create_type1(int ncid, nc_type xtype, MetaNode* root, MetaNode** typenodep) { int ncstat = NC_NOERR; int i; MetaNode* node; nc_meta metatype = NC_NAT; /* Determine the top-level type for xtype */ ncstat = mapnctype(ncid,xtype,&metatype); if(ncstat != NC_NOERR) goto done; node = NC_meta_alloc(metatype); node->ncid = ncid; node->xtype = xtype; switch (node->nodeclass) { case NC_ATOMIC: ncstat = nc_inq_type(ncid,xtype,node->name,&node->size); if(ncstat != NC_NOERR) goto fail; break; case NC_OPAQUE: ncstat = nc_inq_opaque(ncid,xtype,node->name,&node->size); if(ncstat != NC_NOERR) goto fail; break; case NC_ENUM: ncstat = nc_inq_enum(ncid,xtype,node->name,&node->basetype, &node->size,&node->nelems); if(ncstat != NC_NOERR) goto fail; /* Now, create and fill in the enum constants */ node->econsts = (struct MetaEconst*)calloc(node->nelems, sizeof(struct MetaEconst)); if(node->econsts == NULL) {ncstat = NC_ENOMEM;goto fail;} for(i=0;i<node->nelems;i++) { struct MetaEconst* econst = node->consts+i; ncstat = nc_inq_enum_member(ncid,xtype,i, econst->name, (void*)econst->value); if(ncstat != NC_NOERR) goto fail; } break; case NC_COMPOUND: ncstat = nc_inq_compound(ncid,xtype,node->name,&node->size, &node->nelems); if(ncstat != NC_NOERR) goto fail; /* Now, create and fill in the fields */ node->compound.fields = nc_meta_allocn(NC_FIELD,node->nelems); if(node->compound.fields == NULL) {ncstat = NC_ENOMEM;goto fail;} for(i=0;i<node->nelems;i++) { MetaNode* field = node->compound.fields+i; nc_type basetype; ncstat = nc_inq_compound_field(ncid,xtype,i, field->name, &field->offset, &basetype, &field->ndims, field->dims); if(ncstat != NC_NOERR) goto fail; /* create basetype */ ncstat = NC_meta_create_type(ncid,basetype,root,&field->basetype); if(ncstat != NC_NOERR) goto fail; } break; case NC_VLEN: { nc_type basetype; ncstat = nc_inq_vlen(ncid,xtype,node->name,&node->size,&basetype); if(ncstat != NC_NOERR) goto fail; /* create basetype */ ncstat = NC_meta_create_type(ncid,basetype,root,&node->basetype); if(ncstat != NC_NOERR) goto fail; } break; case NC_GROUP: { nc_type* typeids; ncstat = nc_inq_typeids(ncid,&node->nelems,NULL); if(ncstat != NC_NOERR) goto fail; typeids = (nc_type*)calloc(node->nelems,sizeof(nc_type)); if(typeids == NULL) {ncstat = NC_ENOMEM; goto fail;} ncstat = nc_inq_typeids(ncid,&node->nelems,typeids); if(ncstat != NC_NOERR) goto fail; break; default: abort(); } } static int mapnctype(int ncid, nc_type xtype, nc_meta* metatypep) { int ncstat = NC_NOERR; if(metatypep == NULL) goto done; if(xtype <= NC_MAX_ATOMIC_TYPE) goto done; ncstat = nc_inq_user_type(ncid,xtype,NULL,NULL,NULL,NULL,metatypep); done: return ncstat; }