mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-04-24 18:30:51 +08:00
Quincey's fixes for NCF-56, "netcdf-4 can't read HDF5 scalar atts".
Also added ability capability for netCDF-4 to write and read NIL values for string type attributes and variables, so these can be read if used in HDF5 files. Include are additions to CMakeLists files to reflect new tests.
This commit is contained in:
parent
483cbf94fe
commit
e4f9350c23
@ -46,6 +46,13 @@ fprintf(stderr, "Sorry! Unexpected result, %s, line: %d\n", \
|
||||
return 2; \
|
||||
} while (0)
|
||||
|
||||
#define ERR_GOTO do { \
|
||||
fflush(stdout); /* Make sure our stdout is synced with stderr. */ \
|
||||
fprintf(stderr, "Sorry! Unexpected result, %s, line: %d\n", \
|
||||
__FILE__, __LINE__); \
|
||||
goto error; \
|
||||
} while (0)
|
||||
|
||||
/* After a set of tests, report the number of errors, and increment
|
||||
* total_err. */
|
||||
#define SUMMARIZE_ERR do { \
|
||||
|
@ -151,9 +151,15 @@ nc4_get_att(int ncid, NC *nc, int varid, const char *name,
|
||||
{
|
||||
for (i = 0; i < att->len; i++)
|
||||
{
|
||||
if (!(((char **)data)[i] = malloc(strlen(att->stdata[i]) + 1)))
|
||||
BAIL(NC_ENOMEM);
|
||||
strcpy(((char **)data)[i], att->stdata[i]);
|
||||
/* Check for NULL pointer for string (valid in HDF5) */
|
||||
if(att->stdata[i])
|
||||
{
|
||||
if (!(((char **)data)[i] = malloc(strlen(att->stdata[i]) + 1)))
|
||||
BAIL(NC_ENOMEM);
|
||||
strcpy(((char **)data)[i], att->stdata[i]);
|
||||
}
|
||||
else
|
||||
((char **)data)[i] = att->stdata[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -308,6 +314,24 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
|
||||
return NC_ENOMEM;
|
||||
strcpy(att->name, norm_name);
|
||||
att->xtype = file_type;
|
||||
|
||||
/* If this att has vlen or string data, release it before we lose the length value. */
|
||||
if (att->stdata)
|
||||
{
|
||||
for (i = 0; i < att->len; i++)
|
||||
if(att->stdata[i])
|
||||
free(att->stdata[i]);
|
||||
free(att->stdata);
|
||||
att->stdata = NULL;
|
||||
}
|
||||
if (att->vldata)
|
||||
{
|
||||
for (i = 0; i < att->len; i++)
|
||||
nc_free_vlen(&att->vldata[i]);
|
||||
free(att->vldata);
|
||||
att->vldata = NULL;
|
||||
}
|
||||
|
||||
att->len = len;
|
||||
if (att->prev)
|
||||
att->attnum = att->prev->attnum + 1;
|
||||
@ -357,11 +381,14 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
|
||||
if (type_info && type_info->class == NC_VLEN)
|
||||
size = sizeof(hvl_t);
|
||||
else if (var->xtype == NC_STRING)
|
||||
size = sizeof(char *);
|
||||
{
|
||||
size = 1;
|
||||
if(NULL != (*(char **)data))
|
||||
size += strlen(*(char **)data);
|
||||
}
|
||||
else
|
||||
size = type_size;
|
||||
|
||||
/* size = strlen(*(char **)data) + 1; */
|
||||
if (!(var->fill_value = malloc(size)))
|
||||
return NC_ENOMEM;
|
||||
|
||||
@ -377,9 +404,10 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
|
||||
}
|
||||
else if (var->xtype == NC_STRING)
|
||||
{
|
||||
if (!(*(char **)var->fill_value = malloc(strlen(*(char **)data) + 1)))
|
||||
return NC_ENOMEM;
|
||||
strcpy(*(char **)(var->fill_value), *(char **)data);
|
||||
if(NULL != (*(char **)data))
|
||||
strcpy((char *)var->fill_value, *(char **)data);
|
||||
else
|
||||
strcpy((char *)var->fill_value, "");
|
||||
}
|
||||
else
|
||||
memcpy(var->fill_value, data, type_size);
|
||||
@ -415,10 +443,14 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
|
||||
BAIL(NC_ENOMEM);
|
||||
for (i = 0; i < att->len; i++)
|
||||
{
|
||||
LOG((5, "copying string %d of size %d", i, strlen(((char **)data)[i]) + 1));
|
||||
if (!(att->stdata[i] = malloc(strlen(((char **)data)[i]) + 1)))
|
||||
BAIL(NC_ENOMEM);
|
||||
strcpy(att->stdata[i], ((char **)data)[i]);
|
||||
if(NULL != ((char **)data)[i]) {
|
||||
LOG((5, "copying string %d of size %d", i, strlen(((char **)data)[i]) + 1));
|
||||
if (!(att->stdata[i] = malloc(strlen(((char **)data)[i]) + 1)))
|
||||
BAIL(NC_ENOMEM);
|
||||
strcpy(att->stdata[i], ((char **)data)[i]);
|
||||
}
|
||||
else
|
||||
att->stdata[i] = ((char **)data)[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -924,13 +924,29 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
|
||||
}
|
||||
else
|
||||
{
|
||||
H5S_class_t space_class;
|
||||
|
||||
/* All netcdf attributes are scalar or 1-D only. */
|
||||
if (att_ndims > 1)
|
||||
BAIL(NC_EATTMETA);
|
||||
|
||||
/* Read the size of this attribute. */
|
||||
if (H5Sget_simple_extent_dims(spaceid, dims, NULL) < 0)
|
||||
/* Check class of HDF5 dataspace */
|
||||
if ((space_class = H5Sget_simple_extent_type(spaceid)) < 0)
|
||||
BAIL(NC_EATTMETA);
|
||||
|
||||
/* Check for NULL HDF5 dataspace class (should be weeded out earlier) */
|
||||
if (H5S_NULL == space_class)
|
||||
BAIL(NC_EATTMETA);
|
||||
|
||||
/* check for SCALAR HDF5 dataspace class */
|
||||
if (H5S_SCALAR == space_class)
|
||||
dims[0] = 1;
|
||||
else /* Must be "simple" dataspace */
|
||||
{
|
||||
/* Read the size of this attribute. */
|
||||
if (H5Sget_simple_extent_dims(spaceid, dims, NULL) < 0)
|
||||
BAIL(NC_EATTMETA);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell the user what the length if this attribute is. */
|
||||
|
@ -215,7 +215,7 @@ nc4_pg_var1(NC_PG_T pg, NC *nc, int ncid, int varid,
|
||||
/* Get the default fill value for an atomic type. Memory for
|
||||
* fill_value must already be allocated, or you are DOOMED!!!*/
|
||||
int
|
||||
nc4_get_default_fill_value(NC_TYPE_INFO_T *type_info, void *fill_value)
|
||||
nc4_get_default_fill_value(const NC_TYPE_INFO_T *type_info, void *fill_value)
|
||||
{
|
||||
switch (type_info->nc_typeid)
|
||||
{
|
||||
@ -270,28 +270,26 @@ get_fill_value(NC_HDF5_FILE_INFO_T *h5, NC_VAR_INFO_T *var, void **fillp)
|
||||
int retval;
|
||||
|
||||
/* Find out how much space we need for this type's fill value. */
|
||||
if ((retval = nc4_get_typelen_mem(h5, var->xtype, 0, &size)))
|
||||
return retval;
|
||||
|
||||
/* Strings have a size of one for the empty sting (to hold the
|
||||
* null), otherwise the length of the users fill_value string, plus
|
||||
* one. */
|
||||
if (var->xtype == NC_STRING)
|
||||
{
|
||||
size = 1;
|
||||
}
|
||||
|
||||
/* Allocate the space. VLENS are different, of course. */
|
||||
if (var->type_info->class == NC_VLEN)
|
||||
size = sizeof(nc_vlen_t);
|
||||
else if (var->xtype == NC_STRING)
|
||||
{
|
||||
if (!((*fillp) = malloc(sizeof(nc_vlen_t))))
|
||||
return NC_ENOMEM;
|
||||
/* Strings have a size of one for the empty string (to hold the null),
|
||||
* otherwise the length of the users fill_value string, plus one. */
|
||||
size = 1;
|
||||
if (var->fill_value)
|
||||
size += strlen((char *)var->fill_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!((*fillp) = malloc(size)))
|
||||
return NC_ENOMEM;
|
||||
if ((retval = nc4_get_typelen_mem(h5, var->xtype, 0, &size)))
|
||||
return retval;
|
||||
}
|
||||
assert(size);
|
||||
|
||||
/* Allocate the space. */
|
||||
if (!((*fillp) = malloc(size)))
|
||||
return NC_ENOMEM;
|
||||
|
||||
/* If the user has set a fill_value for this var, use, otherwise
|
||||
* find the default fill value. */
|
||||
@ -308,9 +306,6 @@ get_fill_value(NC_HDF5_FILE_INFO_T *h5, NC_VAR_INFO_T *var, void **fillp)
|
||||
}
|
||||
else if (var->xtype == NC_STRING)
|
||||
{
|
||||
if (!(*(char **)fillp = malloc((strlen((char *)var->fill_value) + 1) *
|
||||
sizeof(char))))
|
||||
return NC_ENOMEM;
|
||||
strcpy(*(char **)fillp, (char *)var->fill_value);
|
||||
}
|
||||
else
|
||||
@ -1303,7 +1298,6 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid)
|
||||
hsize_t *chunksize = NULL, *dimsize = NULL, *maxdimsize = NULL;
|
||||
int d;
|
||||
NC_DIM_INFO_T *dim = NULL;
|
||||
void *fillp = NULL;
|
||||
int dims_found = 0;
|
||||
int set_chunksizes = 0;
|
||||
char *name_to_use;
|
||||
@ -1331,6 +1325,8 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid)
|
||||
/* Figure out what fill value to set, if any. */
|
||||
if (!var->no_fill)
|
||||
{
|
||||
void *fillp = NULL;
|
||||
|
||||
if ((retval = get_fill_value(grp->nc4_info, var, &fillp)))
|
||||
BAIL(retval);
|
||||
|
||||
@ -1341,7 +1337,6 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid)
|
||||
{
|
||||
if (H5Pset_fill_value(plistid, typeid, &fillp) < 0)
|
||||
BAIL(NC_EHDFERR);
|
||||
free((char *)fillp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1357,12 +1352,11 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid)
|
||||
BAIL(NC_EHDFERR);
|
||||
if (var->type_info->class == NC_VLEN)
|
||||
nc_free_vlen((nc_vlen_t *)fillp);
|
||||
else
|
||||
free(fillp);
|
||||
if (var->type_info->nc_typeid == NC_STRING || var->type_info->nc_typeid == NC_CHAR)
|
||||
if (H5Tclose(fill_typeid) < 0)
|
||||
BAIL(NC_EHDFERR);
|
||||
}
|
||||
free(fillp);
|
||||
}
|
||||
} else {
|
||||
/* Required to truly turn HDF5 fill values off */
|
||||
|
@ -935,12 +935,8 @@ nc4_var_list_del(NC_VAR_INFO_T **list, NC_VAR_INFO_T *var)
|
||||
if (var->hdf_datasetid)
|
||||
{
|
||||
if (var->type_info)
|
||||
{
|
||||
if (var->type_info->class == NC_VLEN)
|
||||
nc_free_vlen((nc_vlen_t *)var->fill_value);
|
||||
else if (var->type_info->nc_typeid == NC_STRING)
|
||||
free(*(char **)var->fill_value);
|
||||
}
|
||||
}
|
||||
free(var->fill_value);
|
||||
var->fill_value = NULL;
|
||||
@ -1240,7 +1236,8 @@ nc4_att_list_del(NC_ATT_INFO_T **list, NC_ATT_INFO_T *att)
|
||||
if (att->stdata)
|
||||
{
|
||||
for (i = 0; i < att->len; i++)
|
||||
free(att->stdata[i]);
|
||||
if(att->stdata[i])
|
||||
free(att->stdata[i]);
|
||||
free(att->stdata);
|
||||
}
|
||||
|
||||
@ -1350,20 +1347,27 @@ rec_print_metadata(NC_GRP_INFO_T *grp, int *tab_count)
|
||||
;
|
||||
for( ; var; var = var->prev)
|
||||
{
|
||||
dims_string = (char*)malloc(sizeof(char)*(var->ndims*4));
|
||||
strcpy(dims_string, "");
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
{
|
||||
sprintf(temp_string, " %d", var->dimids[d]);
|
||||
strcat(dims_string, temp_string);
|
||||
}
|
||||
if(var->ndims > 0)
|
||||
{
|
||||
dims_string = (char*)malloc(sizeof(char)*(var->ndims*4));
|
||||
strcpy(dims_string, "");
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
{
|
||||
sprintf(temp_string, " %d", var->dimids[d]);
|
||||
strcat(dims_string, temp_string);
|
||||
}
|
||||
}
|
||||
LOG((2, "%s VARIABLE - varid: %d name: %s type: %d ndims: %d dimscale: %d dimids:%s",
|
||||
tabs, var->varid, var->name, var->xtype, var->ndims, var->dimscale,
|
||||
dims_string));
|
||||
(dims_string ? dims_string : " -")));
|
||||
for(att = var->att; att; att = att->next)
|
||||
LOG((2, "%s VAR ATTRIBUTE - attnum: %d name: %s type: %d len: %d",
|
||||
tabs, att->attnum, att->name, att->xtype, att->len));
|
||||
free(dims_string); dims_string = NULL;
|
||||
if(dims_string)
|
||||
{
|
||||
free(dims_string);
|
||||
dims_string = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (type = grp->type; type; type = type->next)
|
||||
|
@ -35,7 +35,7 @@ extern int num_plists;
|
||||
#define NC_SZIP_NN_OPTION_MASK 32
|
||||
#define NC_SZIP_MAX_PIXELS_PER_BLOCK 32
|
||||
|
||||
int nc4_get_default_fill_value(NC_TYPE_INFO_T *type_info, void *fill_value);
|
||||
extern int nc4_get_default_fill_value(const NC_TYPE_INFO_T *type_info, void *fill_value);
|
||||
|
||||
|
||||
/* If the HDF5 dataset for this variable is open, then close it and
|
||||
|
@ -9,7 +9,7 @@ tst_enums tst_coords tst_coords2 tst_coords3 tst_vars3 tst_vars4
|
||||
tst_chunks tst_chunks2 tst_utf8 tst_fills tst_fills2 tst_fillbug
|
||||
tst_xplatform tst_xplatform2 tst_h_atts2 tst_endian_fill tst_atts
|
||||
t_type cdm_sea_soundings tst_vl tst_atts1 tst_atts2
|
||||
tst_vars2 tst_files5 tst_files6 tst_sync tst_h_strbug tst_h_refs)
|
||||
tst_vars2 tst_files5 tst_files6 tst_sync tst_h_strbug tst_h_refs tst_h_scalar)
|
||||
|
||||
IF(NOT MSVC)
|
||||
SET(NC4_TESTS ${NC4_TESTS} tst_interops5 tst_camrun)
|
||||
|
@ -20,7 +20,8 @@ tst_enums tst_coords tst_coords2 tst_coords3 tst_vars3 tst_vars4 \
|
||||
tst_chunks tst_chunks2 tst_utf8 tst_fills tst_fills2 tst_fillbug \
|
||||
tst_xplatform tst_xplatform2 tst_h_atts2 tst_endian_fill tst_atts \
|
||||
t_type cdm_sea_soundings tst_camrun tst_vl tst_atts1 tst_atts2 \
|
||||
tst_vars2 tst_files5 tst_files6 tst_sync tst_h_strbug tst_h_refs
|
||||
tst_vars2 tst_files5 tst_files6 tst_sync tst_h_strbug tst_h_refs \
|
||||
tst_h_scalar
|
||||
|
||||
check_PROGRAMS = $(NC4_TESTS)
|
||||
|
||||
|
@ -72,6 +72,7 @@ IF(ENABLE_TESTS)
|
||||
add_bin_test(ncdump tst_comp)
|
||||
add_bin_test(ncdump tst_comp2)
|
||||
add_bin_test(ncdump tst_nans)
|
||||
add_bin_test(ncdump tst_h_scalar)
|
||||
#add_bin_test(ncdump tst_special_atts)
|
||||
# Add this test by hand, as it is also called from a script.
|
||||
# Editing the script would break autotools compatibility.
|
||||
@ -109,6 +110,7 @@ IF(ENABLE_TESTS)
|
||||
ENDIF()
|
||||
add_sh_test(ncdump tst_grp_spec)
|
||||
add_sh_test(ncdump tst_mud)
|
||||
add_sh_test(ncdump tst_h_scalar)
|
||||
ENDIF()
|
||||
|
||||
#add_sh_test(tst_ncgen4_classic)
|
||||
|
@ -42,13 +42,13 @@ if USE_NETCDF4
|
||||
check_PROGRAMS += tst_create_files tst_h_rdc0 tst_group_data \
|
||||
tst_enum_data tst_opaque_data tst_string_data tst_vlen_data tst_comp \
|
||||
tst_comp2 tst_nans tst_special_atts tst_unicode tst_fillbug tst_compress \
|
||||
tst_chunking
|
||||
tst_chunking tst_h_scalar
|
||||
|
||||
TESTS += tst_create_files tst_group_data tst_enum_data tst_opaque_data \
|
||||
tst_string_data tst_vlen_data tst_comp tst_comp2 tst_nans \
|
||||
tst_special_atts tst_netcdf4.sh tst_h_rdc0 tst_unicode tst_fillbug \
|
||||
tst_fillbug.sh tst_netcdf4_4.sh tst_compress tst_nccopy4.sh \
|
||||
tst_grp_spec.sh tst_mud.sh
|
||||
tst_grp_spec.sh tst_mud.sh tst_h_scalar tst_h_scalar.sh
|
||||
|
||||
if EXTRA_TESTS
|
||||
TESTS += run_back_comp_tests.sh
|
||||
|
130
ncdump/dumplib.c
130
ncdump/dumplib.c
@ -632,6 +632,12 @@ ncuint64_val_equals(const nctype_t *this,
|
||||
bool_t
|
||||
ncstring_val_equals(const nctype_t *this,
|
||||
const void *v1p, const void *v2p) {
|
||||
if (NULL == *((char **)v1p) && NULL == *((char **)v2p))
|
||||
return(1);
|
||||
else if (NULL != *((char **)v1p) && NULL == *((char **)v2p))
|
||||
return(0);
|
||||
else if (NULL == *((char **)v1p) && NULL != *((char **)v2p))
|
||||
return(0);
|
||||
return (strcmp(*((char **)v1p), *((char **)v2p)) == 0);
|
||||
}
|
||||
|
||||
@ -867,69 +873,75 @@ ncuint64_typ_tostring(const nctype_t *typ, safebuf_t *sfbf, const void *valp) {
|
||||
}
|
||||
|
||||
int ncstring_typ_tostring(const nctype_t *typ, safebuf_t *sfbf, const void *valp) {
|
||||
size_t slen;
|
||||
char *sout;
|
||||
const char *cp;
|
||||
char *sp;
|
||||
unsigned char uc;
|
||||
|
||||
cp = ((char **)valp)[0];
|
||||
slen = 3 + 5 * strlen(cp); /* need "'s around string, and extra space to escape control characters */
|
||||
sout = emalloc(slen);
|
||||
sp = sout;
|
||||
*sp++ = '"' ;
|
||||
while(*cp) {
|
||||
switch (uc = *cp++ & 0377) {
|
||||
case '\b':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'b' ;
|
||||
break;
|
||||
case '\f':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'f';
|
||||
break;
|
||||
case '\n':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 't';
|
||||
break;
|
||||
case '\v':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'n';
|
||||
break;
|
||||
case '\\':
|
||||
*sp++ = '\\';
|
||||
*sp++ = '\\';
|
||||
break;
|
||||
case '\'':
|
||||
*sp++ = '\\';
|
||||
*sp++ = '\'';
|
||||
break;
|
||||
case '\"':
|
||||
*sp++ = '\\';
|
||||
*sp++ = '\"';
|
||||
break;
|
||||
default:
|
||||
if (iscntrl(uc)) {
|
||||
snprintf(sp,3,"\\%03o",uc);
|
||||
sp += 4;
|
||||
}
|
||||
else
|
||||
*sp++ = uc;
|
||||
break;
|
||||
}
|
||||
if(cp) {
|
||||
size_t slen;
|
||||
char *sout;
|
||||
char *sp;
|
||||
unsigned char uc;
|
||||
|
||||
slen = 3 + 5 * strlen(cp); /* need "'s around string, and extra space to escape control characters */
|
||||
sout = emalloc(slen);
|
||||
sp = sout;
|
||||
*sp++ = '"' ;
|
||||
while(*cp) {
|
||||
switch (uc = *cp++ & 0377) {
|
||||
case '\b':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'b' ;
|
||||
break;
|
||||
case '\f':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'f';
|
||||
break;
|
||||
case '\n':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 't';
|
||||
break;
|
||||
case '\v':
|
||||
*sp++ = '\\';
|
||||
*sp++ = 'n';
|
||||
break;
|
||||
case '\\':
|
||||
*sp++ = '\\';
|
||||
*sp++ = '\\';
|
||||
break;
|
||||
case '\'':
|
||||
*sp++ = '\\';
|
||||
*sp++ = '\'';
|
||||
break;
|
||||
case '\"':
|
||||
*sp++ = '\\';
|
||||
*sp++ = '\"';
|
||||
break;
|
||||
default:
|
||||
if (iscntrl(uc)) {
|
||||
snprintf(sp,3,"\\%03o",uc);
|
||||
sp += 4;
|
||||
}
|
||||
else
|
||||
*sp++ = uc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*sp++ = '"' ;
|
||||
*sp = '\0' ;
|
||||
sbuf_cpy(sfbf, sout);
|
||||
free(sout);
|
||||
}
|
||||
else {
|
||||
sbuf_cpy(sfbf, "NIL");
|
||||
}
|
||||
*sp++ = '"' ;
|
||||
*sp = '\0' ;
|
||||
sbuf_cpy(sfbf, sout);
|
||||
free(sout);
|
||||
return sbuf_len(sfbf);
|
||||
}
|
||||
|
||||
|
@ -489,7 +489,10 @@ pr_att_valgs(
|
||||
break;
|
||||
case NC_STRING:
|
||||
stringp = ((char **) vals)[iel];
|
||||
pr_att_string(kind, strlen(stringp), stringp);
|
||||
if(stringp)
|
||||
pr_att_string(kind, strlen(stringp), stringp);
|
||||
else
|
||||
printf("NIL");
|
||||
printf("%s", delim);
|
||||
break;
|
||||
#endif /* USE_NETCDF4 */
|
||||
|
48
ncdump/ref_tst_h_scalar.cdl
Normal file
48
ncdump/ref_tst_h_scalar.cdl
Normal file
@ -0,0 +1,48 @@
|
||||
netcdf tst_h_scalar {
|
||||
variables:
|
||||
string vstrvar1 ;
|
||||
string vstrvar1:vstratt1 = NIL ;
|
||||
string vstrvar1:vstratt2 = NIL ;
|
||||
string vstrvar1:vstratt3 = "" ;
|
||||
string vstrvar1:vstratt4 = "foo" ;
|
||||
vstrvar1:fstratt = "" ;
|
||||
vstrvar1:intatt = 0 ;
|
||||
string fstrvar ;
|
||||
string fstrvar:vstratt1 = NIL ;
|
||||
string fstrvar:vstratt2 = NIL ;
|
||||
string fstrvar:vstratt3 = "" ;
|
||||
string fstrvar:vstratt4 = "foo" ;
|
||||
fstrvar:fstratt = "" ;
|
||||
fstrvar:intatt = 0 ;
|
||||
int intvar ;
|
||||
string intvar:vstratt1 = NIL ;
|
||||
string intvar:vstratt2 = NIL ;
|
||||
string intvar:vstratt3 = "" ;
|
||||
string intvar:vstratt4 = "foo" ;
|
||||
intvar:fstratt = "" ;
|
||||
intvar:intatt = 0 ;
|
||||
string vstrvar2 ;
|
||||
string vstrvar3 ;
|
||||
string vstrvar4 ;
|
||||
|
||||
// global attributes:
|
||||
string :vstratt1 = NIL ;
|
||||
string :vstratt2 = NIL ;
|
||||
string :vstratt3 = "" ;
|
||||
string :vstratt4 = "foo" ;
|
||||
:fstratt = "" ;
|
||||
:intatt = 0 ;
|
||||
data:
|
||||
|
||||
vstrvar1 = NIL ;
|
||||
|
||||
fstrvar = _ ;
|
||||
|
||||
intvar = 0 ;
|
||||
|
||||
vstrvar2 = NIL ;
|
||||
|
||||
vstrvar3 = _ ;
|
||||
|
||||
vstrvar4 = "foo" ;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user