NetCDF  4.9.2
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 
17 #ifdef ENABLE_DAP4
18 EXTERNL int NCD4_get_substrate(int ncid);
19 #endif
20 
21 /* The sizes of types may vary from platform to platform, but within
22  * netCDF files, type sizes are fixed. */
23 #define NC_CHAR_LEN sizeof(char)
24 #define NC_STRING_LEN sizeof(char *)
25 #define NC_BYTE_LEN 1
26 #define NC_SHORT_LEN 2
27 #define NC_INT_LEN 4
28 #define NC_FLOAT_LEN 4
29 #define NC_DOUBLE_LEN 8
30 #define NC_INT64_LEN 8
33 const char* nc4_atomic_name[NUM_ATOMIC_TYPES] = {"none", "byte", "char",
34  "short", "int", "float",
35  "double", "ubyte",
36  "ushort", "uint",
37  "int64", "uint64", "string"};
38 static const int nc4_atomic_size[NUM_ATOMIC_TYPES] = {0, NC_BYTE_LEN, NC_CHAR_LEN, NC_SHORT_LEN,
39  NC_INT_LEN, NC_FLOAT_LEN, NC_DOUBLE_LEN,
40  NC_BYTE_LEN, NC_SHORT_LEN, NC_INT_LEN, NC_INT64_LEN,
41  NC_INT64_LEN, NC_STRING_LEN};
42 
56 int
57 NC4_inq_typeids(int ncid, int *ntypes, int *typeids)
58 {
59  NC_GRP_INFO_T *grp;
60  NC_FILE_INFO_T *h5;
61  NC_TYPE_INFO_T *type;
62  int num = 0;
63  int retval;
64 
65  LOG((2, "nc_inq_typeids: ncid 0x%x", ncid));
66 
67  /* Find info for this file and group, and set pointer to each. */
68  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
69  return retval;
70  assert(h5 && grp);
71 
72  /* Count types. */
73  if (grp->type) {
74  int i;
75  for(i=0;i<ncindexsize(grp->type);i++)
76  {
77  if((type = (NC_TYPE_INFO_T*)ncindexith(grp->type,i)) == NULL) continue;
78  if (typeids)
79  typeids[num] = type->hdr.id;
80  num++;
81  }
82  }
83 
84  /* Give the count to the user. */
85  if (ntypes)
86  *ntypes = num;
87 
88  return NC_NOERR;
89 }
90 
104 int
105 NC4_inq_atomic_type(nc_type typeid1, char *name, size_t *size)
106 {
107  LOG((2, "nc_inq_atomic_type: typeid %d", typeid1));
108 
109  if (typeid1 >= NUM_ATOMIC_TYPES)
110  return NC_EBADTYPE;
111  if (name)
112  strcpy(name, nc4_atomic_name[typeid1]);
113  if (size)
114  *size = nc4_atomic_size[typeid1];
115  return NC_NOERR;
116 }
117 
129 int
130 NC4_lookup_atomic_type(const char *name, nc_type* idp, size_t *sizep)
131 {
132  int i;
133 
134  LOG((2, "nc_lookup_atomic_type: name %s ", name));
135 
136  if (name == NULL || strlen(name) == 0)
137  return NC_EBADTYPE;
138  for(i=0;i<NUM_ATOMIC_TYPES;i++) {
139  if(strcasecmp(name,nc4_atomic_name[i])==0) {
140  if(idp) *idp = i;
141  if(sizep) *sizep = nc4_atomic_size[i];
142  return NC_NOERR;
143  }
144  }
145  return NC_EBADTYPE;
146 }
147 
162 int
163 NC4_inq_type(int ncid, nc_type typeid1, char *name, size_t *size)
164 {
165  NC_GRP_INFO_T *grp;
166  NC_TYPE_INFO_T *type;
167 
168  int retval;
169 
170  LOG((2, "nc_inq_type: ncid 0x%x typeid %d", ncid, typeid1));
171 
172  /* If this is an atomic type, the answer is easy. */
173  if (typeid1 < NUM_ATOMIC_TYPES)
174  {
175  if (name)
176  strcpy(name, nc4_atomic_name[typeid1]);
177  if (size)
178  *size = nc4_atomic_size[typeid1];
179  return NC_NOERR;
180  }
181 
182  /* Not an atomic type - so find group. */
183  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
184  return retval;
185 
186  /* Find this type. */
187  if (!(type = nclistget(grp->nc4_info->alltypes, typeid1)))
188  return NC_EBADTYPE;
189 
190  if (name)
191  strcpy(name, type->hdr.name);
192 
193  if (size)
194  {
195  if (type->nc_type_class == NC_VLEN)
196  *size = sizeof(nc_vlen_t);
197  else if (type->nc_type_class == NC_STRING)
198  *size = NC_STRING_LEN;
199  else
200  *size = type->size;
201  }
202 
203  return NC_NOERR;
204 }
205 
222 int
223 NC4_inq_user_type(int ncid, nc_type typeid1, char *name, size_t *size,
224  nc_type *base_nc_typep, size_t *nfieldsp, int *classp)
225 {
226  NC_GRP_INFO_T *grp;
227  NC_TYPE_INFO_T *type;
228  int retval;
229 
230  LOG((2, "nc_inq_user_type: ncid 0x%x typeid %d", ncid, typeid1));
231 
232  /* Find group metadata. */
233  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
234  return retval;
235 
236  /* Find this type. */
237  if (!(type = nclistget(grp->nc4_info->alltypes, typeid1)))
238  return NC_EBADTYPE;
239 
240  /* Count the number of fields. */
241  if (nfieldsp)
242  {
243  if (type->nc_type_class == NC_COMPOUND)
244  *nfieldsp = nclistlength(type->u.c.field);
245  else if (type->nc_type_class == NC_ENUM)
246  *nfieldsp = nclistlength(type->u.e.enum_member);
247  else
248  *nfieldsp = 0;
249  }
250 
251  /* Fill in size and name info, if desired. */
252  if (size)
253  {
254  if (type->nc_type_class == NC_VLEN)
255  *size = sizeof(nc_vlen_t);
256  else if (type->nc_type_class == NC_STRING)
257  *size = NC_STRING_LEN;
258  else
259  *size = type->size;
260  }
261  if (name)
262  strcpy(name, type->hdr.name);
263 
264  /* VLENS and ENUMs have a base type - that is, they type they are
265  * arrays of or enums of. */
266  if (base_nc_typep)
267  {
268  if (type->nc_type_class == NC_ENUM)
269  *base_nc_typep = type->u.e.base_nc_typeid;
270  else if (type->nc_type_class == NC_VLEN)
271  *base_nc_typep = type->u.v.base_nc_typeid;
272  else
273  *base_nc_typep = NC_NAT;
274  }
275 
276  /* If the user wants it, tell whether this is a compound, opaque,
277  * vlen, enum, or string class of type. */
278  if (classp)
279  *classp = type->nc_type_class;
280 
281  return NC_NOERR;
282 }
283 
301 int
302 NC4_inq_compound_field(int ncid, nc_type typeid1, int fieldid, char *name,
303  size_t *offsetp, nc_type *field_typeidp, int *ndimsp,
304  int *dim_sizesp)
305 {
306  NC_GRP_INFO_T *grp;
307  NC_TYPE_INFO_T *type;
308  NC_FIELD_INFO_T *field;
309  int d, retval;
310 
311  /* Find file metadata. */
312  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
313  return retval;
314 
315  /* Find this type. */
316  if (!(type = nclistget(grp->nc4_info->alltypes, typeid1)))
317  return NC_EBADTYPE;
318 
319  /* Find the field. */
320  if (!(field = nclistget(type->u.c.field,fieldid)))
321  return NC_EBADFIELD;
322 
323  if (name)
324  strcpy(name, field->hdr.name);
325  if (offsetp)
326  *offsetp = field->offset;
327  if (field_typeidp)
328  *field_typeidp = field->nc_typeid;
329  if (ndimsp)
330  *ndimsp = field->ndims;
331  if (dim_sizesp)
332  for (d = 0; d < field->ndims; d++)
333  dim_sizesp[d] = field->dim_size[d];
334 
335  return NC_NOERR;
336 }
337 
352 int
353 NC4_inq_compound_fieldindex(int ncid, nc_type typeid1, const char *name, int *fieldidp)
354 {
355  NC_FILE_INFO_T *h5;
356  NC_TYPE_INFO_T *type;
357  NC_FIELD_INFO_T *field;
358  char norm_name[NC_MAX_NAME + 1];
359  int retval;
360  int i;
361 
362  LOG((2, "nc_inq_compound_fieldindex: ncid 0x%x typeid %d name %s",
363  ncid, typeid1, name));
364 
365  /* Find file metadata. */
366  if ((retval = nc4_find_grp_h5(ncid, NULL, &h5)))
367  return retval;
368 
369  /* Find the type. */
370  if ((retval = nc4_find_type(h5, typeid1, &type)))
371  return retval;
372 
373  /* Did the user give us a good compound type typeid? */
374  if (!type || type->nc_type_class != NC_COMPOUND)
375  return NC_EBADTYPE;
376 
377  /* Normalize name. */
378  if ((retval = nc4_normalize_name(name, norm_name)))
379  return retval;
380 
381  /* Find the field with this name. */
382  for (i = 0; i < nclistlength(type->u.c.field); i++)
383  {
384  field = nclistget(type->u.c.field, i);
385  assert(field);
386  if (!strcmp(field->hdr.name, norm_name))
387  break;
388  field = NULL; /* because this is the indicator of not found */
389  }
390 
391  if (!field)
392  return NC_EBADFIELD;
393 
394  if (fieldidp)
395  *fieldidp = field->hdr.id;
396  return NC_NOERR;
397 }
398 
415 int
416 NC4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier)
417 {
418  NC_GRP_INFO_T *grp;
419  NC_TYPE_INFO_T *type;
420  NC_ENUM_MEMBER_INFO_T *enum_member;
421  long long ll_val;
422  int i;
423  int retval;
424  int found;
425 
426  LOG((3, "nc_inq_enum_ident: xtype %d value %d\n", xtype, value));
427 
428  /* Find group metadata. */
429  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
430  return retval;
431 
432  /* Find this type. */
433  if (!(type = nclistget(grp->nc4_info->alltypes, xtype)))
434  return NC_EBADTYPE;
435 
436  /* Complain if they are confused about the type. */
437  if (type->nc_type_class != NC_ENUM)
438  return NC_EBADTYPE;
439 
440  /* Move to the desired enum member in the list. */
441  for (found = 0, i = 0; i < nclistlength(type->u.e.enum_member); i++)
442  {
443  enum_member = nclistget(type->u.e.enum_member, i);
444  assert(enum_member);
445  switch (type->u.e.base_nc_typeid)
446  {
447  case NC_BYTE:
448  ll_val = *(char *)enum_member->value;
449  break;
450  case NC_UBYTE:
451  ll_val = *(unsigned char *)enum_member->value;
452  break;
453  case NC_SHORT:
454  ll_val = *(short *)enum_member->value;
455  break;
456  case NC_USHORT:
457  ll_val = *(unsigned short *)enum_member->value;
458  break;
459  case NC_INT:
460  ll_val = *(int *)enum_member->value;
461  break;
462  case NC_UINT:
463  ll_val = *(unsigned int *)enum_member->value;
464  break;
465  case NC_INT64:
466  case NC_UINT64:
467  ll_val = *(long long *)enum_member->value;
468  break;
469  default:
470  return NC_EINVAL;
471  }
472  LOG((4, "ll_val=%d", ll_val));
473  if (ll_val == value)
474  {
475  if (identifier)
476  strcpy(identifier, enum_member->name);
477  found = 1;
478  break;
479  }
480  }
481 
482  /* If we didn't find it, life sucks for us. :-( */
483  if(!found) {
484  if(value == 0) /* Special case for HDF5 default Fill Value*/
485  strcpy(identifier, NC_UNDEFINED_ENUM_IDENT);
486  else
487  return NC_EINVAL;
488  }
489 
490  return NC_NOERR;
491 }
492 
509 int
510 NC4_inq_enum_member(int ncid, nc_type typeid1, int idx, char *identifier,
511  void *value)
512 {
513  NC_GRP_INFO_T *grp;
514  NC_TYPE_INFO_T *type;
515  NC_ENUM_MEMBER_INFO_T *enum_member;
516  int retval;
517 
518  LOG((2, "nc_inq_enum_member: ncid 0x%x typeid %d", ncid, typeid1));
519 
520  /* Find group metadata. */
521  if ((retval = nc4_find_nc4_grp(ncid, &grp)))
522  return retval;
523 
524  /* Find this type. */
525  if (!(type = nclistget(grp->nc4_info->alltypes, typeid1)))
526  return NC_EBADTYPE;
527 
528  /* Complain if they are confused about the type. */
529  if (type->nc_type_class != NC_ENUM)
530  return NC_EBADTYPE;
531 
532  /* Move to the desired enum member in the list. */
533  if (!(enum_member = nclistget(type->u.e.enum_member, idx)))
534  return NC_EINVAL;
535 
536  /* Give the people what they want. */
537  if (identifier)
538  strcpy(identifier, enum_member->name);
539  if (value)
540  memcpy(value, enum_member->value, type->size);
541 
542  return NC_NOERR;
543 }
544 
559 EXTERNL int
560 NC4_inq_typeid(int ncid, const char *name, nc_type *typeidp)
561 {
562  NC_GRP_INFO_T *grp;
563  NC_GRP_INFO_T *grptwo;
564  NC_FILE_INFO_T *h5;
565  NC_TYPE_INFO_T *type = NULL;
566  char *norm_name = NULL;
567  int i, retval = NC_NOERR;
568 
569  /* Handle atomic types. */
570  for (i = 0; i < NUM_ATOMIC_TYPES; i++)
571  if (!strcmp(name, nc4_atomic_name[i]))
572  {
573  if (typeidp)
574  *typeidp = i;
575  goto done;
576  }
577 
578  /* Find info for this file and group, and set pointer to each. */
579  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
580  goto done;
581  assert(h5 && grp);
582 
583  /* If the first char is a /, this is a fully-qualified
584  * name. Otherwise, this had better be a local name (i.e. no / in
585  * the middle). */
586  if (name[0] != '/' && strstr(name, "/"))
587  {retval = NC_EINVAL; goto done;}
588 
589  /* Normalize name. */
590  if (!(norm_name = (char*)malloc(strlen(name) + 1)))
591  {retval = NC_ENOMEM; goto done;}
592  if ((retval = nc4_normalize_name(name, norm_name)))
593  goto done;
594 
595  /* If this is a fqn, then walk the sequence of parent groups to the last group
596  and see if that group has a type of the right name */
597  if(name[0] == '/') { /* FQN */
598  int rootncid = (grp->nc4_info->root_grp->hdr.id | grp->nc4_info->controller->ext_ncid);
599  int parent = 0;
600  char* lastname = strrchr(norm_name,'/'); /* break off the last segment: the type name */
601  if(lastname == norm_name)
602  {retval = NC_EINVAL; goto done;}
603  *lastname++ = '\0'; /* break off the lastsegment */
604  if((retval = NC4_inq_grp_full_ncid(rootncid,norm_name,&parent)))
605  goto done;
606  /* Get parent info */
607  if((retval=nc4_find_nc4_grp(parent,&grp)))
608  goto done;
609  /* See if type exists in this group */
610  type = (NC_TYPE_INFO_T*)ncindexlookup(grp->type,lastname);
611  if(type == NULL)
612  {retval = NC_EBADTYPE; goto done;}
613  goto done;
614  }
615 
616  /* Is the type in this group? If not, search parents. */
617  for (grptwo = grp; grptwo; grptwo = grptwo->parent) {
618  type = (NC_TYPE_INFO_T*)ncindexlookup(grptwo->type,norm_name);
619  if(type)
620  {
621  if (typeidp)
622  *typeidp = type->hdr.id;
623  break;
624  }
625  }
626 
627  /* Still didn't find type? Search file recursively, starting at the
628  * root group. */
629  if (!type)
630  if ((type = nc4_rec_find_named_type(grp->nc4_info->root_grp, norm_name)))
631  if (typeidp)
632  *typeidp = type->hdr.id;
633 
634  /* OK, I give up already! */
635  if (!type)
636  {retval = NC_EBADTYPE; goto done;}
637 
638 done:
639  nullfree(norm_name);
640  return retval;
641 }
642 
655 int
656 nc4_get_typeclass(const NC_FILE_INFO_T *h5, nc_type xtype, int *type_class)
657 {
658  int retval = NC_NOERR;
659 
660  LOG((4, "%s xtype: %d", __func__, xtype));
661  assert(type_class);
662 
663  /* If this is an atomic type, the answer is easy. */
664  if (xtype <= NC_STRING)
665  {
666  switch (xtype)
667  {
668  case NC_BYTE:
669  case NC_UBYTE:
670  case NC_SHORT:
671  case NC_USHORT:
672  case NC_INT:
673  case NC_UINT:
674  case NC_INT64:
675  case NC_UINT64:
676  /* NC_INT is class used for all integral types */
677  *type_class = NC_INT;
678  break;
679 
680  case NC_FLOAT:
681  case NC_DOUBLE:
682  /* NC_FLOAT is class used for all floating-point types */
683  *type_class = NC_FLOAT;
684  break;
685 
686  case NC_CHAR:
687  *type_class = NC_CHAR;
688  break;
689 
690  case NC_STRING:
691  *type_class = NC_STRING;
692  break;
693 
694  default:
695  BAIL(NC_EBADTYPE);
696  }
697  }
698  else
699  {
700  NC_TYPE_INFO_T *type;
701 
702  /* See if it's a used-defined type */
703  if ((retval = nc4_find_type(h5, xtype, &type)))
704  BAIL(retval);
705  if (!type)
706  BAIL(NC_EBADTYPE);
707 
708  *type_class = type->nc_type_class;
709  }
710 
711 exit:
712  return retval;
713 }
714 
726 int
727 NC4_inq_type_fixed_size(int ncid, nc_type xtype, int* fixedsizep)
728 {
729  int stat = NC_NOERR;
730  int f = 0;
731  int xclass;
732 
733  if(xtype < NC_STRING) {f = 1; goto done;}
734  if(xtype == NC_STRING) {f = 0; goto done;}
735 
736 #ifdef USE_NETCDF4
737  /* Must be user type */
738  if((stat = nc_inq_user_type(ncid,xtype,NULL,NULL,NULL,NULL,&xclass))) goto done;
739  switch (xclass) {
740  case NC_ENUM: case NC_OPAQUE: f = 1; break;
741  case NC_VLEN: f = 0; break;
742  case NC_COMPOUND: {
743  NC_FILE_INFO_T* h5 = NULL;
744  NC_TYPE_INFO_T* typ = NULL;
745 #ifdef ENABLE_DAP4
746  NC* nc = NULL;
747  int xformat;
748  if ((stat = NC_check_id(ncid, &nc))) goto done;
749  xformat = nc->dispatch->model;
750  if(xformat == NC_FORMATX_DAP4) {
751  ncid = NCD4_get_substrate(ncid);
752  } /* Fall thru */
753 #endif
754  if ((stat = nc4_find_grp_h5(ncid, NULL, &h5)))
755  goto done;
756  if((stat = nc4_find_type(h5,xtype,&typ))) goto done;
757  f = !typ->u.c.varsized;
758  } break;
759  default: stat = NC_EBADTYPE; goto done;
760  }
761 #endif
762 done:
763  if(fixedsizep) *fixedsizep = f;
764  return stat;
765 }
EXTERNL int nc_inq_user_type(int ncid, nc_type xtype, char *name, size_t *size, nc_type *base_nc_typep, size_t *nfieldsp, int *classp)
Learn about a user defined type.
Definition: dtype.c:146
#define NC_EBADTYPE
Not a netcdf data type.
Definition: netcdf.h:410
#define NC_EBADFIELD
Bad field ID.
Definition: netcdf.h:499
#define NC_UINT
unsigned 4-byte int
Definition: netcdf.h:44
#define NC_INT
signed 4 byte integer
Definition: netcdf.h:38
#define NC_BYTE
signed 1 byte integer
Definition: netcdf.h:35
#define NC_VLEN
vlen (variable-length) types
Definition: netcdf.h:53
#define NC_NAT
Not A Type.
Definition: netcdf.h:34
#define NC_DOUBLE
double precision floating point number
Definition: netcdf.h:41
#define NC_UBYTE
unsigned 1 byte int
Definition: netcdf.h:42
#define NC_FLOAT
single precision floating point number
Definition: netcdf.h:40
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:448
#define EXTERNL
Needed for DLL build.
Definition: netcdf.h:556
#define NC_COMPOUND
compound types
Definition: netcdf.h:56
#define NC_SHORT
signed 2 byte integer
Definition: netcdf.h:37
#define NC_ENUM
enum types
Definition: netcdf.h:55
#define NC_INT64
signed 8-byte int
Definition: netcdf.h:45
#define NC_FORMATX_DAP4
Extended format specifier returned by nc_inq_format_extended() Added in version 4....
Definition: netcdf.h:222
#define NC_UINT64
unsigned 8-byte int
Definition: netcdf.h:46
#define NC_EINVAL
Invalid Argument.
Definition: netcdf.h:378
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:281
#define NC_NOERR
No Error.
Definition: netcdf.h:368
#define NC_USHORT
unsigned 2-byte int
Definition: netcdf.h:43
#define NC_OPAQUE
opaque types
Definition: netcdf.h:54
#define NC_STRING
string
Definition: netcdf.h:47
#define NC_CHAR
ISO/ASCII character.
Definition: netcdf.h:36
int nc_type
The nc_type type is just an int.
Definition: netcdf.h:25
This is the type of arrays of vlens.
Definition: netcdf.h:746