Skip to content

Commit

Permalink
Merge pull request #2462 from DennisHeimbigner/enumdfalt.dmh
Browse files Browse the repository at this point in the history
Provide a default enum const when fill value does not match any enum constant
  • Loading branch information
WardF committed Jul 27, 2022
2 parents 62ae05d + ba37c0a commit 5ebc855
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 10 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This file contains a high-level description of this package's evolution. Release

## 4.9.1 - T.B.D.

* [Bug Fix] Provide a default enum const when fill value does not match any enum constant for the value zero. See [Github #2462](https://github.com/Unidata/netcdf-c/pull/2462).
* [Bug Fi] Fix the json submodule symbol conflicts between libnetcdf and the plugin specific netcdf_json.h. See [Github #2448](https://github.com/Unidata/netcdf-c/pull/2448).
* [Bug Fix] Fix quantize with CLASSIC_MODEL files. See [Github #2405](https://github.com/Unidata/netcdf-c/pull/2445).
* [Enhancement] Add `--disable-quantize` option to `configure`.
Expand Down
3 changes: 3 additions & 0 deletions include/netcdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,9 @@ nc_inq_enum_member(int ncid, nc_type xtype, int idx, char *name,


/* Get enum name from enum value. Name size will be <= NC_MAX_NAME. */
/* If value is zero and there is no matching ident, then return _UNDEFINED */
#define NC_UNDEFINED_ENUM_IDENT "_UNDEFINED"

EXTERNL int
nc_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier);

Expand Down
17 changes: 11 additions & 6 deletions libsrc4/nc4type.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,9 @@ NC4_inq_compound_fieldindex(int ncid, nc_type typeid1, const char *name, int *fi
}

/**
* @internal Get enum name from enum value. Name size will be <=
* NC_MAX_NAME.
* @internal Get enum name from enum value. Name size will be <= NC_MAX_NAME.
* If the value is not a legitimate enum identifier and the value is zero
* (the default HDF5 enum fill value), then return the identifier "_UNDEFINED".
*
* @param ncid File and group ID.
* @param xtype Type ID.
Expand All @@ -408,7 +409,7 @@ NC4_inq_compound_fieldindex(int ncid, nc_type typeid1, const char *name, int *fi
* @return ::NC_NOERR No error.
* @return ::NC_EBADID Bad ncid.
* @return ::NC_EBADTYPE Type not found.
* @return ::NC_EINVAL Invalid type data.
* @return ::NC_EINVAL Invalid type data or no matching enum value is found
* @author Ed Hartnett
*/
int
Expand Down Expand Up @@ -479,9 +480,13 @@ NC4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier)
}

/* If we didn't find it, life sucks for us. :-( */
if (!found)
return NC_EINVAL;

if(!found) {
if(value == 0) /* Special case for HDF5 default Fill Value*/
strcpy(identifier, NC_UNDEFINED_ENUM_IDENT);
else
return NC_EINVAL;
}

return NC_NOERR;
}

Expand Down
3 changes: 2 additions & 1 deletion ncdump/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,18 @@ endif()
IF(USE_HDF5)
build_bin_test_no_prefix(tst_h_rdc0)
build_bin_test_no_prefix(tst_unicode)
build_bin_test_no_prefix(tst_vlen_data)
add_bin_test_no_prefix(tst_create_files)
add_bin_test_no_prefix(tst_opaque_data)
add_bin_test_no_prefix(tst_string_data)
add_bin_test_no_prefix(tst_vlen_data)
add_bin_test_no_prefix(tst_comp2)
add_bin_test_no_prefix(tst_nans)
add_bin_test_no_prefix(tst_h_scalar)
add_bin_test_no_prefix(tst_compress)
add_bin_test_no_prefix(tst_chunking)
add_bin_test_no_prefix(tst_group_data)
add_bin_test_no_prefix(tst_enum_data)
add_bin_test_no_prefix(tst_enum_undef)
add_bin_test_no_prefix(tst_comp)
# Add this test by hand, as it is also called from a script.
# Editing the script would break autotools compatibility.
Expand Down
7 changes: 4 additions & 3 deletions ncdump/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ if USE_HDF5
check_PROGRAMS += tst_fileinfo 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_h_scalar
tst_unicode tst_fillbug tst_compress tst_chunking tst_h_scalar \
tst_enum_undef

check_PROGRAMS += tst_vlen_demo

Expand Down Expand Up @@ -204,7 +205,7 @@ test_keywords.sh ref_keyword1.cdl ref_keyword2.cdl ref_keyword3.cdl ref_keyword4
ref_tst_nofilters.cdl test_scope.sh \
test_rcmerge.sh ref_rcmerge1.txt ref_rcmerge2.txt ref_rcmerge3.txt \
scope_ancestor_only.cdl scope_ancestor_subgroup.cdl scope_group_only.cdl scope_preorder.cdl \
ref_rcapi.txt
ref_rcapi.txt ref_tst_enum_undef.cdl

# The L512.bin file is file containing exactly 512 bytes each of value 0.
# It is used for creating hdf5 files with varying offsets for testing.
Expand Down Expand Up @@ -246,7 +247,7 @@ tst_roman_szip_unlim.cdl tst_perdimpspecs.nc tmppds.* \
keyword1.nc keyword2.nc keyword3.nc keyword4.nc \
tmp_keyword1.cdl tmp_keyword2.cdl tmp_keyword3.cdl tmp_keyword4.cdl \
type_*.nc copy_type_*.cdl \
scope_*.nc copy_scope_*.cdl keyword5.nc
scope_*.nc copy_scope_*.cdl keyword5.nc tst_enum_undef.cdl

# Remove directories
clean-local:
Expand Down
13 changes: 13 additions & 0 deletions ncdump/ref_tst_enum_undef.cdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
netcdf tst_enum_undef {
types:
ubyte enum cloud_class_t {Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3,
Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7,
Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 255} ;
dimensions:
station = 5 ;
variables:
cloud_class_t primary_cloud(station) ;
data:

primary_cloud = _UNDEFINED, Stratus, _UNDEFINED, Cumulonimbus, Missing ;
}
148 changes: 148 additions & 0 deletions ncdump/tst_enum_undef.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/* 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 an enum type and enum data for ncdump to read.
$Id: tst_enum_data.c,v 1.8 2008/10/20 01:48:08 ed Exp $
*/

#include <nc_tests.h>
#include "err_macros.h"
#include <netcdf.h>

#undef WITHFILL

#define FILE2_NAME "tst_enum_undef.nc"
#define TYPE2_NAME "cloud_class_t"
#define DIM2_NAME "station"
#define DIM2_LEN 5
#define VAR2_NAME "primary_cloud"
#define VAR2_RANK 1
#define ATT2_NAME "_FillValue"
#define ATT2_LEN 1

int
main(int argc, char **argv)
{
int ncid;
int dimid, varid;
nc_type typeid;
int num_members;
char name_in[NC_MAX_NAME+1];
nc_type base_nc_type_in;
size_t nfields_in, base_size_in, num_members_in;
int class_in;
unsigned char value_in;
#ifdef WITHFILL
char zero = 0;
#endif

int i;

enum clouds { /* a C enumeration */
/* No 0 value */
CUMULONIMBUS=1,
STRATUS=2,
STRATOCUMULUS=3,
CUMULUS=4,
ALTOSTRATUS=5,
NIMBOSTRATUS=6,
ALTOCUMULUS=7,
CIRROSTRATUS=8,
CIRROCUMULUS=9,
CIRRUS=10,
MISSING=255};

struct {
char *name;
unsigned char value;
} cloud_types[] = {
{"Cumulonimbus", CUMULONIMBUS},
{"Stratus", STRATUS},
{"Stratocumulus", STRATOCUMULUS},
{"Cumulus", CUMULUS},
{"Altostratus", ALTOSTRATUS},
{"Nimbostratus", NIMBOSTRATUS},
{"Altocumulus", ALTOCUMULUS},
{"Cirrostratus", CIRROSTRATUS},
{"Cirrocumulus", CIRROCUMULUS},
{"Cirrus", CIRRUS},
{"Missing", MISSING}
};
int var_dims[VAR2_RANK];
unsigned char cloud_data[DIM2_LEN] = {
0, STRATUS, 0, CUMULONIMBUS, MISSING};
unsigned char cloud_data_in[DIM2_LEN];

printf("\n*** Testing enum undefined identifier.\n");
printf("*** creating enum test file %s...", FILE2_NAME);
/*nc_set_log_level(3);*/
if (nc_create(FILE2_NAME, NC_CLOBBER | NC_NETCDF4, &ncid)) ERR;

/* Create an enum type. */
if (nc_def_enum(ncid, NC_UBYTE, TYPE2_NAME, &typeid)) ERR;
num_members = (sizeof cloud_types) / (sizeof cloud_types[0]);
for (i = 0; i < num_members; i++) {
if (nc_insert_enum(ncid, typeid, cloud_types[i].name,
&cloud_types[i].value))
ERR;
}
/* Declare a station dimension */
if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimid)) ERR;
/* Declare a variable of the enum type */
var_dims[0] = dimid;
if (nc_def_var(ncid, VAR2_NAME, typeid, VAR2_RANK, var_dims, &varid)) ERR;
#ifdef WITHFILL
if (nc_def_var_fill(ncid, varid, NC_FILL, &zero)) ERR;
#endif
if (nc_enddef(ncid)) ERR;
/* Store some data of the enum type */
if(nc_put_var(ncid, varid, cloud_data)) ERR;
/* Write the file. */
if (nc_close(ncid)) ERR;

/* Check it out. */

/* Reopen the file. */
if (nc_open(FILE2_NAME, NC_NOWRITE, &ncid)) ERR;

if (nc_inq_user_type(ncid, typeid, name_in, &base_size_in, &base_nc_type_in,
&nfields_in, &class_in)) ERR;
if (strcmp(name_in, TYPE2_NAME) ||
base_size_in != sizeof(unsigned char) ||
base_nc_type_in != NC_UBYTE ||
nfields_in != num_members ||
class_in != NC_ENUM) ERR;
if (nc_inq_enum(ncid, typeid, name_in,
&base_nc_type_in, &base_size_in, &num_members_in)) ERR;
if (strcmp(name_in, TYPE2_NAME) ||
base_nc_type_in != NC_UBYTE ||
num_members_in != num_members) ERR;
for (i = 0; i < num_members; i++)
{
if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR;
if (strcmp(name_in, cloud_types[i].name) ||
value_in != cloud_types[i].value) ERR;
if (nc_inq_enum_ident(ncid, typeid, cloud_types[i].value,
name_in)) ERR;
if (strcmp(name_in, cloud_types[i].name)) ERR;
}
if (nc_inq_varid(ncid, VAR2_NAME, &varid)) ERR;

#ifdef WITHFILL
if (nc_get_att(ncid, varid, ATT2_NAME, &value_in)) ERR;
if (value_in != 0) ERR;
#endif

if(nc_get_var(ncid, varid, cloud_data_in)) ERR;
for (i = 0; i < DIM2_LEN; i++) {
if (cloud_data_in[i] != cloud_data[i]) ERR;
}

if (nc_close(ncid)) ERR;


SUMMARIZE_ERR;
FINAL_RESULTS;
}
2 changes: 2 additions & 0 deletions ncdump/tst_nccopy4.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ set -e

# For a netCDF-4 build, test nccopy on netCDF files in this directory

#if 0
if test -f tst_group_data${ext} ; then ${execdir}/tst_group_data ; fi
if test -f tst_enum_data${ext} ; then ${execdir}/tst_enum_data ; fi
if test -f tst_comp${ext} ; then ${execdir}/tst_comp ; fi
if test -f tst_comp2${ext} ; then ${execdir}/tst_comp2 ; fi
#endif

echo ""

Expand Down
5 changes: 5 additions & 0 deletions ncdump/tst_netcdf4.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ ${execdir}/tst_enum_data ; ERR
${NCDUMP} tst_enum_data.nc | sed 's/e+0/e+/g' > tst_enum_data.cdl ; ERR
diff -b tst_enum_data.cdl $srcdir/ref_tst_enum_data.cdl ; ERR

echo "*** Running tst_enum_undef.c to create test files."
${execdir}/tst_enum_undef ; ERR
${NCDUMP} tst_enum_undef.nc | sed 's/e+0/e+/g' > tst_enum_undef.cdl ; ERR
diff -b tst_enum_undef.cdl $srcdir/ref_tst_enum_undef.cdl ; ERR

echo "*** Running tst_opaque_data.c to create test files."
${execdir}/tst_opaque_data ; ERR
${NCDUMP} tst_opaque_data.nc | sed 's/e+0/e+/g' > tst_opaque_data.cdl ; ERR
Expand Down
1 change: 1 addition & 0 deletions nczarr_test/run_newformat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
if test "x$srcdir" = x ; then srcdir=`pwd`; fi
. ../test_common.sh

set -x
. "$srcdir/test_nczarr.sh"

set -e
Expand Down

0 comments on commit 5ebc855

Please sign in to comment.