NetCDF 4.8.0
Loading...
Searching...
No Matches
nc4internal.c
Go to the documentation of this file.
1/* Copyright 2003-2018, University Corporation for Atmospheric
2 * Research. See the COPYRIGHT file for copying and redistribution
3 * conditions.
4 */
18#include "config.h"
19#include "netcdf.h"
20#include "netcdf_filter.h"
21#include "nc4internal.h"
22#include "nc.h" /* from libsrc */
23#include "ncdispatch.h" /* from libdispatch */
24#include "ncutf8.h"
25#include "netcdf_aux.h"
26
35#define NRESERVED 11 /*|NC_reservedatt|*/
36
39static const NC_reservedatt NC_reserved[NRESERVED] = {
40 {NC_ATT_CLASS, READONLYFLAG|DIMSCALEFLAG}, /*CLASS*/
41 {NC_ATT_DIMENSION_LIST, READONLYFLAG|DIMSCALEFLAG}, /*DIMENSION_LIST*/
42 {NC_ATT_NAME, READONLYFLAG|DIMSCALEFLAG}, /*NAME*/
43 {NC_ATT_REFERENCE_LIST, READONLYFLAG|DIMSCALEFLAG}, /*REFERENCE_LIST*/
44 {NC_ATT_FORMAT, READONLYFLAG}, /*_Format*/
45 {ISNETCDF4ATT, READONLYFLAG|NAMEONLYFLAG}, /*_IsNetcdf4*/
46 {NCPROPS, READONLYFLAG|NAMEONLYFLAG|MATERIALIZEDFLAG},/*_NCProperties*/
47 {NC_ATT_COORDINATES, READONLYFLAG|DIMSCALEFLAG|MATERIALIZEDFLAG},/*_Netcdf4Coordinates*/
48 {NC_ATT_DIMID_NAME, READONLYFLAG|DIMSCALEFLAG|MATERIALIZEDFLAG},/*_Netcdf4Dimid*/
49 {SUPERBLOCKATT, READONLYFLAG|NAMEONLYFLAG},/*_SuperblockVersion*/
50 {NC_ATT_NC3_STRICT_NAME, READONLYFLAG|MATERIALIZEDFLAG}, /*_nc3_strict*/
51};
52
53/* These hold the file caching settings for the library. */
54size_t nc4_chunk_cache_size = CHUNK_CACHE_SIZE;
55size_t nc4_chunk_cache_nelems = CHUNK_CACHE_NELEMS;
56float nc4_chunk_cache_preemption = CHUNK_CACHE_PREEMPTION;
58static int NC4_move_in_NCList(NC* nc, int new_id);
59
60#ifdef LOGGING
61/* This is the severity level of messages which will be logged. Use
62 severity 0 for errors, 1 for important log messages, 2 for less
63 important, etc. */
64int nc_log_level = NC_TURN_OFF_LOGGING;
65#endif /* LOGGING */
66
79int
80nc4_check_name(const char *name, char *norm_name)
81{
82 char *temp;
83 int retval;
84
85 assert(norm_name);
86
87 /* Check for NULL. */
88 if (!name)
89 return NC_EINVAL;
90
91 /* Make sure this is a valid netcdf name. This should be done
92 * before the name is normalized, because it gives better error
93 * codes for bad utf8 strings. */
94 if ((retval = NC_check_name(name)))
95 return retval;
96
97 /* Normalize the name. */
98 if ((retval = nc_utf8_normalize((const unsigned char *)name,
99 (unsigned char **)&temp)))
100 return retval;
101
102 /* Check length of normalized name. */
103 if (strlen(temp) > NC_MAX_NAME)
104 {
105 free(temp);
106 return NC_EMAXNAME;
107 }
108
109 /* Copy the normalized name. */
110 strcpy(norm_name, temp);
111 free(temp);
112
113 return NC_NOERR;
114}
115
136int
137nc4_file_list_add(int ncid, const char *path, int mode, void **dispatchdata)
138{
139 NC *nc;
140 int ret;
141
142 /* Find NC pointer for this file. */
143 if ((ret = NC_check_id(ncid, &nc)))
144 return ret;
145
146 /* Add necessary structs to hold netcdf-4 file data. This is where
147 * the NC_FILE_INFO_T struct is allocated for the file. */
148 if ((ret = nc4_nc4f_list_add(nc, path, mode)))
149 return ret;
150
151 /* If the user wants a pointer to the NC_FILE_INFO_T, then provide
152 * it. */
153 if (dispatchdata)
154 *dispatchdata = nc->dispatchdata;
155
156 return NC_NOERR;
157}
158
172int
173nc4_file_change_ncid(int ncid, unsigned short new_ncid_index)
174{
175 NC *nc;
176 int ret;
177
178 LOG((2, "%s: ncid %d new_ncid_index %d", __func__, ncid, new_ncid_index));
179
180 /* Find NC pointer for this file. */
181 if ((ret = NC_check_id(ncid, &nc)))
182 return ret;
183
184 /* Move it in the list. It will faile if list spot is already
185 * occupied. */
186 LOG((3, "moving nc->ext_ncid %d nc->ext_ncid >> ID_SHIFT %d",
187 nc->ext_ncid, nc->ext_ncid >> ID_SHIFT));
188 if (NC4_move_in_NCList(nc, new_ncid_index))
189 return NC_EIO;
190 LOG((3, "moved to new_ncid_index %d new nc->ext_ncid %d", new_ncid_index,
191 nc->ext_ncid));
192
193 return NC_NOERR;
194}
195
215int
216nc4_file_list_get(int ncid, char **path, int *mode, void **dispatchdata)
217{
218 NC *nc;
219 int ret;
220
221 /* Find NC pointer for this file. */
222 if ((ret = NC_check_id(ncid, &nc)))
223 return ret;
224
225 /* If the user wants path, give it. */
226 if (path)
227 strncpy(*path, nc->path, NC_MAX_NAME);
228
229 /* If the user wants mode, give it. */
230 if (mode)
231 *mode = nc->mode;
232
233 /* If the user wants dispatchdata, give it. */
234 if (dispatchdata)
235 *dispatchdata = nc->dispatchdata;
236
237 return NC_NOERR;
238}
239
254int
255nc4_nc4f_list_add(NC *nc, const char *path, int mode)
256{
257 NC_FILE_INFO_T *h5;
258 int retval;
259
260 assert(nc && !NC4_DATA(nc) && path);
261
262 /* We need to malloc and initialize the substructure
263 NC_FILE_INFO_T. */
264 if (!(h5 = calloc(1, sizeof(NC_FILE_INFO_T))))
265 return NC_ENOMEM;
266 nc->dispatchdata = h5;
267 h5->controller = nc;
268
269 h5->hdr.sort = NCFIL;
270 h5->hdr.name = strdup(path);
271 h5->hdr.id = nc->ext_ncid;
272
273 /* Hang on to cmode, and note that we're in define mode. */
274 h5->cmode = mode | NC_INDEF;
275
276 /* The next_typeid needs to be set beyond the end of our atomic
277 * types. */
278 h5->next_typeid = NC_FIRSTUSERTYPEID;
279
280 /* Initialize lists for dimensions, types, and groups. */
281 h5->alldims = nclistnew();
282 h5->alltypes = nclistnew();
283 h5->allgroups = nclistnew();
284
285 /* There's always at least one open group - the root
286 * group. Allocate space for one group's worth of information. Set
287 * its grp id, name, and allocate associated empty lists. */
288 if ((retval = nc4_grp_list_add(h5, NULL, NC_GROUP_NAME, &h5->root_grp)))
289 return retval;
290
291 return NC_NOERR;
292}
293
306int
307nc4_find_nc4_grp(int ncid, NC_GRP_INFO_T **grp)
308{
309 return nc4_find_nc_grp_h5(ncid, NULL, grp, NULL);
310}
311
327int
328nc4_find_grp_h5(int ncid, NC_GRP_INFO_T **grp, NC_FILE_INFO_T **h5)
329{
330 return nc4_find_nc_grp_h5(ncid, NULL, grp, h5);
331}
332
347int
348nc4_find_nc_grp_h5(int ncid, NC **nc, NC_GRP_INFO_T **grp, NC_FILE_INFO_T **h5)
349{
350 NC_GRP_INFO_T *my_grp = NULL;
351 NC_FILE_INFO_T *my_h5 = NULL;
352 NC *my_nc;
353 int retval;
354
355 /* Look up file metadata. */
356 if ((retval = NC_check_id(ncid, &my_nc)))
357 return retval;
358 my_h5 = my_nc->dispatchdata;
359 assert(my_h5 && my_h5->root_grp);
360
361 /* If we can't find it, the grp id part of ncid is bad. */
362 if (!(my_grp = nclistget(my_h5->allgroups, (ncid & GRP_ID_MASK))))
363 return NC_EBADID;
364
365 /* Return pointers to caller, if desired. */
366 if (nc)
367 *nc = my_nc;
368 if (h5)
369 *h5 = my_h5;
370 if (grp)
371 *grp = my_grp;
372
373 return NC_NOERR;
374}
375
391int
392nc4_find_grp_h5_var(int ncid, int varid, NC_FILE_INFO_T **h5, NC_GRP_INFO_T **grp,
393 NC_VAR_INFO_T **var)
394{
395 NC_FILE_INFO_T *my_h5;
396 NC_GRP_INFO_T *my_grp;
397 NC_VAR_INFO_T *my_var;
398 int retval;
399
400 /* Look up file and group metadata. */
401 if ((retval = nc4_find_grp_h5(ncid, &my_grp, &my_h5)))
402 return retval;
403 assert(my_grp && my_h5);
404
405 /* Find the var. */
406 if (!(my_var = (NC_VAR_INFO_T *)ncindexith(my_grp->vars, varid)))
407 return NC_ENOTVAR;
408 assert(my_var && my_var->hdr.id == varid);
409
410 /* Return pointers that caller wants. */
411 if (h5)
412 *h5 = my_h5;
413 if (grp)
414 *grp = my_grp;
415 if (var)
416 *var = my_var;
417
418 return NC_NOERR;
419}
420
434int
435nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim,
436 NC_GRP_INFO_T **dim_grp)
437{
438 assert(grp && grp->nc4_info && dim);
439 LOG((4, "%s: dimid %d", __func__, dimid));
440
441 /* Find the dim info. */
442 if (!((*dim) = nclistget(grp->nc4_info->alldims, dimid)))
443 return NC_EBADDIM;
444
445 /* Give the caller the group the dimension is in. */
446 if (dim_grp)
447 *dim_grp = (*dim)->container;
448
449 return NC_NOERR;
450}
451
462int
463nc4_find_var(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var)
464{
465 assert(grp && var && name);
466
467 /* Find the var info. */
468 *var = (NC_VAR_INFO_T*)ncindexlookup(grp->vars,name);
469 return NC_NOERR;
470}
471
481NC_TYPE_INFO_T *
482nc4_rec_find_named_type(NC_GRP_INFO_T *start_grp, char *name)
483{
484 NC_GRP_INFO_T *g;
485 NC_TYPE_INFO_T *type, *res;
486 int i;
487
488 assert(start_grp);
489
490 /* Does this group have the type we are searching for? */
491 type = (NC_TYPE_INFO_T*)ncindexlookup(start_grp->type,name);
492 if(type != NULL)
493 return type;
494
495 /* Search subgroups. */
496 for(i=0;i<ncindexsize(start_grp->children);i++) {
497 g = (NC_GRP_INFO_T*)ncindexith(start_grp->children,i);
498 if(g == NULL) continue;
499 if ((res = nc4_rec_find_named_type(g, name)))
500 return res;
501 }
502 /* Can't find it. Oh, woe is me! */
503 return NULL;
504}
505
517int
518nc4_find_type(const NC_FILE_INFO_T *h5, nc_type typeid, NC_TYPE_INFO_T **type)
519{
520 /* Check inputs. */
521 assert(h5);
522 if (typeid < 0 || !type)
523 return NC_EINVAL;
524 *type = NULL;
525
526 /* Atomic types don't have associated NC_TYPE_INFO_T struct, just
527 * return NOERR. */
528 if (typeid <= NC_STRING)
529 return NC_NOERR;
530
531 /* Find the type. */
532 if (!(*type = nclistget(h5->alltypes,typeid)))
533 return NC_EBADTYPID;
534
535 return NC_NOERR;
536}
537
553int
554nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum,
555 NC_ATT_INFO_T **att)
556{
557 NC_VAR_INFO_T *var;
558 NC_ATT_INFO_T *my_att;
559 NCindex *attlist = NULL;
560
561 assert(grp && grp->hdr.name && att);
562
563 LOG((4, "%s: grp->name %s varid %d attnum %d", __func__, grp->hdr.name,
564 varid, attnum));
565
566 /* Get either the global or a variable attribute list. */
567 if (varid == NC_GLOBAL)
568 {
569 attlist = grp->att;
570 }
571 else
572 {
573 var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
574 if (!var) return NC_ENOTVAR;
575
576 attlist = var->att;
577 }
578 assert(attlist);
579
580 /* Now find the attribute by name or number. If a name is provided,
581 * ignore the attnum. */
582 if (name)
583 my_att = (NC_ATT_INFO_T *)ncindexlookup(attlist, name);
584 else
585 my_att = (NC_ATT_INFO_T *)ncindexith(attlist, attnum);
586
587 if (!my_att)
588 return NC_ENOTATT;
589
590 *att = my_att;
591 return NC_NOERR;
592}
593
610int
611nc4_find_nc_att(int ncid, int varid, const char *name, int attnum,
612 NC_ATT_INFO_T **att)
613{
614 NC_GRP_INFO_T *grp;
615 int retval;
616
617 LOG((4, "nc4_find_nc_att: ncid 0x%x varid %d name %s attnum %d",
618 ncid, varid, name, attnum));
619
620 /* Find info for this file and group, and set pointer to each. */
621 if ((retval = nc4_find_grp_h5(ncid, &grp, NULL)))
622 return retval;
623 assert(grp);
624
625 return nc4_find_grp_att(grp, varid, name, attnum, att);
626}
627
636static void
637obj_track(NC_FILE_INFO_T* file, NC_OBJ* obj)
638{
639 NClist* list = NULL;
640 /* record the object in the file */
641 switch (obj->sort) {
642 case NCDIM: list = file->alldims; break;
643 case NCTYP: list = file->alltypes; break;
644 case NCGRP: list = file->allgroups; break;
645 default:
646 assert(NC_FALSE);
647 }
648 /* Insert at the appropriate point in the list */
649 nclistset(list,obj->id,obj);
650}
651
666int
667nc4_var_list_add2(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var)
668{
669 NC_VAR_INFO_T *new_var = NULL;
670
671 /* Allocate storage for new variable. */
672 if (!(new_var = calloc(1, sizeof(NC_VAR_INFO_T))))
673 return NC_ENOMEM;
674 new_var->hdr.sort = NCVAR;
675 new_var->container = grp;
676
677 /* These are the HDF5-1.8.4 defaults. */
678 new_var->chunk_cache_size = nc4_chunk_cache_size;
679 new_var->chunk_cache_nelems = nc4_chunk_cache_nelems;
680 new_var->chunk_cache_preemption = nc4_chunk_cache_preemption;
681
682 /* Now fill in the values in the var info structure. */
683 new_var->hdr.id = ncindexsize(grp->vars);
684 if (!(new_var->hdr.name = strdup(name))) {
685 if(new_var)
686 free(new_var);
687 return NC_ENOMEM;
688 }
689
690 /* Create an indexed list for the attributes. */
691 new_var->att = ncindexnew(0);
692
693 /* Officially track it */
694 ncindexadd(grp->vars, (NC_OBJ *)new_var);
695
696 /* Set the var pointer, if one was given */
697 if (var)
698 *var = new_var;
699
700 return NC_NOERR;
701}
702
715int
716nc4_var_set_ndims(NC_VAR_INFO_T *var, int ndims)
717{
718 assert(var);
719
720 /* Remember the number of dimensions. */
721 var->ndims = ndims;
722
723 /* Allocate space for dimension information. */
724 if (ndims)
725 {
726 if (!(var->dim = calloc(ndims, sizeof(NC_DIM_INFO_T *))))
727 return NC_ENOMEM;
728 if (!(var->dimids = calloc(ndims, sizeof(int))))
729 return NC_ENOMEM;
730
731 /* Initialize dimids to illegal values (-1). See the comment
732 in nc4_rec_match_dimscales(). */
733 memset(var->dimids, -1, ndims * sizeof(int));
734 }
735
736 return NC_NOERR;
737}
738
753int
754nc4_var_list_add(NC_GRP_INFO_T* grp, const char* name, int ndims,
755 NC_VAR_INFO_T **var)
756{
757 int retval;
758
759 if ((retval = nc4_var_list_add2(grp, name, var)))
760 return retval;
761 if ((retval = nc4_var_set_ndims(*var, ndims)))
762 return retval;
763
764 return NC_NOERR;
765}
766
780int
781nc4_dim_list_add(NC_GRP_INFO_T *grp, const char *name, size_t len,
782 int assignedid, NC_DIM_INFO_T **dim)
783{
784 NC_DIM_INFO_T *new_dim = NULL;
785
786 assert(grp && name);
787
788 /* Allocate memory for dim metadata. */
789 if (!(new_dim = calloc(1, sizeof(NC_DIM_INFO_T))))
790 return NC_ENOMEM;
791
792 new_dim->hdr.sort = NCDIM;
793
794 /* Assign the dimension ID. */
795 if (assignedid >= 0)
796 new_dim->hdr.id = assignedid;
797 else
798 new_dim->hdr.id = grp->nc4_info->next_dimid++;
799
800 /* Remember the name and create a hash. */
801 if (!(new_dim->hdr.name = strdup(name))) {
802 if(new_dim)
803 free(new_dim);
804
805 return NC_ENOMEM;
806 }
807
808 /* Is dimension unlimited? */
809 new_dim->len = len;
810 if (len == NC_UNLIMITED)
811 new_dim->unlimited = NC_TRUE;
812
813 /* Remember the containing group. */
814 new_dim->container = grp;
815
816 /* Add object to dimension list for this group. */
817 ncindexadd(grp->dim, (NC_OBJ *)new_dim);
818 obj_track(grp->nc4_info, (NC_OBJ *)new_dim);
819
820 /* Set the dim pointer, if one was given */
821 if (dim)
822 *dim = new_dim;
823
824 return NC_NOERR;
825}
826
839int
840nc4_att_list_add(NCindex *list, const char *name, NC_ATT_INFO_T **att)
841{
842 NC_ATT_INFO_T *new_att = NULL;
843
844 LOG((3, "%s: name %s ", __func__, name));
845
846 if (!(new_att = calloc(1, sizeof(NC_ATT_INFO_T))))
847 return NC_ENOMEM;
848 new_att->hdr.sort = NCATT;
849
850 /* Fill in the information we know. */
851 new_att->hdr.id = ncindexsize(list);
852 if (!(new_att->hdr.name = strdup(name))) {
853 if(new_att)
854 free(new_att);
855 return NC_ENOMEM;
856 }
857
858 /* Add object to list as specified by its number */
859 ncindexadd(list, (NC_OBJ *)new_att);
860
861 /* Set the attribute pointer, if one was given */
862 if (att)
863 *att = new_att;
864
865 return NC_NOERR;
866}
867
882int
883nc4_grp_list_add(NC_FILE_INFO_T *h5, NC_GRP_INFO_T *parent, char *name,
884 NC_GRP_INFO_T **grp)
885{
886 NC_GRP_INFO_T *new_grp;
887
888 /* Check inputs. */
889 assert(h5 && name);
890 LOG((3, "%s: name %s ", __func__, name));
891
892 /* Get the memory to store this groups info. */
893 if (!(new_grp = calloc(1, sizeof(NC_GRP_INFO_T))))
894 return NC_ENOMEM;
895
896 /* Fill in this group's information. */
897 new_grp->hdr.sort = NCGRP;
898 new_grp->nc4_info = h5;
899 new_grp->parent = parent;
900
901 /* Assign the group ID. The root group will get id 0. */
902 new_grp->hdr.id = h5->next_nc_grpid++;
903 assert(parent || !new_grp->hdr.id);
904
905 /* Handle the group name. */
906 if (!(new_grp->hdr.name = strdup(name)))
907 {
908 free(new_grp);
909 return NC_ENOMEM;
910 }
911
912 /* Set up new indexed lists for stuff this group can contain. */
913 new_grp->children = ncindexnew(0);
914 new_grp->dim = ncindexnew(0);
915 new_grp->att = ncindexnew(0);
916 new_grp->type = ncindexnew(0);
917 new_grp->vars = ncindexnew(0);
918
919 /* Add object to lists */
920 if (parent)
921 ncindexadd(parent->children, (NC_OBJ *)new_grp);
922 obj_track(h5, (NC_OBJ *)new_grp);
923
924 /* Set the group pointer, if one was given */
925 if (grp)
926 *grp = new_grp;
927
928 return NC_NOERR;
929}
930
944int
945nc4_check_dup_name(NC_GRP_INFO_T *grp, char *name)
946{
947 NC_TYPE_INFO_T *type;
948 NC_GRP_INFO_T *g;
949 NC_VAR_INFO_T *var;
950
951 /* Any types of this name? */
952 type = (NC_TYPE_INFO_T*)ncindexlookup(grp->type,name);
953 if(type != NULL)
954 return NC_ENAMEINUSE;
955
956 /* Any child groups of this name? */
957 g = (NC_GRP_INFO_T*)ncindexlookup(grp->children,name);
958 if(g != NULL)
959 return NC_ENAMEINUSE;
960
961 /* Any variables of this name? */
962 var = (NC_VAR_INFO_T*)ncindexlookup(grp->vars,name);
963 if(var != NULL)
964 return NC_ENAMEINUSE;
965
966 return NC_NOERR;
967}
968
982int
983nc4_type_new(size_t size, const char *name, int assignedid,
984 NC_TYPE_INFO_T **type)
985{
986 NC_TYPE_INFO_T *new_type;
987
988 LOG((4, "%s: size %d name %s assignedid %d", __func__, size, name, assignedid));
989
990 /* Check inputs. */
991 assert(type);
992
993 /* Allocate memory for the type */
994 if (!(new_type = calloc(1, sizeof(NC_TYPE_INFO_T))))
995 return NC_ENOMEM;
996 new_type->hdr.sort = NCTYP;
997 new_type->hdr.id = assignedid;
998
999 /* Remember info about this type. */
1000 new_type->size = size;
1001 if (!(new_type->hdr.name = strdup(name))) {
1002 free(new_type);
1003 return NC_ENOMEM;
1004 }
1005
1006 /* Return a pointer to the new type. */
1007 *type = new_type;
1008
1009 return NC_NOERR;
1010}
1011
1025int
1026nc4_type_list_add(NC_GRP_INFO_T *grp, size_t size, const char *name,
1027 NC_TYPE_INFO_T **type)
1028{
1029 NC_TYPE_INFO_T *new_type;
1030 int retval;
1031
1032 /* Check inputs. */
1033 assert(grp && name && type);
1034 LOG((4, "%s: size %d name %s", __func__, size, name));
1035
1036 /* Create the new TYPE_INFO struct. */
1037 if ((retval = nc4_type_new(size, name, grp->nc4_info->next_typeid,
1038 &new_type)))
1039 return retval;
1040 grp->nc4_info->next_typeid++;
1041
1042 /* Increment the ref. count on the type */
1043 new_type->rc++;
1044
1045 /* Add object to lists */
1046 ncindexadd(grp->type, (NC_OBJ *)new_type);
1047 obj_track(grp->nc4_info,(NC_OBJ*)new_type);
1048
1049 /* Return a pointer to the new type. */
1050 *type = new_type;
1051
1052 return NC_NOERR;
1053}
1054
1068int
1069nc4_field_list_add(NC_TYPE_INFO_T *parent, const char *name,
1070 size_t offset, nc_type xtype, int ndims,
1071 const int *dim_sizesp)
1072{
1073 NC_FIELD_INFO_T *field;
1074
1075 /* Name has already been checked and UTF8 normalized. */
1076 if (!name)
1077 return NC_EINVAL;
1078
1079 /* Allocate storage for this field information. */
1080 if (!(field = calloc(1, sizeof(NC_FIELD_INFO_T))))
1081 return NC_ENOMEM;
1082 field->hdr.sort = NCFLD;
1083
1084 /* Store the information about this field. */
1085 if (!(field->hdr.name = strdup(name)))
1086 {
1087 free(field);
1088 return NC_ENOMEM;
1089 }
1090 field->nc_typeid = xtype;
1091 field->offset = offset;
1092 field->ndims = ndims;
1093 if (ndims)
1094 {
1095 int i;
1096 if (!(field->dim_size = malloc(ndims * sizeof(int))))
1097 {
1098 free(field->hdr.name);
1099 free(field);
1100 return NC_ENOMEM;
1101 }
1102 for (i = 0; i < ndims; i++)
1103 field->dim_size[i] = dim_sizesp[i];
1104 }
1105
1106 /* Add object to lists */
1107 field->hdr.id = nclistlength(parent->u.c.field);
1108 nclistpush(parent->u.c.field,field);
1109
1110 return NC_NOERR;
1111}
1112
1125int
1126nc4_enum_member_add(NC_TYPE_INFO_T *parent, size_t size,
1127 const char *name, const void *value)
1128{
1129 NC_ENUM_MEMBER_INFO_T *member;
1130
1131 /* Name has already been checked. */
1132 assert(name && size > 0 && value);
1133 LOG((4, "%s: size %d name %s", __func__, size, name));
1134
1135 /* Allocate storage for this field information. */
1136 if (!(member = calloc(1, sizeof(NC_ENUM_MEMBER_INFO_T))))
1137 return NC_ENOMEM;
1138 if (!(member->value = malloc(size))) {
1139 free(member);
1140 return NC_ENOMEM;
1141 }
1142 if (!(member->name = strdup(name))) {
1143 free(member->value);
1144 free(member);
1145 return NC_ENOMEM;
1146 }
1147
1148 /* Store the value for this member. */
1149 memcpy(member->value, value, size);
1150
1151 /* Add object to list */
1152 nclistpush(parent->u.e.enum_member,member);
1153
1154 return NC_NOERR;
1155}
1156
1165static void
1166field_free(NC_FIELD_INFO_T *field)
1167{
1168 /* Free some stuff. */
1169 if (field->hdr.name)
1170 free(field->hdr.name);
1171 if (field->dim_size)
1172 free(field->dim_size);
1173
1174 /* Nc_Free the memory. */
1175 free(field);
1176}
1177
1187int
1188nc4_type_free(NC_TYPE_INFO_T *type)
1189{
1190 int i;
1191
1192 assert(type && type->rc && type->hdr.name);
1193
1194 /* Decrement the ref. count on the type */
1195 type->rc--;
1196
1197 /* Release the type, if the ref. count drops to zero */
1198 if (type->rc == 0)
1199 {
1200 LOG((4, "%s: deleting type %s", __func__, type->hdr.name));
1201
1202 /* Free the name. */
1203 free(type->hdr.name);
1204
1205 /* Enums and compound types have lists of fields to clean up. */
1206 switch (type->nc_type_class)
1207 {
1208 case NC_COMPOUND:
1209 {
1210 NC_FIELD_INFO_T *field;
1211
1212 /* Delete all the fields in this type (there will be some if its a
1213 * compound). */
1214 for(i=0;i<nclistlength(type->u.c.field);i++) {
1215 field = nclistget(type->u.c.field,i);
1216 field_free(field);
1217 }
1218 nclistfree(type->u.c.field);
1219 }
1220 break;
1221
1222 case NC_ENUM:
1223 {
1224 NC_ENUM_MEMBER_INFO_T *enum_member;
1225
1226 /* Delete all the enum_members, if any. */
1227 for(i=0;i<nclistlength(type->u.e.enum_member);i++) {
1228 enum_member = nclistget(type->u.e.enum_member,i);
1229 free(enum_member->value);
1230 free(enum_member->name);
1231 free(enum_member);
1232 }
1233 nclistfree(type->u.e.enum_member);
1234 }
1235 break;
1236
1237 default:
1238 break;
1239 }
1240
1241 /* Release the memory. */
1242 free(type);
1243 }
1244
1245 return NC_NOERR;
1246}
1247
1256int
1257nc4_att_free(NC_ATT_INFO_T *att)
1258{
1259 int i;
1260
1261 assert(att);
1262 LOG((3, "%s: name %s ", __func__, att->hdr.name));
1263
1264 /* Free memory that was malloced to hold data for this
1265 * attribute. */
1266 if (att->data)
1267 free(att->data);
1268
1269 /* Free the name. */
1270 if (att->hdr.name)
1271 free(att->hdr.name);
1272
1273 /* If this is a string array attribute, delete all members of the
1274 * string array, then delete the array of pointers to strings. (The
1275 * array was filled with pointers by HDF5 when the att was read,
1276 * and memory for each string was allocated by HDF5. That's why I
1277 * use free and not nc_free, because the netCDF library didn't
1278 * allocate the memory that is being freed.) */
1279 if (att->stdata)
1280 {
1281 for (i = 0; i < att->len; i++)
1282 if(att->stdata[i])
1283 free(att->stdata[i]);
1284 free(att->stdata);
1285 }
1286
1287 /* If this att has vlen data, release it. */
1288 if (att->vldata)
1289 {
1290 for (i = 0; i < att->len; i++)
1291 nc_free_vlen(&att->vldata[i]);
1292 free(att->vldata);
1293 }
1294
1295 free(att);
1296 return NC_NOERR;
1297}
1298
1308static int
1309var_free(NC_VAR_INFO_T *var)
1310{
1311 int i;
1312 int retval;
1313
1314 assert(var);
1315 LOG((4, "%s: deleting var %s", __func__, var->hdr.name));
1316
1317 /* First delete all the attributes attached to this var. */
1318 for (i = 0; i < ncindexsize(var->att); i++)
1319 if ((retval = nc4_att_free((NC_ATT_INFO_T *)ncindexith(var->att, i))))
1320 return retval;
1321 ncindexfree(var->att);
1322
1323 /* Free some things that may be allocated. */
1324 if (var->chunksizes)
1325 free(var->chunksizes);
1326
1327 if (var->alt_name)
1328 free(var->alt_name);
1329
1330 if (var->dimids)
1331 free(var->dimids);
1332
1333 if (var->dim)
1334 free(var->dim);
1335
1336 /* Delete any fill value allocation. */
1337 if (var->fill_value)
1338 free(var->fill_value);
1339
1340 /* Release type information */
1341 if (var->type_info)
1342 if ((retval = nc4_type_free(var->type_info)))
1343 return retval;
1344
1345 /* Do this last because debugging may need it */
1346 if (var->hdr.name)
1347 free(var->hdr.name);
1348
1349 /* Delete the var. */
1350 free(var);
1351
1352 return NC_NOERR;
1353}
1354
1364int
1365nc4_var_list_del(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
1366{
1367 int i;
1368
1369 assert(var && grp);
1370
1371 /* Remove from lists */
1372 i = ncindexfind(grp->vars, (NC_OBJ *)var);
1373 if (i >= 0)
1374 ncindexidel(grp->vars, i);
1375
1376 return var_free(var);
1377}
1378
1387static int
1388dim_free(NC_DIM_INFO_T *dim)
1389{
1390 assert(dim);
1391 LOG((4, "%s: deleting dim %s", __func__, dim->hdr.name));
1392
1393 /* Free memory allocated for names. */
1394 if (dim->hdr.name)
1395 free(dim->hdr.name);
1396
1397 free(dim);
1398 return NC_NOERR;
1399}
1400
1410int
1411nc4_dim_list_del(NC_GRP_INFO_T *grp, NC_DIM_INFO_T *dim)
1412{
1413 if (grp && dim)
1414 {
1415 int pos = ncindexfind(grp->dim, (NC_OBJ *)dim);
1416 if(pos >= 0)
1417 ncindexidel(grp->dim, pos);
1418 }
1419
1420 return dim_free(dim);
1421}
1422
1432int
1433nc4_rec_grp_del(NC_GRP_INFO_T *grp)
1434{
1435 int i;
1436 int retval;
1437
1438 assert(grp);
1439 LOG((3, "%s: grp->name %s", __func__, grp->hdr.name));
1440
1441 /* Recursively call this function for each child, if any, stopping
1442 * if there is an error. */
1443 for (i = 0; i < ncindexsize(grp->children); i++)
1444 if ((retval = nc4_rec_grp_del((NC_GRP_INFO_T *)ncindexith(grp->children,
1445 i))))
1446 return retval;
1447 ncindexfree(grp->children);
1448
1449 /* Free attributes */
1450 for (i = 0; i < ncindexsize(grp->att); i++)
1451 if ((retval = nc4_att_free((NC_ATT_INFO_T *)ncindexith(grp->att, i))))
1452 return retval;
1453 ncindexfree(grp->att);
1454
1455 /* Delete all vars. */
1456 for (i = 0; i < ncindexsize(grp->vars); i++) {
1457 NC_VAR_INFO_T* v = (NC_VAR_INFO_T *)ncindexith(grp->vars, i);
1458 if ((retval = var_free(v)))
1459 return retval;
1460 }
1461 ncindexfree(grp->vars);
1462
1463 /* Delete all dims, and free the list of dims. */
1464 for (i = 0; i < ncindexsize(grp->dim); i++)
1465 if ((retval = dim_free((NC_DIM_INFO_T *)ncindexith(grp->dim, i))))
1466 return retval;
1467 ncindexfree(grp->dim);
1468
1469 /* Delete all types. */
1470 for (i = 0; i < ncindexsize(grp->type); i++)
1471 if ((retval = nc4_type_free((NC_TYPE_INFO_T *)ncindexith(grp->type, i))))
1472 return retval;
1473 ncindexfree(grp->type);
1474
1475 /* Free the name. */
1476 free(grp->hdr.name);
1477
1478 /* Free up this group */
1479 free(grp);
1480
1481 return NC_NOERR;
1482}
1483
1494int
1495nc4_att_list_del(NCindex *list, NC_ATT_INFO_T *att)
1496{
1497 assert(att && list);
1498 ncindexidel(list, ((NC_OBJ *)att)->id);
1499 return nc4_att_free(att);
1500}
1501
1515int
1517{
1518 NC_FILE_INFO_T *h5;
1519 int retval;
1520
1521 /* Find our metadata for this file. */
1522 if ((retval = nc4_find_grp_h5(ncid, NULL, &h5)))
1523 return retval;
1524 assert(h5);
1525
1526 /* Delete the file resources. */
1527 if ((retval = nc4_nc4f_list_del(h5)))
1528 return retval;
1529
1530 return NC_NOERR;
1531}
1532
1542int
1543nc4_nc4f_list_del(NC_FILE_INFO_T *h5)
1544{
1545 int retval;
1546
1547 assert(h5);
1548
1549 /* Delete all the list contents for vars, dims, and atts, in each
1550 * group. */
1551 if ((retval = nc4_rec_grp_del(h5->root_grp)))
1552 return retval;
1553
1554 /* Cleanup these (extra) lists of all dims, groups, and types. */
1555 nclistfree(h5->alldims);
1556 nclistfree(h5->allgroups);
1557 nclistfree(h5->alltypes);
1558
1559 /* Free the NC_FILE_INFO_T struct. */
1560 nullfree(h5->hdr.name);
1561 free(h5);
1562
1563 return NC_NOERR;
1564}
1565
1579int
1580nc4_normalize_name(const char *name, char *norm_name)
1581{
1582 char *temp_name;
1583 int stat = nc_utf8_normalize((const unsigned char *)name,(unsigned char **)&temp_name);
1584 if(stat != NC_NOERR)
1585 return stat;
1586 if (strlen(temp_name) > NC_MAX_NAME)
1587 {
1588 free(temp_name);
1589 return NC_EMAXNAME;
1590 }
1591 strcpy(norm_name, temp_name);
1592 free(temp_name);
1593 return NC_NOERR;
1594}
1595
1596#ifdef ENABLE_SET_LOG_LEVEL
1597
1612int
1613nc_set_log_level(int new_level)
1614{
1615#ifdef LOGGING
1616 /* Remember the new level. */
1617 nc_log_level = new_level;
1618 LOG((4, "log_level changed to %d", nc_log_level));
1619#endif /*LOGGING */
1620 return 0;
1621}
1622#endif /* ENABLE_SET_LOG_LEVEL */
1623
1624#ifdef LOGGING
1625#define MAX_NESTS 10
1635static int
1636rec_print_metadata(NC_GRP_INFO_T *grp, int tab_count)
1637{
1638 NC_ATT_INFO_T *att;
1639 NC_VAR_INFO_T *var;
1640 NC_DIM_INFO_T *dim;
1641 NC_TYPE_INFO_T *type;
1642 NC_FIELD_INFO_T *field;
1643 char tabs[MAX_NESTS+1] = "";
1644 char temp_string[10];
1645 int t, retval, d, i;
1646
1647 /* Come up with a number of tabs relative to the group. */
1648 for (t = 0; t < tab_count && t < MAX_NESTS; t++)
1649 tabs[t] = '\t';
1650 tabs[t] = '\0';
1651
1652 LOG((2, "%s GROUP - %s nc_grpid: %d nvars: %d natts: %d",
1653 tabs, grp->hdr.name, grp->hdr.id, ncindexsize(grp->vars), ncindexsize(grp->att)));
1654
1655 for (i = 0; i < ncindexsize(grp->att); i++)
1656 {
1657 att = (NC_ATT_INFO_T *)ncindexith(grp->att, i);
1658 assert(att);
1659 LOG((2, "%s GROUP ATTRIBUTE - attnum: %d name: %s type: %d len: %d",
1660 tabs, att->hdr.id, att->hdr.name, att->nc_typeid, att->len));
1661 }
1662
1663 for (i = 0; i < ncindexsize(grp->dim); i++)
1664 {
1665 dim = (NC_DIM_INFO_T *)ncindexith(grp->dim, i);
1666 assert(dim);
1667 LOG((2, "%s DIMENSION - dimid: %d name: %s len: %d unlimited: %d",
1668 tabs, dim->hdr.id, dim->hdr.name, dim->len, dim->unlimited));
1669 }
1670
1671 for (i = 0; i < ncindexsize(grp->vars); i++)
1672 {
1673 int j;
1674 char storage_str[NC_MAX_NAME] = "";
1675 char *dims_string = NULL;
1676
1677 var = (NC_VAR_INFO_T*)ncindexith(grp->vars,i);
1678 assert(var);
1679 if (var->ndims > 0)
1680 {
1681 if (!(dims_string = malloc(sizeof(char) * var->ndims * 4)))
1682 return NC_ENOMEM;
1683 strcpy(dims_string, "");
1684 for (d = 0; d < var->ndims; d++)
1685 {
1686 sprintf(temp_string, " %d", var->dimids[d]);
1687 strcat(dims_string, temp_string);
1688 }
1689 }
1690 if (!var->meta_read)
1691 strcat(storage_str, "unknown");
1692 else if (var->storage == NC_CONTIGUOUS)
1693 strcat(storage_str, "contiguous");
1694 else if (var->storage == NC_COMPACT)
1695 strcat(storage_str, "compact");
1696 else
1697 strcat(storage_str, "chunked");
1698 LOG((2, "%s VARIABLE - varid: %d name: %s ndims: %d "
1699 "dimids:%s storage: %s", tabs, var->hdr.id, var->hdr.name,
1700 var->ndims,
1701 (dims_string ? dims_string : " -"), storage_str));
1702 for (j = 0; j < ncindexsize(var->att); j++)
1703 {
1704 att = (NC_ATT_INFO_T *)ncindexith(var->att, j);
1705 assert(att);
1706 LOG((2, "%s VAR ATTRIBUTE - attnum: %d name: %s type: %d len: %d",
1707 tabs, att->hdr.id, att->hdr.name, att->nc_typeid, att->len));
1708 }
1709 if (dims_string)
1710 free(dims_string);
1711 }
1712
1713 for (i = 0; i < ncindexsize(grp->type); i++)
1714 {
1715 type = (NC_TYPE_INFO_T*)ncindexith(grp->type, i);
1716 assert(type);
1717 LOG((2, "%s TYPE - nc_typeid: %d size: %d committed: %d name: %s",
1718 tabs, type->hdr.id, type->size, (int)type->committed, type->hdr.name));
1719 /* Is this a compound type? */
1720 if (type->nc_type_class == NC_COMPOUND)
1721 {
1722 int j;
1723 LOG((3, "compound type"));
1724 for (j = 0; j < nclistlength(type->u.c.field); j++)
1725 {
1726 field = (NC_FIELD_INFO_T *)nclistget(type->u.c.field, j);
1727 LOG((4, "field %s offset %d nctype %d ndims %d", field->hdr.name,
1728 field->offset, field->nc_typeid, field->ndims));
1729 }
1730 }
1731 else if (type->nc_type_class == NC_VLEN)
1732 {
1733 LOG((3, "VLEN type"));
1734 LOG((4, "base_nc_type: %d", type->u.v.base_nc_typeid));
1735 }
1736 else if (type->nc_type_class == NC_OPAQUE)
1737 LOG((3, "Opaque type"));
1738 else if (type->nc_type_class == NC_ENUM)
1739 {
1740 LOG((3, "Enum type"));
1741 LOG((4, "base_nc_type: %d", type->u.e.base_nc_typeid));
1742 }
1743 else
1744 {
1745 LOG((0, "Unknown class: %d", type->nc_type_class));
1746 return NC_EBADTYPE;
1747 }
1748 }
1749
1750 /* Call self for each child of this group. */
1751 for (i = 0; i < ncindexsize(grp->children); i++)
1752 if ((retval = rec_print_metadata((NC_GRP_INFO_T *)ncindexith(grp->children, i),
1753 tab_count + 1)))
1754 return retval;
1755
1756 return NC_NOERR;
1757}
1758
1769int
1770log_metadata_nc(NC_FILE_INFO_T *h5)
1771{
1772 LOG((2, "*** NetCDF-4 Internal Metadata: int_ncid 0x%x ext_ncid 0x%x",
1773 h5->root_grp->nc4_info->controller->int_ncid,
1774 h5->root_grp->nc4_info->controller->ext_ncid));
1775 if (!h5)
1776 {
1777 LOG((2, "This is a netCDF-3 file."));
1778 return NC_NOERR;
1779 }
1780 LOG((2, "FILE - path: %s cmode: 0x%x parallel: %d redef: %d "
1781 "fill_mode: %d no_write: %d next_nc_grpid: %d", h5->root_grp->nc4_info->controller->path,
1782 h5->cmode, (int)h5->parallel, (int)h5->redef, h5->fill_mode, (int)h5->no_write,
1783 h5->next_nc_grpid));
1784 if(nc_log_level >= 2)
1785 return rec_print_metadata(h5->root_grp, 0);
1786 return NC_NOERR;
1787}
1788
1789#endif /*LOGGING */
1790
1802int
1804{
1805 int retval = NC_NOERR;
1806#ifdef LOGGING
1807 NC_FILE_INFO_T *h5;
1808 int old_log_level = nc_log_level;
1809
1810 /* Find file metadata. */
1811 if ((retval = nc4_find_grp_h5(ncid, NULL, &h5)))
1812 return retval;
1813
1814 /* Log level must be 2 to see metadata. */
1815 nc_log_level = 2;
1816 retval = log_metadata_nc(h5);
1817 nc_log_level = old_log_level;
1818#endif /*LOGGING*/
1819 return retval;
1820}
1821
1829const NC_reservedatt*
1830NC_findreserved(const char* name)
1831{
1832 int n = NRESERVED;
1833 int L = 0;
1834 int R = (n - 1);
1835 for(;;) {
1836 if(L > R) break;
1837 int m = (L + R) / 2;
1838 const NC_reservedatt* p = &NC_reserved[m];
1839 int cmp = strcmp(p->name,name);
1840 if(cmp == 0) return p;
1841 if(cmp < 0)
1842 L = (m + 1);
1843 else /*cmp > 0*/
1844 R = (m - 1);
1845 }
1846 return NULL;
1847}
1848
1849static int
1850NC4_move_in_NCList(NC* nc, int new_id)
1851{
1852 int stat = move_in_NCList(nc,new_id);
1853 if(stat == NC_NOERR) {
1854 /* Synchronize header */
1855 if(nc->dispatchdata)
1856 ((NC_OBJ*)nc->dispatchdata)->id = nc->ext_ncid;
1857 }
1858 return stat;
1859}
EXTERNL int nc_free_vlen(nc_vlen_t *vl)
Free memory in a VLEN object.
Definition dvlen.c:41
int nc4_att_list_add(NCindex *list, const char *name, NC_ATT_INFO_T **att)
int nc4_grp_list_add(NC_FILE_INFO_T *h5, NC_GRP_INFO_T *parent, char *name, NC_GRP_INFO_T **grp)
int nc4_dim_list_del(NC_GRP_INFO_T *grp, NC_DIM_INFO_T *dim)
int nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum, NC_ATT_INFO_T **att)
size_t nc4_chunk_cache_size
Default chunk cache size.
Definition nc4internal.c:54
int nc4_field_list_add(NC_TYPE_INFO_T *parent, const char *name, size_t offset, nc_type xtype, int ndims, const int *dim_sizesp)
static void field_free(NC_FIELD_INFO_T *field)
NC_TYPE_INFO_T * nc4_rec_find_named_type(NC_GRP_INFO_T *start_grp, char *name)
int nc4_check_name(const char *name, char *norm_name)
Definition nc4internal.c:80
int nc4_var_list_del(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
int nc4_file_list_get(int ncid, char **path, int *mode, void **dispatchdata)
int nc4_nc4f_list_del(NC_FILE_INFO_T *h5)
static int var_free(NC_VAR_INFO_T *var)
int nc4_file_list_add(int ncid, const char *path, int mode, void **dispatchdata)
int nc4_var_list_add(NC_GRP_INFO_T *grp, const char *name, int ndims, NC_VAR_INFO_T **var)
int NC4_show_metadata(int ncid)
int nc4_var_set_ndims(NC_VAR_INFO_T *var, int ndims)
int nc4_nc4f_list_add(NC *nc, const char *path, int mode)
size_t nc4_chunk_cache_nelems
Default chunk cache number of elements.
Definition nc4internal.c:55
int nc4_type_list_add(NC_GRP_INFO_T *grp, size_t size, const char *name, NC_TYPE_INFO_T **type)
int nc4_find_var(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var)
const NC_reservedatt * NC_findreserved(const char *name)
int nc4_att_list_del(NCindex *list, NC_ATT_INFO_T *att)
int nc4_file_list_del(int ncid)
int nc4_find_nc4_grp(int ncid, NC_GRP_INFO_T **grp)
int nc4_dim_list_add(NC_GRP_INFO_T *grp, const char *name, size_t len, int assignedid, NC_DIM_INFO_T **dim)
static const NC_reservedatt NC_reserved[NRESERVED]
Definition nc4internal.c:39
int nc4_type_new(size_t size, const char *name, int assignedid, NC_TYPE_INFO_T **type)
int nc4_enum_member_add(NC_TYPE_INFO_T *parent, size_t size, const char *name, const void *value)
int nc4_find_grp_h5(int ncid, NC_GRP_INFO_T **grp, NC_FILE_INFO_T **h5)
int nc4_rec_grp_del(NC_GRP_INFO_T *grp)
int nc4_check_dup_name(NC_GRP_INFO_T *grp, char *name)
int nc4_att_free(NC_ATT_INFO_T *att)
#define NRESERVED
Definition nc4internal.c:35
int nc4_find_nc_att(int ncid, int varid, const char *name, int attnum, NC_ATT_INFO_T **att)
int nc4_find_grp_h5_var(int ncid, int varid, NC_FILE_INFO_T **h5, NC_GRP_INFO_T **grp, NC_VAR_INFO_T **var)
int nc4_file_change_ncid(int ncid, unsigned short new_ncid_index)
static int dim_free(NC_DIM_INFO_T *dim)
static void obj_track(NC_FILE_INFO_T *file, NC_OBJ *obj)
int nc4_type_free(NC_TYPE_INFO_T *type)
int nc4_normalize_name(const char *name, char *norm_name)
int nc4_var_list_add2(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var)
int nc4_find_type(const NC_FILE_INFO_T *h5, nc_type typeid, NC_TYPE_INFO_T **type)
float nc4_chunk_cache_preemption
Default chunk cache preemption.
Definition nc4internal.c:56
int nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim, NC_GRP_INFO_T **dim_grp)
int nc4_find_nc_grp_h5(int ncid, NC **nc, NC_GRP_INFO_T **grp, NC_FILE_INFO_T **h5)
Main header file for the C API.
#define NC_UNLIMITED
Size argument to nc_def_dim() for an unlimited dimension.
Definition netcdf.h:246
#define NC_EBADTYPE
Not a netcdf data type.
Definition netcdf.h:372
#define NC_VLEN
vlen (variable-length) types
Definition netcdf.h:53
#define NC_ENAMEINUSE
String match to name in use.
Definition netcdf.h:369
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition netcdf.h:410
#define NC_COMPOUND
compound types
Definition netcdf.h:56
#define NC_FIRSTUSERTYPEID
Definition netcdf.h:60
#define NC_ENUM
enum types
Definition netcdf.h:55
#define NC_CONTIGUOUS
In HDF5 files you can set storage for each variable to be either contiguous or chunked,...
Definition netcdf.h:299
#define NC_GLOBAL
Attribute id to put/get a global attribute.
Definition netcdf.h:249
#define NC_EMAXNAME
NC_MAX_NAME exceeded.
Definition netcdf.h:388
#define NC_ENOTATT
Attribute not found.
Definition netcdf.h:370
#define NC_COMPACT
In HDF5 files you can set storage for each variable to be either contiguous or chunked,...
Definition netcdf.h:300
#define NC_ENOTVAR
Variable not found.
Definition netcdf.h:384
#define NC_EINVAL
Invalid Argument.
Definition netcdf.h:340
#define NC_MAX_NAME
Maximum for classic library.
Definition netcdf.h:276
#define NC_NOERR
No Error.
Definition netcdf.h:330
#define NC_OPAQUE
opaque types
Definition netcdf.h:54
#define NC_EIO
Generic IO error.
Definition netcdf.h:419
#define NC_STRING
string
Definition netcdf.h:47
#define NC_EBADID
Not a netcdf id.
Definition netcdf.h:337
#define NC_EBADTYPID
Bad type ID.
Definition netcdf.h:459
#define NC_EBADDIM
Invalid dimension id or name.
Definition netcdf.h:373
int nc_type
The nc_type type is just an int.
Definition netcdf.h:25