netcdf-c/ncdump/utils.h
Dennis Heimbigner 245961de00 re: github issues
https://github.com/Unidata/netcdf-c/issues/1168
    https://github.com/Unidata/netcdf-c/issues/1163
    https://github.com/Unidata/netcdf-c/issues/1162

This PR partially fixes memory leaks in the netcdf-c library,
in the ncdump utility, and in some test cases.

The netcdf-c library now runs memory clean with the assumption
that the --disable-utilities option is used. The primary remaining
problem is ncgen. Once that is fixed, I believe the netcdf-c library
will run memory clean with no limitations.

Notes
-----------
1. Memory checking was performed using gcc -fsanitize=address.
   Valgrind-based testing has yet to be performed.
2. The pnetcdf, hdf4, and examples code has not been tested.

Misc. Non-leak changes
1. Make tst_diskless2 only run when netcdf4 is enabled (issue 1162)
2. Fix CmakeLists.txt to turn off logging if ENABLE_NETCDF_4 is OFF
3. Isolated all my debug scripts into a single top-level directory
   called debug
4. Fix some USE_NETCDF4 dependencies in nc_test and nc_test4 Makefile.am
2018-10-30 20:48:12 -06:00

175 lines
5.6 KiB
C

/*********************************************************************
* Copyright 2011, University Corporation for Atmospheric Research
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
*
* Stuff that's common to both ncdump and nccopy
*
*********************************************************************/
#ifndef _UTILS_H
#define _UTILS_H
#include "config.h"
#ifndef NCSTREQ
#define NCSTREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
#endif
/* Delimiter for separating netCDF groups in absolute pathnames, same as for HDF5 */
#define NC_GRP_DELIM '/'
typedef int bool_t;
enum {false=0, true=1};
struct safebuf_t;
/* Buffer structure for implementing growable strings, used in
* preventing buffer overflows when the size needed for a character
* buffer cannot be easily predicted or limited to any specific
* maximum, such as when used in recursive function calls for nested
* vlens and nested compound types. */
typedef struct safebuf_t {
size_t len; /* current length of buffer */
size_t cl; /* current length of string in buffer, < len-1 */
char *buf;
} safebuf_t;
/* structure for list of ids, such as varids or grpids specified with -v or -g option */
typedef struct idnode {
struct idnode* next;
int id;
} idnode_t;
/* node in stack of group ids */
typedef struct grpnode {
int grpid;
struct grpnode *next;
} grpnode_t;
/*
* The opaque structure to hold state of iteration over groups.
* (Just implemented as a stack of group ids.)
*/
typedef struct {
int ngrps; /* number of groups left to visit */
grpnode_t *top; /* group ids left to visit */
} ncgiter_t;
extern char *progname; /* for error messages */
#ifndef NO_NETCDF_2
#define NO_NETCDF_2 /* assert we aren't using any netcdf-2 stuff */
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define NC_CHECK(fncall) {int ncstat=fncall;if(ncstat!=NC_NOERR)check(ncstat,__FILE__,__LINE__);}
/* Print error message to stderr and exit */
extern void error ( const char *fmt, ... );
/* Check error on malloc and exit with message if out of memory */
extern void* emalloc ( size_t size );
/* Ditto calloc */
extern void* ecalloc ( size_t size );
/* Ditto realloc */
extern void* erealloc (void* p, size_t size );
/* Check error return. If bad, print error message and exit. */
extern void check(int err, const char* file, const int line);
/* Return malloced name with chars special to CDL escaped. */
char* escaped_name(const char* cp);
/* Print name of netCDF var, dim, att, group, type, member, or enum
* symbol with escaped special chars */
void print_name(const char *name);
/* Get dimid from a full dimension path name that may include group
* names */
extern int nc_inq_dimid2(int ncid, const char *dimname, int *dimidp);
/* Convert a full path name to a group to the specific groupid. */
extern int nc_inq_grpid2(int ncid, const char *grpname0, int *grpidp);
/* Convert a full path name to a varid to the specific varid + grpid */
extern int nc_inq_varid2(int ncid, const char *path0, int* varidp, int* grpidp);
/* Test if variable is a record variable */
extern int isrecvar ( int ncid, int varid );
/* Get a new, empty id list. */
extern idnode_t* newidlist(void);
/* Add id to id list */
extern void idadd(idnode_t* idlist, int id);
/* Test if id is in id list */
extern bool_t idmember ( const idnode_t* idlist, int id );
/* Test if a group id is in group list */
extern bool_t group_wanted ( int grpid, int nlgrps, const idnode_t* grpids );
/* Check group list for missing groups */
extern int grp_matches(int ncid, int nlgrps, char** lgrps, idnode_t *grpids);
/* Returns 1 if string s1 ends with string s2, 0 otherwise. */
extern int strendswith(const char *s1, const char *s2);
/* Within group with id ncid, get varid of variable with name varname
* using nested group syntax "gp1/gp2/var" */
extern int nc_inq_gvarid ( int ncid, const char *varname, int *varidp );
/* Get variable id varid within group grpid using absolute or relative pathname for variable */
extern int nc_inq_gvarid(int grpid, const char *varname, int *varidp);
/* Return how many variables are named varname in any groups in ncid */
extern size_t nc_inq_varname_count(int ncid, char *varname);
/* Check if any variable names specified in the list lvars (of length nlvars) are missing. */
extern int missing_vars(int ncid, int nlvars, char **lvars);
/* Make list of variables from comma-delimited string */
extern void make_lvars(char *optarg, int *nlvarsp, char ***lvarsp);
/* Make list of groups from comma-delimited string */
extern void make_lgrps(char *optarg, int *nlgrpsp, char*** lgrpsp, idnode_t **grpidsp);
/* Release an id list */
extern void freeidlist(idnode_t *idlist);
/*
* Simplest interface for group iteration: get total number of groups
* (including all descendant groups, recursively) and all group ids
* for start group and its descendants, in preorder. Note that this
* loses information about subgroup relationships, just flattening all
* groups into a serial list.
*/
extern int nc_inq_grps_full(int ncid, int *numgrps, int *ncids);
/*
* More complex iterator interface: get group iterator for start group
* ncid and all its descendant groups.
*/
extern int nc_get_giter(int ncid, ncgiter_t **iterp);
/*
* Get group id of next group. On first call returns start group,
* subsequently returns other subgroup ids in preorder. Returns grpid
* of 0 (never an actual group number) when no more groups.
*/
extern int nc_next_giter(ncgiter_t *iterp, int *grpid);
/*
* Release memory allocated for group iterator.
*/
extern void nc_free_giter(ncgiter_t *iterp);
extern int getrootid(int grpid);
#ifdef __cplusplus
}
#endif
#endif /* _UTILS_H */