/* get group id in output corresponding to group igrp in input, * given parent group id (or root group id) parid in output. */ static int get_grpid(int igrp, int parid, int *ogrpp) { int stat = NC_NOERR; int ogid; /* like igrp but in output file */ #ifdef USE_NETCDF4 int inparid; /* if not root group, get corresponding output groupid from group name */ stat = nc_inq_grp_parent(igrp, &inparid); if(stat == NC_NOERR) { /* not root group */ char grpname[NC_MAX_NAME + 1]; NC_CHECK(nc_inq_grpname(igrp, grpname)); NC_CHECK(nc_inq_grp_ncid(parid, grpname, &ogid)); } else if(stat == NC_ENOGRP) { /* root group */ ogid = parid; stat = NC_NOERR; } else { NC_CHECK(stat); } #else ogid = parid; #endif /* USE_NETCDF4 */ *ogrpp = ogid; return stat; }
/* Find the full path name to the group represented by ncid. Either * pointer argument may be NULL; pass a NULL for the third parameter * to get the length of the full path name. The length will not * include room for a null pointer. */ EXTERNL int nc_inq_grpname_full(int ncid, size_t *lenp, char *full_name) { char *name, grp_name[NC_MAX_NAME + 1]; int g, id = ncid, parent_id, *gid; int i, ret = NC_NOERR; /* How many generations? */ for (g = 0; !nc_inq_grp_parent(id, &parent_id); g++, id = parent_id) ; /* Allocate storage. */ if (!(name = malloc((g + 1) * (NC_MAX_NAME + 1) + 1))) return NC_ENOMEM; if (!(gid = malloc((g + 1) * sizeof(int)))) { free(name); return NC_ENOMEM; } assert(name && gid); /* Always start with a "/" for the root group. */ strcpy(name, "/"); /* Get the ncids for all generations. */ gid[0] = ncid; for (i = 1; i < g && !ret; i++) ret = nc_inq_grp_parent(gid[i - 1], &gid[i]); /* Assemble the full name. */ for (i = g - 1; !ret && i >= 0 && !ret; i--) { if ((ret = nc_inq_grpname(gid[i], grp_name))) break; strcat(name, grp_name); if (i) strcat(name, "/"); } /* Give the user the length of the name, if he wants it. */ if (!ret && lenp) *lenp = strlen(name); /* Give the user the name, if he wants it. */ if (!ret && full_name) strcpy(full_name, name); free(gid); free(name); return ret; }
/* Input: sx_root_id: integer group id Outputs: sx_ierr: set to 0 on success, -1 on failure returned value: a string witht he group name */ SEXP R_nc4_grpname(SEXP sx_root_id, SEXP sx_ierr_retval) { int root_id, ierr; size_t nchar; char *str; SEXP sx_retval, sx_string; INTEGER(sx_ierr_retval)[0] = 0; /* start with 'no error' condition */ /* Make sure our passed args are the right type and size */ if (!IS_INTEGER(sx_root_id) || LENGTH(sx_root_id)!=1) Rf_error("Passed argument sx_root_id must be 'integer(1)'"); if (!IS_INTEGER(sx_ierr_retval) || LENGTH(sx_ierr_retval)!=1) Rf_error("Passed argument sx_ierr_retval must be 'integer(1)'"); /* Turn R sx_value into ordinary integer */ root_id = INTEGER(sx_root_id)[0]; /* Get # of chars in group name */ ierr = nc_inq_grpname_len( root_id, &nchar ); if( ierr != 0 ) { Rprintf( "Error in R_nc_grpname: on call to nc_inq_grpname_len: %s\n", nc_strerror(ierr) ); INTEGER(sx_ierr_retval)[0] = -1; /* Indicate error condition */ return( NULL ); } /* Make space for C string to be returned */ str = R_alloc(nchar + 1, sizeof(char)); ierr = nc_inq_grpname( root_id, str ); if( ierr != 0 ) { Rprintf( "Error in R_nc_grpname: on call to nc_inq_grpname: %s\n", nc_strerror(ierr) ); INTEGER(sx_ierr_retval)[0] = -1; /* Indicate error condition */ return( NULL ); } str[nchar] = '\0'; sx_retval = PROTECT(NEW_CHARACTER(1)); sx_string = PROTECT(mkChar(str)); SET_STRING_ELT(sx_retval, 0, sx_string); UNPROTECT(2); return(sx_retval); }
/* 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; }