1 /*********************************************************************
2  *   Copyright 2018, University Corporation for Atmospheric Research
3  *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4  *
5  *   Stuff that's common to both ncdump and nccopy
6  *
7  *********************************************************************/
8 #ifndef _UTILS_H
9 #define _UTILS_H
10 
11 #include "config.h"
12 
13 #ifndef NCSTREQ
14 #define	NCSTREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
15 #endif
16 
17 /* Delimiter for separating netCDF groups in absolute pathnames, same as for HDF5 */
18 #define NC_GRP_DELIM '/'
19 
20 typedef int bool_t;
21 enum {false=0, true=1};
22 
23 struct safebuf_t;
24 /* Buffer structure for implementing growable strings, used in
25  * preventing buffer overflows when the size needed for a character
26  * buffer cannot be easily predicted or limited to any specific
27  * maximum, such as when used in recursive function calls for nested
28  * vlens and nested compound types. */
29 typedef struct safebuf_t {
30     size_t len;			/* current length of buffer */
31     size_t cl;			/* current length of string in buffer, < len-1 */
32     char *buf;
33 } safebuf_t;
34 
35 /* structure for list of ids, such as varids or grpids specified with -v or -g option */
36 typedef struct idnode {
37     struct idnode* next;
38     int id;
39 } idnode_t;
40 
41 /* node in stack of group ids */
42 typedef struct grpnode {
43     int grpid;
44     struct grpnode *next;
45 } grpnode_t;
46 
47 /*
48  * The opaque structure to hold state of iteration over groups.
49  * (Just implemented as a stack of group ids.)
50  */
51 typedef struct {
52     int ngrps;			/* number of groups left to visit */
53     grpnode_t *top;		/* group ids left to visit */
54 } ncgiter_t;
55 
56 extern char *progname;		/* for error messages */
57 
58 #ifndef NO_NETCDF_2
59 #define NO_NETCDF_2		/* assert we aren't using any netcdf-2 stuff */
60 #endif
61 
62 #ifdef __cplusplus
63 extern "C" {
64 #endif
65 
66 /* For NDEBUG builds, provide a version of NC_CHECK that does not
67  * include a file name. Including a file name causes heartache for the
68  * debian package builders. They already use NDEBUG to turn off the
69  * file names in asserts. */
70 #ifdef NDEBUG
71 #define NC_CHECK(fncall) {int ncstat=fncall;if(ncstat!=NC_NOERR)check(ncstat,"",__LINE__);}
72 #else
73 #define NC_CHECK(fncall) {int ncstat=fncall;if(ncstat!=NC_NOERR)check(ncstat,__FILE__,__LINE__);}
74 #endif /* NDEBUG */
75 
76 /* Print error message to stderr and exit */
77 extern void	error ( const char *fmt, ... );
78 
79 /* Check error on malloc and exit with message if out of memory */
80 extern void*    emalloc ( size_t size );
81 /* Ditto calloc */
82 extern void*    ecalloc ( size_t size );
83 /* Ditto realloc */
84 extern void*    erealloc (void* p, size_t size );
85 
86 /* Check error return.  If bad, print error message and exit. */
87 extern void check(int err, const char* file, const int line);
88 
89 /* Return malloced name with chars special to CDL escaped. */
90 char* escaped_name(const char* cp);
91 
92 /* Print name of netCDF var, dim, att, group, type, member, or enum
93  * symbol with escaped special chars */
94 void print_name(const char *name);
95 
96 /* Get dimid from a full dimension path name that may include group
97  * names */
98 extern int  nc_inq_dimid2(int ncid, const char *dimname, int *dimidp);
99 
100 /* Convert a full path name to a group to the specific groupid. */
101 extern int  nc_inq_grpid2(int ncid, const char *grpname0, int *grpidp);
102 
103 /* Convert a full path name to a varid to the specific varid + grpid */
104 extern int nc_inq_varid2(int ncid, const char *path0, int* varidp, int* grpidp);
105 
106 /* Test if variable is a record variable */
107 extern int  isrecvar ( int ncid, int varid );
108 
109 /* Get a new, empty id list. */
110 extern idnode_t* newidlist(void);
111 
112 /* Add id to id list  */
113 extern void idadd(idnode_t* idlist, int id);
114 
115 /* Test if id is in id list */
116 extern bool_t	idmember ( const idnode_t* idlist, int id );
117 
118 /* Test if a group id is in group list */
119 extern bool_t	group_wanted ( int grpid, int nlgrps, const idnode_t* grpids );
120 
121 /* Check group list for missing groups */
122 extern int grp_matches(int ncid, int nlgrps, char** lgrps, idnode_t *grpids);
123 
124 /* Returns 1 if string s1 ends with string s2, 0 otherwise. */
125 extern int strendswith(const char *s1, const char *s2);
126 
127 /* Within group with id ncid, get varid of variable with name varname
128  * using nested group syntax "gp1/gp2/var" */
129 extern int nc_inq_gvarid ( int ncid, const char *varname, int *varidp );
130 
131 /* Get variable id varid within group grpid using absolute or relative pathname for variable */
132     extern int nc_inq_gvarid(int grpid, const char *varname, int *varidp);
133 
134 /* Return how many variables are named varname in any groups in ncid */
135 extern size_t nc_inq_varname_count(int ncid, char *varname);
136 
137 /* Check if any variable names specified in the list lvars (of length nlvars) are missing. */
138 extern int missing_vars(int ncid, int nlvars, char **lvars);
139 
140 /* Make list of variables from comma-delimited string */
141 extern void make_lvars(char *optarg, int *nlvarsp, char ***lvarsp);
142 
143 /* Make list of groups from comma-delimited string */
144 extern void make_lgrps(char *optarg, int *nlgrpsp, char*** lgrpsp, idnode_t **grpidsp);
145 
146 /* Release an id list */
147 extern void freeidlist(idnode_t *idlist);
148 
149 /*
150  * Simplest interface for group iteration: get total number of groups
151  * (including all descendant groups, recursively) and all group ids
152  * for start group and its descendants, in preorder.  Note that this
153  * loses information about subgroup relationships, just flattening all
154  * groups into a serial list.
155  */
156 extern int nc_inq_grps_full(int ncid, int *numgrps, int *ncids);
157 
158 /*
159  * More complex iterator interface: get group iterator for start group
160  * ncid and all its descendant groups.
161  */
162 extern int nc_get_giter(int ncid, ncgiter_t **iterp);
163 
164 /*
165  * Get group id of next group.  On first call returns start group,
166  * subsequently returns other subgroup ids in preorder.  Returns grpid
167  * of 0 (never an actual group number) when no more groups.
168  */
169 extern int nc_next_giter(ncgiter_t *iterp, int *grpid);
170 
171 /*
172  * Release memory allocated for group iterator.
173  */
174 extern void nc_free_giter(ncgiter_t *iterp);
175 extern int getrootid(int grpid);
176 
177 #ifdef __cplusplus
178 }
179 #endif
180 
181 #endif /* _UTILS_H */
182 
183