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