NetCDF  4.9.3
nc4type.c
Go to the documentation of this file.
1 /* Copyright 2005, University Corporation for Atmospheric Research. See
2  * the COPYRIGHT file for copying and redistribution conditions. */
14 #include "nc4internal.h"
15 #include "nc4dispatch.h"
16 #include <stddef.h>
17 
31 int
32 NC4_inq_typeids(int ncid, int *ntypes, int *typeids)
33 {
34  NC_GRP_INFO_T *grp;
35  NC_FILE_INFO_T *h5;
36  NC_TYPE_INFO_T *type;
37  int num = 0;
38  int retval;
39 
40  LOG((2, "nc_inq_typeids: ncid 0x%x", ncid));
41 
42  /* Find info for this file and group, and set pointer to each. */
43  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
44  return retval;
45  assert(h5 && grp);
46 
47  /* Count types. */
48  if (grp->type) {
49  for(size_t i=0;i<ncindexsize(grp->type);i++)
50  {
51  if((type = (NC_TYPE_INFO_T*)ncindexith(grp->type,i)) == NULL) continue;
52  if (typeids)
53  typeids[num] = type->hdr.id;
54  num++;
55  }
56  }
57 
58  /* Give the count to the user. */
59  if (ntypes)
60  *ntypes = num;
61 
62  return NC_NOERR;
63 }
64 
79 int
80 NC4_inq_type(int ncid, nc_type typeid1, char *name, size_t *size)
81 {
82  NC_GRP_INFO_T *grp;
83  NC_TYPE_INFO_T *type;
84 
85  int retval;
86 
87  LOG((2, "nc_inq_type: ncid 0x%x typeid %d", ncid, typeid1));
88 
89  /* If this is an atomic type, the answer is easy. */
90  if (typeid1 < NUM_ATOMIC_TYPES)
91  {
92  if((retval=NC4_inq_atomic_type(typeid1, name, size))) return retval;
93  return NC_NOERR;
94  }
95 
96  /* Not an atomic type - so find group. */
97  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
98  return retval;
99 
100  /* Find this type. */
101  if (!(type = nclistget(grp->nc4_info->alltypes, (size_t)typeid1)))
102  return NC_EBADTYPE;
103 
104  if (name)
105  strcpy(name, type->hdr.name);
106 
107  if (size)
108  {
109  if (type->nc_type_class == NC_VLEN)
110  *size = sizeof(nc_vlen_t);
111  else
112  *size = type->size;
113  }
114 
115  return NC_NOERR;
116 }
117 
134 int
135 NC4_inq_user_type(int ncid, nc_type typeid1, char *name, size_t *size,
136  nc_type *base_nc_typep, size_t *nfieldsp, int *classp)
137 {
138  NC_GRP_INFO_T *grp;
139  NC_TYPE_INFO_T *type;
140  int retval;
141 
142  LOG((2, "nc_inq_user_type: ncid 0x%x typeid %d", ncid, typeid1));
143 
144  /* Find group metadata. */
145  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
146  return retval;
147 
148  /* Find this type. */
149  if (!(type = nclistget(grp->nc4_info->alltypes, (size_t)typeid1)))
150  return NC_EBADTYPE;
151 
152  /* Count the number of fields. */
153  if (nfieldsp)
154  {
155  if (type->nc_type_class == NC_COMPOUND)
156  *nfieldsp = nclistlength(type->u.c.field);
157  else if (type->nc_type_class == NC_ENUM)
158  *nfieldsp = nclistlength(type->u.e.enum_member);
159  else
160  *nfieldsp = 0;
161  }
162 
163  /* Fill in size and name info, if desired. */
164  if (size)
165  {
166  if (type->nc_type_class == NC_VLEN)
167  *size = sizeof(nc_vlen_t);
168  else if (type->nc_type_class == NC_STRING) {
169  if((retval=NC4_inq_type(ncid,typeid1,NULL,size))) return retval;
170  } else
171  *size = type->size;
172  }
173  if (name)
174  strcpy(name, type->hdr.name);
175 
176  /* VLENS and ENUMs have a base type - that is, they type they are
177  * arrays of or enums of. */
178  if (base_nc_typep)
179  {
180  if (type->nc_type_class == NC_ENUM)
181  *base_nc_typep = type->u.e.base_nc_typeid;
182  else if (type->nc_type_class == NC_VLEN)
183  *base_nc_typep = type->u.v.base_nc_typeid;
184  else
185  *base_nc_typep = NC_NAT;
186  }
187 
188  /* If the user wants it, tell whether this is a compound, opaque,
189  * vlen, enum, or string class of type. */
190  if (classp)
191  *classp = type->nc_type_class;
192 
193  return NC_NOERR;
194 }
195 
213 int
214 NC4_inq_compound_field(int ncid, nc_type typeid1, int fieldid, char *name,
215  size_t *offsetp, nc_type *field_typeidp, int *ndimsp,
216  int *dim_sizesp)
217 {
218  NC_GRP_INFO_T *grp;
219  NC_TYPE_INFO_T *type;
220  NC_FIELD_INFO_T *field;
221  int d, retval;
222 
223  /* Find file metadata. */
224  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
225  return retval;
226 
227  /* Find this type. */
228  if (!(type = nclistget(grp->nc4_info->alltypes, (size_t)typeid1)))
229  return NC_EBADTYPE;
230 
231  /* Find the field. */
232  if (!(field = nclistget(type->u.c.field, (size_t)fieldid)))
233  return NC_EBADFIELD;
234 
235  if (name)
236  strcpy(name, field->hdr.name);
237  if (offsetp)
238  *offsetp = field->offset;
239  if (field_typeidp)
240  *field_typeidp = field->nc_typeid;
241  if (ndimsp)
242  *ndimsp = field->ndims;
243  if (dim_sizesp)
244  for (d = 0; d < field->ndims; d++)
245  dim_sizesp[d] = field->dim_size[d];
246 
247  return NC_NOERR;
248 }
249 
264 int
265 NC4_inq_compound_fieldindex(int ncid, nc_type typeid1, const char *name, int *fieldidp)
266 {
267  NC_FILE_INFO_T *h5;
268  NC_TYPE_INFO_T *type;
269  NC_FIELD_INFO_T *field;
270  char norm_name[NC_MAX_NAME + 1];
271  int retval;
272  size_t i;
273 
274  LOG((2, "nc_inq_compound_fieldindex: ncid 0x%x typeid %d name %s",
275  ncid, typeid1, name));
276 
277  /* Find file metadata. */
278  if ((retval = nc4_find_grp_h5(ncid, NULL, &h5)))
279  return retval;
280 
281  /* Find the type. */
282  if ((retval = nc4_find_type(h5, typeid1, &type)))
283  return retval;
284 
285  /* Did the user give us a good compound type typeid? */
286  if (!type || type->nc_type_class != NC_COMPOUND)
287  return NC_EBADTYPE;
288 
289  /* Normalize name. */
290  if ((retval = nc4_normalize_name(name, norm_name)))
291  return retval;
292 
293  /* Find the field with this name. */
294  for (i = 0; i < nclistlength(type->u.c.field); i++)
295  {
296  field = nclistget(type->u.c.field, i);
297  assert(field);
298  if (!strcmp(field->hdr.name, norm_name))
299  break;
300  field = NULL; /* because this is the indicator of not found */
301  }
302 
303  if (!field)
304  return NC_EBADFIELD;
305 
306  if (fieldidp)
307  *fieldidp = field->hdr.id;
308  return NC_NOERR;
309 }
310 
327 int
328 NC4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier)
329 {
330  NC_GRP_INFO_T *grp;
331  NC_TYPE_INFO_T *type;
332  NC_ENUM_MEMBER_INFO_T *enum_member;
333  long long ll_val;
334  size_t i;
335  int retval;
336  int found;
337 
338  LOG((3, "nc_inq_enum_ident: xtype %d value %d\n", xtype, value));
339 
340  /* Find group metadata. */
341  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
342  return retval;
343 
344  /* Find this type. */
345  if (!(type = nclistget(grp->nc4_info->alltypes, (size_t)xtype)))
346  return NC_EBADTYPE;
347 
348  /* Complain if they are confused about the type. */
349  if (type->nc_type_class != NC_ENUM)
350  return NC_EBADTYPE;
351 
352  /* Move to the desired enum member in the list. */
353  for (found = 0, i = 0; i < nclistlength(type->u.e.enum_member); i++)
354  {
355  enum_member = nclistget(type->u.e.enum_member, i);
356  assert(enum_member);
357  switch (type->u.e.base_nc_typeid)
358  {
359  case NC_BYTE:
360  ll_val = *(char *)enum_member->value;
361  break;
362  case NC_UBYTE:
363  ll_val = *(unsigned char *)enum_member->value;
364  break;
365  case NC_SHORT:
366  ll_val = *(short *)enum_member->value;
367  break;
368  case NC_USHORT:
369  ll_val = *(unsigned short *)enum_member->value;
370  break;
371  case NC_INT:
372  ll_val = *(int *)enum_member->value;
373  break;
374  case NC_UINT:
375  ll_val = *(unsigned int *)enum_member->value;
376  break;
377  case NC_INT64:
378  case NC_UINT64:
379  ll_val = *(long long *)enum_member->value;
380  break;
381  default:
382  return NC_EINVAL;
383  }
384  LOG((4, "ll_val=%d", ll_val));
385  if (ll_val == value)
386  {
387  if (identifier)
388  strcpy(identifier, enum_member->name);
389  found = 1;
390  break;
391  }
392  }
393 
394  /* If we didn't find it, life sucks for us. :-( */
395  if(!found) {
396  if(value == 0) /* Special case for HDF5 default Fill Value*/
397  strcpy(identifier, NC_UNDEFINED_ENUM_IDENT);
398  else
399  return NC_EINVAL;
400  }
401 
402  return NC_NOERR;
403 }
404 
421 int
422 NC4_inq_enum_member(int ncid, nc_type typeid1, int idx, char *identifier,
423  void *value)
424 {
425  NC_GRP_INFO_T *grp;
426  NC_TYPE_INFO_T *type;
427  NC_ENUM_MEMBER_INFO_T *enum_member;
428  int retval;
429 
430  LOG((2, "nc_inq_enum_member: ncid 0x%x typeid %d", ncid, typeid1));
431 
432  /* Find group metadata. */
433  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
434  return retval;
435 
436  /* Find this type. */
437  if (!(type = nclistget(grp->nc4_info->alltypes, (size_t)typeid1)))
438  return NC_EBADTYPE;
439 
440  /* Complain if they are confused about the type. */
441  if (type->nc_type_class != NC_ENUM)
442  return NC_EBADTYPE;
443 
444  /* Move to the desired enum member in the list. */
445  if (!(enum_member = nclistget(type->u.e.enum_member, (size_t)idx)))
446  return NC_EINVAL;
447 
448  /* Give the people what they want. */
449  if (identifier)
450  strcpy(identifier, enum_member->name);
451  if (value)
452  memcpy(value, enum_member->value, type->size);
453 
454  return NC_NOERR;
455 }
456 
471 EXTERNL int
472 NC4_inq_typeid(int ncid, const char *name, nc_type *typeidp)
473 {
474  NC_GRP_INFO_T *grp;
475  NC_GRP_INFO_T *grptwo;
476  NC_FILE_INFO_T *h5;
477  NC_TYPE_INFO_T *type = NULL;
478  char *norm_name = NULL;
479  int i, retval = NC_NOERR;
480 
481  /* Handle atomic types. */
482  for (i = 0; i < NUM_ATOMIC_TYPES; i++)
483  if (!strcmp(name, nc4_atomic_name[i]))
484  {
485  if (typeidp)
486  *typeidp = i;
487  goto done;
488  }
489 
490  /* Find info for this file and group, and set pointer to each. */
491  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
492  goto done;
493  assert(h5 && grp);
494 
495  /* If the first char is a /, this is a fully-qualified
496  * name. Otherwise, this had better be a local name (i.e. no / in
497  * the middle). */
498  if (name[0] != '/' && strstr(name, "/"))
499  {retval = NC_EINVAL; goto done;}
500 
501  /* Normalize name. */
502  if (!(norm_name = (char*)malloc(strlen(name) + 1)))
503  {retval = NC_ENOMEM; goto done;}
504  if ((retval = nc4_normalize_name(name, norm_name)))
505  goto done;
506 
507  /* If this is a fqn, then walk the sequence of parent groups to the last group
508  and see if that group has a type of the right name */
509  if(name[0] == '/') { /* FQN */
510  int rootncid = (grp->nc4_info->root_grp->hdr.id | grp->nc4_info->controller->ext_ncid);
511  int parent = 0;
512  char* lastname = strrchr(norm_name,'/'); /* break off the last segment: the type name */
513  if(lastname == norm_name)
514  {retval = NC_EINVAL; goto done;}
515  *lastname++ = '\0'; /* break off the lastsegment */
516  if((retval = NC4_inq_grp_full_ncid(rootncid,norm_name,&parent)))
517  goto done;
518  /* Get parent info */
519  if((retval=nc4_find_nc4_grp(parent,&grp)))
520  goto done;
521  /* See if type exists in this group */
522  type = (NC_TYPE_INFO_T*)ncindexlookup(grp->type,lastname);
523  if(type == NULL)
524  {retval = NC_EBADTYPE; goto done;}
525  goto done;
526  }
527 
528  /* Is the type in this group? If not, search parents. */
529  for (grptwo = grp; grptwo; grptwo = grptwo->parent) {
530  type = (NC_TYPE_INFO_T*)ncindexlookup(grptwo->type,norm_name);
531  if(type)
532  {
533  if (typeidp)
534  *typeidp = type->hdr.id;
535  break;
536  }
537  }
538 
539  /* Still didn't find type? Search file recursively, starting at the
540  * root group. */
541  if (!type)
542  if ((type = nc4_rec_find_named_type(grp->nc4_info->root_grp, norm_name)))
543  if (typeidp)
544  *typeidp = type->hdr.id;
545 
546  /* OK, I give up already! */
547  if (!type)
548  {retval = NC_EBADTYPE; goto done;}
549 
550 done:
551  nullfree(norm_name);
552  return retval;
553 }
554 
567 int
568 nc4_get_typeclass(const NC_FILE_INFO_T *h5, nc_type xtype, int *type_class)
569 {
570  int retval = NC_NOERR;
571 
572  LOG((4, "%s xtype: %d", __func__, xtype));
573  assert(type_class);
574 
575  /* If this is an atomic type, the answer is easy. */
576  if (xtype <= NC_STRING)
577  {
578  switch (xtype)
579  {
580  case NC_BYTE:
581  case NC_UBYTE:
582  case NC_SHORT:
583  case NC_USHORT:
584  case NC_INT:
585  case NC_UINT:
586  case NC_INT64:
587  case NC_UINT64:
588  /* NC_INT is class used for all integral types */
589  *type_class = NC_INT;
590  break;
591 
592  case NC_FLOAT:
593  case NC_DOUBLE:
594  /* NC_FLOAT is class used for all floating-point types */
595  *type_class = NC_FLOAT;
596  break;
597 
598  case NC_CHAR:
599  *type_class = NC_CHAR;
600  break;
601 
602  case NC_STRING:
603  *type_class = NC_STRING;
604  break;
605 
606  default:
607  BAIL(NC_EBADTYPE);
608  }
609  }
610  else
611  {
612  NC_TYPE_INFO_T *type;
613 
614  /* See if it's a used-defined type */
615  if ((retval = nc4_find_type(h5, xtype, &type)))
616  BAIL(retval);
617  if (!type)
618  BAIL(NC_EBADTYPE);
619 
620  *type_class = type->nc_type_class;
621  }
622 
623 exit:
624  return retval;
625 }
626 
638 int
639 NC4_inq_type_fixed_size(int ncid, nc_type xtype, int* fixedsizep)
640 {
641  int stat = NC_NOERR;
642  int f = 0;
643  NC_FILE_INFO_T* h5 = NULL;
644  NC_TYPE_INFO_T* typ = NULL;
645 
646  if(xtype < NC_STRING) {f = 1; goto done;}
647  if(xtype == NC_STRING) {f = 0; goto done;}
648 
649 #ifdef USE_NETCDF4
650  /* Must be user type */
651  if ((stat = nc4_find_grp_h5(ncid, NULL, &h5)))
652  goto done;
653  if((stat = nc4_find_type(h5,xtype,&typ))) goto done;
654  f = !typ->varsized;
655 #endif
656 done:
657  if(fixedsizep) *fixedsizep = f;
658  return stat;
659 }
660 
661 
671 int
672 NC4_recheck_varsize(NC_TYPE_INFO_T* parenttype, nc_type subtype)
673 {
674  int stat = NC_NOERR;
675  NC_FILE_INFO_T* file = NULL;
676  NC_TYPE_INFO_T* utype = NULL;
677  if(subtype < NC_STRING) goto done; /* will not change the "variable-sizedness" of parenttype */
678  if(subtype == NC_STRING) {parenttype->varsized = 1; goto done;}
679  /* Get the inferred user-type */
680  file = parenttype->container->nc4_info;
681  if((stat = nc4_find_type(file,subtype,&utype))) goto done;
682  switch (utype->nc_type_class) {
683  case NC_OPAQUE: case NC_ENUM: break; /* no change */
684  case NC_VLEN: parenttype->varsized = 1; break;
685  case NC_COMPOUND: if(utype->varsized) parenttype->varsized = 1; break;
686  }
687 
688 done:
689  return stat;
690 }
691 
697 int
698 NC4_set_varsize(NC_TYPE_INFO_T* typ)
699 {
700  int stat = NC_NOERR;
701  if(typ->hdr.id < NC_STRING) goto done; /* will not change the "variable-sizedness" of typ */
702  if(typ->hdr.id == NC_STRING) {typ->varsized = 1; goto done;}
703  switch (typ->nc_type_class) {
704  case NC_OPAQUE: case NC_ENUM: break; /* no change */
705  case NC_VLEN: typ->varsized = 1; break;
706  case NC_COMPOUND: typ->varsized = 0; break; /* until proven otherwise */
707  }
708 done:
709  return stat;
710 }
711 
717 int
718 NC4_var_varsized(NC_VAR_INFO_T* var)
719 {
720  NC_TYPE_INFO_T* vtype = NULL;
721 
722  /* Check the variable type */
723  vtype = var->type_info;
724  if(vtype->hdr.id < NC_STRING) return 0;
725  if(vtype->hdr.id == NC_STRING) return 1;
726  return vtype->varsized;
727 }
728 
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:458
int NC4_recheck_varsize(NC_TYPE_INFO_T *parenttype, nc_type subtype)
For types with one or more subtypes (e.g.
Definition: nc4type.c:672
#define NC_CHAR
ISO/ASCII character.
Definition: netcdf.h:36
#define NC_UBYTE
unsigned 1 byte int
Definition: netcdf.h:42
#define NC_UINT
unsigned 4-byte int
Definition: netcdf.h:44
#define NC_OPAQUE
opaque types
Definition: netcdf.h:54
#define NC_INT64
signed 8-byte int
Definition: netcdf.h:45
#define NC_STRING
string
Definition: netcdf.h:47
#define NC_DOUBLE
double precision floating point number
Definition: netcdf.h:41
int nc_type
The nc_type type is just an int.
Definition: netcdf.h:25
#define NC_BYTE
signed 1 byte integer
Definition: netcdf.h:35
#define NC_EBADFIELD
Bad field ID.
Definition: netcdf.h:509
#define NC_VLEN
vlen (variable-length) types
Definition: netcdf.h:53
#define NC_EBADTYPE
Not a netcdf data type.
Definition: netcdf.h:420
#define NC_EINVAL
Invalid Argument.
Definition: netcdf.h:388
#define NC_INT
signed 4 byte integer
Definition: netcdf.h:38
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:291
#define NC_NAT
Not A Type.
Definition: netcdf.h:34
#define NC_USHORT
unsigned 2-byte int
Definition: netcdf.h:43
int NC4_set_varsize(NC_TYPE_INFO_T *typ)
When creating a type, mark it as variable-sized if known for sure.
Definition: nc4type.c:698
#define EXTERNL
Needed for DLL build.
Definition: netcdf.h:571
This is the type of arrays of vlens.
Definition: netcdf.h:761
#define NC_SHORT
signed 2 byte integer
Definition: netcdf.h:37
#define NC_NOERR
No Error.
Definition: netcdf.h:378
#define NC_ENUM
enum types
Definition: netcdf.h:55
#define NC_COMPOUND
compound types
Definition: netcdf.h:56
int NC4_var_varsized(NC_VAR_INFO_T *var)
Test if a variable's type is fixed sized or not.
Definition: nc4type.c:718
#define NC_FLOAT
single precision floating point number
Definition: netcdf.h:40
#define NC_UINT64
unsigned 8-byte int
Definition: netcdf.h:46