NetCDF 4.9.2
Loading...
Searching...
No Matches
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
415int
416NC4_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
509int
510NC4_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
559EXTERNL int
560NC4_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
638done:
639 nullfree(norm_name);
640 return retval;
641}
642
655int
656nc4_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
711exit:
712 return retval;
713}
714
726int
727NC4_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
762done:
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