NetCDF 4.9.0
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
18EXTERNL 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
33const char* nc4_atomic_name[NUM_ATOMIC_TYPES] = {"none", "byte", "char",
34 "short", "int", "float",
35 "double", "ubyte",
36 "ushort", "uint",
37 "int64", "uint64", "string"};
38static 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
56int
57NC4_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
104int
105NC4_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
129int
130NC4_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
162int
163NC4_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
222int
223NC4_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
301int
302NC4_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
352int
353NC4_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
414int
415NC4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier)
416{
417 NC_GRP_INFO_T *grp;
418 NC_TYPE_INFO_T *type;
419 NC_ENUM_MEMBER_INFO_T *enum_member;
420 long long ll_val;
421 int i;
422 int retval;
423 int found;
424
425 LOG((3, "nc_inq_enum_ident: xtype %d value %d\n", xtype, value));
426
427 /* Find group metadata. */
428 if ((retval = nc4_find_nc4_grp(ncid, &grp)))
429 return retval;
430
431 /* Find this type. */
432 if (!(type = nclistget(grp->nc4_info->alltypes, xtype)))
433 return NC_EBADTYPE;
434
435 /* Complain if they are confused about the type. */
436 if (type->nc_type_class != NC_ENUM)
437 return NC_EBADTYPE;
438
439 /* Move to the desired enum member in the list. */
440 for (found = 0, i = 0; i < nclistlength(type->u.e.enum_member); i++)
441 {
442 enum_member = nclistget(type->u.e.enum_member, i);
443 assert(enum_member);
444 switch (type->u.e.base_nc_typeid)
445 {
446 case NC_BYTE:
447 ll_val = *(char *)enum_member->value;
448 break;
449 case NC_UBYTE:
450 ll_val = *(unsigned char *)enum_member->value;
451 break;
452 case NC_SHORT:
453 ll_val = *(short *)enum_member->value;
454 break;
455 case NC_USHORT:
456 ll_val = *(unsigned short *)enum_member->value;
457 break;
458 case NC_INT:
459 ll_val = *(int *)enum_member->value;
460 break;
461 case NC_UINT:
462 ll_val = *(unsigned int *)enum_member->value;
463 break;
464 case NC_INT64:
465 case NC_UINT64:
466 ll_val = *(long long *)enum_member->value;
467 break;
468 default:
469 return NC_EINVAL;
470 }
471 LOG((4, "ll_val=%d", ll_val));
472 if (ll_val == value)
473 {
474 if (identifier)
475 strcpy(identifier, enum_member->name);
476 found = 1;
477 break;
478 }
479 }
480
481 /* If we didn't find it, life sucks for us. :-( */
482 if (!found)
483 return NC_EINVAL;
484
485 return NC_NOERR;
486}
487
504int
505NC4_inq_enum_member(int ncid, nc_type typeid1, int idx, char *identifier,
506 void *value)
507{
508 NC_GRP_INFO_T *grp;
509 NC_TYPE_INFO_T *type;
510 NC_ENUM_MEMBER_INFO_T *enum_member;
511 int retval;
512
513 LOG((2, "nc_inq_enum_member: ncid 0x%x typeid %d", ncid, typeid1));
514
515 /* Find group metadata. */
516 if ((retval = nc4_find_nc4_grp(ncid, &grp)))
517 return retval;
518
519 /* Find this type. */
520 if (!(type = nclistget(grp->nc4_info->alltypes, typeid1)))
521 return NC_EBADTYPE;
522
523 /* Complain if they are confused about the type. */
524 if (type->nc_type_class != NC_ENUM)
525 return NC_EBADTYPE;
526
527 /* Move to the desired enum member in the list. */
528 if (!(enum_member = nclistget(type->u.e.enum_member, idx)))
529 return NC_EINVAL;
530
531 /* Give the people what they want. */
532 if (identifier)
533 strcpy(identifier, enum_member->name);
534 if (value)
535 memcpy(value, enum_member->value, type->size);
536
537 return NC_NOERR;
538}
539
554EXTERNL int
555NC4_inq_typeid(int ncid, const char *name, nc_type *typeidp)
556{
557 NC_GRP_INFO_T *grp;
558 NC_GRP_INFO_T *grptwo;
559 NC_FILE_INFO_T *h5;
560 NC_TYPE_INFO_T *type = NULL;
561 char *norm_name = NULL;
562 int i, retval = NC_NOERR;
563
564 /* Handle atomic types. */
565 for (i = 0; i < NUM_ATOMIC_TYPES; i++)
566 if (!strcmp(name, nc4_atomic_name[i]))
567 {
568 if (typeidp)
569 *typeidp = i;
570 goto done;
571 }
572
573 /* Find info for this file and group, and set pointer to each. */
574 if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
575 goto done;
576 assert(h5 && grp);
577
578 /* If the first char is a /, this is a fully-qualified
579 * name. Otherwise, this had better be a local name (i.e. no / in
580 * the middle). */
581 if (name[0] != '/' && strstr(name, "/"))
582 {retval = NC_EINVAL; goto done;}
583
584 /* Normalize name. */
585 if (!(norm_name = (char*)malloc(strlen(name) + 1)))
586 {retval = NC_ENOMEM; goto done;}
587 if ((retval = nc4_normalize_name(name, norm_name)))
588 goto done;
589
590 /* If this is a fqn, then walk the sequence of parent groups to the last group
591 and see if that group has a type of the right name */
592 if(name[0] == '/') { /* FQN */
593 int rootncid = (grp->nc4_info->root_grp->hdr.id | grp->nc4_info->controller->ext_ncid);
594 int parent = 0;
595 char* lastname = strrchr(norm_name,'/'); /* break off the last segment: the type name */
596 if(lastname == norm_name)
597 {retval = NC_EINVAL; goto done;}
598 *lastname++ = '\0'; /* break off the lastsegment */
599 if((retval = NC4_inq_grp_full_ncid(rootncid,norm_name,&parent)))
600 goto done;
601 /* Get parent info */
602 if((retval=nc4_find_nc4_grp(parent,&grp)))
603 goto done;
604 /* See if type exists in this group */
605 type = (NC_TYPE_INFO_T*)ncindexlookup(grp->type,lastname);
606 if(type == NULL)
607 {retval = NC_EBADTYPE; goto done;}
608 goto done;
609 }
610
611 /* Is the type in this group? If not, search parents. */
612 for (grptwo = grp; grptwo; grptwo = grptwo->parent) {
613 type = (NC_TYPE_INFO_T*)ncindexlookup(grptwo->type,norm_name);
614 if(type)
615 {
616 if (typeidp)
617 *typeidp = type->hdr.id;
618 break;
619 }
620 }
621
622 /* Still didn't find type? Search file recursively, starting at the
623 * root group. */
624 if (!type)
625 if ((type = nc4_rec_find_named_type(grp->nc4_info->root_grp, norm_name)))
626 if (typeidp)
627 *typeidp = type->hdr.id;
628
629 /* OK, I give up already! */
630 if (!type)
631 {retval = NC_EBADTYPE; goto done;}
632
633done:
634 nullfree(norm_name);
635 return retval;
636}
637
650int
651nc4_get_typeclass(const NC_FILE_INFO_T *h5, nc_type xtype, int *type_class)
652{
653 int retval = NC_NOERR;
654
655 LOG((4, "%s xtype: %d", __func__, xtype));
656 assert(type_class);
657
658 /* If this is an atomic type, the answer is easy. */
659 if (xtype <= NC_STRING)
660 {
661 switch (xtype)
662 {
663 case NC_BYTE:
664 case NC_UBYTE:
665 case NC_SHORT:
666 case NC_USHORT:
667 case NC_INT:
668 case NC_UINT:
669 case NC_INT64:
670 case NC_UINT64:
671 /* NC_INT is class used for all integral types */
672 *type_class = NC_INT;
673 break;
674
675 case NC_FLOAT:
676 case NC_DOUBLE:
677 /* NC_FLOAT is class used for all floating-point types */
678 *type_class = NC_FLOAT;
679 break;
680
681 case NC_CHAR:
682 *type_class = NC_CHAR;
683 break;
684
685 case NC_STRING:
686 *type_class = NC_STRING;
687 break;
688
689 default:
690 BAIL(NC_EBADTYPE);
691 }
692 }
693 else
694 {
695 NC_TYPE_INFO_T *type;
696
697 /* See if it's a used-defined type */
698 if ((retval = nc4_find_type(h5, xtype, &type)))
699 BAIL(retval);
700 if (!type)
701 BAIL(NC_EBADTYPE);
702
703 *type_class = type->nc_type_class;
704 }
705
706exit:
707 return retval;
708}
709
721int
722NC4_inq_type_fixed_size(int ncid, nc_type xtype, int* fixedsizep)
723{
724 int stat = NC_NOERR;
725 int f = 0;
726 int xclass;
727
728 if(xtype < NC_STRING) {f = 1; goto done;}
729 if(xtype == NC_STRING) {f = 0; goto done;}
730
731#ifdef USE_NETCDF4
732 /* Must be user type */
733 if((stat = nc_inq_user_type(ncid,xtype,NULL,NULL,NULL,NULL,&xclass))) goto done;
734 switch (xclass) {
735 case NC_ENUM: case NC_OPAQUE: f = 1; break;
736 case NC_VLEN: f = 0; break;
737 case NC_COMPOUND: {
738 NC_FILE_INFO_T* h5 = NULL;
739 NC_TYPE_INFO_T* typ = NULL;
740#ifdef ENABLE_DAP4
741 NC* nc = NULL;
742 int xformat;
743 if ((stat = NC_check_id(ncid, &nc))) goto done;
744 xformat = nc->dispatch->model;
745 if(xformat == NC_FORMATX_DAP4) {
746 ncid = NCD4_get_substrate(ncid);
747 } /* Fall thru */
748#endif
749 if ((stat = nc4_find_grp_h5(ncid, NULL, &h5)))
750 goto done;
751 if((stat = nc4_find_type(h5,xtype,&typ))) goto done;
752 f = !typ->u.c.varsized;
753 } break;
754 default: stat = NC_EBADTYPE; goto done;
755 }
756#endif
757done:
758 if(fixedsizep) *fixedsizep = f;
759 return stat;
760}
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