NetCDF 4.9.3
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#include <stddef.h>
17
31int
32NC4_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
79int
80NC4_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
134int
135NC4_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
213int
214NC4_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
264int
265NC4_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
327int
328NC4_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
421int
422NC4_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
471EXTERNL int
472NC4_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
550done:
551 nullfree(norm_name);
552 return retval;
553}
554
567int
568nc4_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
623exit:
624 return retval;
625}
626
638int
639NC4_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
656done:
657 if(fixedsizep) *fixedsizep = f;
658 return stat;
659}
660
661
670
671int
672NC4_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
688done:
689 return stat;
690}
691
696
697int
698NC4_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 }
708done:
709 return stat;
710}
711
717int
718NC4_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
int NC4_var_varsized(NC_VAR_INFO_T *var)
Test if a variable's type is fixed sized or not.
Definition nc4type.c:718
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
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 NC_EBADTYPE
Not a netcdf data type.
Definition netcdf.h:420
#define NC_EBADFIELD
Bad field ID.
Definition netcdf.h:509
#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:458
#define EXTERNL
Needed for DLL build.
Definition netcdf.h:571
#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_UINT64
unsigned 8-byte int
Definition netcdf.h:46
#define NC_EINVAL
Invalid Argument.
Definition netcdf.h:388
#define NC_MAX_NAME
Maximum for classic library.
Definition netcdf.h:291
#define NC_NOERR
No Error.
Definition netcdf.h:378
#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:761