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