netcdf-c/ncdump/tst_vlen_data.c
Dennis Heimbigner 8b0e1134b4 Ensure that netcdf_json.h does not interfere with ncjson.
re: Issue https://github.com/Unidata/netcdf-c/issues/2419

There are effectively two json subsystems in netcdf-c.
1. ncjson.[ch] in libnetcdf
2. netcdf_json.h for use by plugins so they can be built without need
   for libnetcdf.

The netcdf_json.h file is constructed from the concatenation of
ncjson.h plus ncjson.c. It turned out that in doing this, I was
leaving some symbols externally visible so that if, for some
reason, a plugin was built and needed libnetcdf, then symbol
conflicts arose.

The solution is to prefix the declarations in ncjson.[ch] with a
macro (OPTSTATIC) that can be resolved to either nothing or to
"static". Then in netcdf_json.h, it resolves to "static" and
prevents the symbol conflicts.

Note that netcdf_json.h is constructed once in
netcdf-c/include/Makefile.am with the rule named
"makepluginjson". This means that it is included in the
distribution. However, this also means that if ncjson.[ch] is
changed, then it is necessary to invoke makepluginjson
explicitly to rebuild netcdf_json.h
2022-07-05 22:03:52 -06:00

181 lines
5.2 KiB
C

/* This is part of the netCDF package. Copyright 2018 University
Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
conditions of use. See www.unidata.ucar.edu for more info.
Create a test file with a vlen type and vlen data for ncdump to read.
$Id: tst_vlen_data.c,v 1.12 2009/11/15 00:17:59 dmh Exp $
*/
/* WARNING: this test leaks memory.
The leak may be in HDF5.
*/
#include <nc_tests.h>
#include <stdlib.h>
#include <netcdf.h>
#include <netcdf_aux.h>
#include "err_macros.h"
#define FILE5_NAME "tst_vlen_data.nc"
#define TYPE5_NAME "row_of_floats"
#define TYPE5_TYPE NC_FLOAT
#define DIM5_NAME "m"
#define DIM5_LEN 5
#define VAR5_NAME "ragged_array"
#define VAR5_RANK 1
#define ATT5_NAME "_FillValue"
#define ATT5_LEN 1
#define NROWS 5
/* Use reclaim_data */
#undef RECLAIM
int
main(int argc, char **argv)
{
int ncid;
int dimid, varid;
nc_type typeid;
char name_in[NC_MAX_NAME+1];
nc_type base_typeid;
size_t base_size_in;
int class_in;
float value_in;
int i, j;
int var_dims[VAR5_RANK];
float **array; /* a ragged array */
nc_vlen_t ragged_data[DIM5_LEN];
float missing_value = -999.0;
nc_vlen_t missing_val;
nc_vlen_t val_in;
printf("\n*** Testing vlens.\n");
printf("*** creating vlen test file %s...", FILE5_NAME);
if (nc_create(FILE5_NAME, NC_CLOBBER | NC_NETCDF4, &ncid)) ERR;
/* Create a vlen type. */
if (nc_def_vlen(ncid, TYPE5_NAME, TYPE5_TYPE, &typeid)) ERR;
/* Declare a dimension for number of rows */
if (nc_def_dim(ncid, DIM5_NAME, DIM5_LEN, &dimid)) ERR;
/* Declare a variable of the vlen type */
var_dims[0] = dimid;
if (nc_def_var(ncid, VAR5_NAME, typeid, VAR5_RANK, var_dims, &varid)) ERR;
/* Create and write a variable attribute of the vlen type */
#ifdef RECLAIM
/* In order to use ncaux_reclaim_data, all the interior nodes must have been alloc'd */
missing_val.p = (float*)malloc(sizeof(missing_value));
memcpy((void*)missing_val.p,&missing_value,sizeof(missing_value));
#else
missing_val.p = &missing_value;
#endif
missing_val.len = 1;
if (nc_put_att(ncid, varid, ATT5_NAME, typeid, ATT5_LEN, (void *) &missing_val)) ERR;
if (nc_enddef(ncid)) ERR;
#ifdef RECLAIM
/* reclaim */
if(ncaux_reclaim_data(ncid,typeid,&missing_val,1)) ERR;
#endif
/* fill in pointers to data rows in preparation for writing */
array = (float **) malloc(NROWS * sizeof(float *));
if(array == NULL) ERR;
for (i = 0; i < NROWS; i++) {
int ncolumns = NROWS - i;
array[i] = (float *) malloc(ncolumns * sizeof(float));
if(array[i] == NULL) ERR;
for (j = 0; j < ncolumns; j++) {
array[i][j] = 10.0 * (i + 1) + j;
}
}
array[4][0] = missing_value; /* overwrite last row with missing for equality test */
for (i = 0; i < DIM5_LEN; i++) {
ragged_data[i].p = array[i];
ragged_data[i].len = NROWS - i;
}
/* Store data, writing all values of the ragged matrix in one call */
if(nc_put_var(ncid, varid, ragged_data)) ERR;
/* Write the file. */
if (nc_close(ncid)) ERR;
/* Check it out. */
/* Reopen the file. */
if (nc_open(FILE5_NAME, NC_NOWRITE, &ncid)) ERR;
/* Get info with the generic inquire for user-defined types */
if (nc_inq_user_type(ncid, typeid, name_in, &base_size_in, &base_typeid,
NULL, &class_in)) ERR;
if (strcmp(name_in, TYPE5_NAME) ||
base_size_in != sizeof(nc_vlen_t) ||
base_typeid != NC_FLOAT ||
class_in != NC_VLEN) ERR;
/* Get the same info with the vlen-specific inquire function */
if (nc_inq_vlen(ncid, typeid, name_in, &base_size_in, &base_typeid)) ERR;
if (strcmp(name_in, TYPE5_NAME) ||
base_size_in != sizeof(nc_vlen_t) ||
base_typeid != NC_FLOAT) ERR;
if (nc_inq_varid(ncid, VAR5_NAME, &varid)) ERR;
/* Read in attribute value and check it */
if (nc_get_att(ncid, varid, ATT5_NAME, &val_in)) ERR;
if (val_in.len != ATT5_LEN) ERR;
value_in = *(float *)val_in.p;
if (value_in != missing_value) ERR;
/* Free allocated space for attribute value when finished with it */
if (nc_free_vlen(&val_in)) ERR;
/* Read in each row, check its length and values */
for (i = 0; i < DIM5_LEN; i++) {
size_t index[VAR5_RANK];
float *fvals;
index[0] = i;
if (nc_get_var1(ncid, varid, index, (void *) &val_in)) ERR;
if (val_in.len != NROWS - i) ERR;
fvals = (float *)val_in.p;
for (j = 0; j < val_in.len; j++) {
if (fvals[j] != array[i][j] ) ERR;
}
if (nc_free_vlen(&val_in)) ERR;
}
/* Now read in all the rows at once, then check lengths and values */
{
nc_vlen_t vals_in[DIM5_LEN];
float *fvals;
size_t start[VAR5_RANK], count[VAR5_RANK];
start[0] = 0;
count[0] = NROWS;
if (nc_get_vara(ncid, varid, start, count, vals_in)) ERR;
for (i = 0; i < DIM5_LEN; i++) {
for (j = 0; j < vals_in[i].len; j++) {
fvals = (float *)vals_in[i].p;
if (fvals[j] != array[i][j] ) ERR;
}
if (nc_free_vlen(&vals_in[i])) ERR;
}
}
if (nc_close(ncid)) ERR;
/* Free space used for sample data. */
for (i = 0; i < NROWS; i++)
free(array[i]);
free(array);
SUMMARIZE_ERR;
FINAL_RESULTS;
}