mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-12-27 08:49:16 +08:00
364 lines
13 KiB
C
364 lines
13 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.
|
|
|
|
Test netcdf-4 enum types.
|
|
|
|
Ed Hartnett
|
|
*/
|
|
|
|
#include <nc_tests.h>
|
|
#include "err_macros.h"
|
|
#include "netcdf.h"
|
|
|
|
#define FILE_NAME "tst_enums.nc"
|
|
#define DIM_LEN 4
|
|
#define NUM_MEMBERS 4
|
|
#define DIM_NAME "dim"
|
|
#define BASE_SIZE 20
|
|
#define VAR_NAME "Advice"
|
|
#define TYPE_NAME "Mysterous_Word"
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int ncid;
|
|
nc_type typeid;
|
|
int i;
|
|
char name_in[NC_MAX_NAME+1];
|
|
int ntypes, typeids[1] = {0};
|
|
nc_type base_nc_type, base_nc_type_in;
|
|
size_t nfields_in, num_members, base_size_in;
|
|
int class_in;
|
|
|
|
printf("\n*** Testing netcdf-4 enum type.\n");
|
|
printf("*** testing creation of enum type...");
|
|
{
|
|
int value_in;
|
|
/* Can't use the same name twice! */
|
|
char member_name[NUM_MEMBERS][NC_MAX_NAME + 1] = {"Mene1", "Mene2",
|
|
"Tekel", "Upharsin"};
|
|
int member_value[NUM_MEMBERS] = {0, 99, 81232, 12};
|
|
|
|
/* Create a file. */
|
|
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
|
|
|
|
/* Create an enum type. */
|
|
if (nc_def_enum(ncid, NC_INT, TYPE_NAME, &typeid)) ERR;
|
|
for (i = 0; i < NUM_MEMBERS; i++)
|
|
if (nc_insert_enum(ncid, typeid, member_name[i],
|
|
&member_value[i])) ERR;
|
|
|
|
/* Check it out. */
|
|
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, TYPE_NAME) || base_size_in != sizeof(int) ||
|
|
base_nc_type_in != NC_INT || nfields_in != NUM_MEMBERS || class_in != NC_ENUM) ERR;
|
|
if (nc_inq_enum(ncid, typeid, name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
|
|
if (strcmp(name_in, TYPE_NAME) || base_nc_type != NC_INT ||
|
|
num_members != 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, member_name[i]) || value_in != member_value[i]) ERR;
|
|
if (nc_inq_enum_ident(ncid, typeid, member_value[i], name_in)) ERR;
|
|
if (strcmp(name_in, member_name[i])) ERR;
|
|
}
|
|
|
|
/* Write the file. */
|
|
if (nc_close(ncid)) ERR;
|
|
|
|
/* Reopen the file. */
|
|
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
|
|
|
|
/* Get type info. */
|
|
if (nc_inq_typeids(ncid, &ntypes, typeids)) ERR;
|
|
if (ntypes != 1 || !typeids[0]) ERR;
|
|
|
|
/* Check it out. */
|
|
if (nc_inq_user_type(ncid, typeids[0], name_in, &base_size_in, &base_nc_type_in,
|
|
&nfields_in, &class_in)) ERR;
|
|
if (strcmp(name_in, TYPE_NAME) || base_size_in != sizeof(int) ||
|
|
base_nc_type_in != NC_INT || nfields_in != NUM_MEMBERS || class_in != NC_ENUM) ERR;
|
|
if (nc_inq_type(ncid, typeids[0], name_in, &base_size_in)) ERR;
|
|
if (strcmp(name_in, TYPE_NAME) || base_size_in != sizeof(int)) ERR;
|
|
if (nc_inq_enum(ncid, typeids[0], name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
|
|
if (strcmp(name_in, TYPE_NAME) || base_nc_type != NC_INT || num_members != 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, member_name[i]) || value_in != member_value[i]) ERR;
|
|
if (nc_inq_enum_ident(ncid, typeid, member_value[i], name_in)) ERR;
|
|
if (strcmp(name_in, member_name[i])) ERR;
|
|
}
|
|
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
|
|
#define NUM_BRADYS 9
|
|
#define BRADYS "Bradys"
|
|
#define BRADY_DIM_LEN 3
|
|
#define ATT_NAME "brady_attribute"
|
|
|
|
printf("*** testing enum attribute...");
|
|
{
|
|
char brady_name[NUM_BRADYS][NC_MAX_NAME + 1] = {"Mike", "Carol", "Greg", "Marsha",
|
|
"Peter", "Jan", "Bobby", "Whats-her-face",
|
|
"Alice"};
|
|
unsigned char brady_value[NUM_BRADYS] = {8, 7, 6 , 5, 4, 3, 2, 1, 0};
|
|
unsigned char data[BRADY_DIM_LEN] = {0, 4, 8};
|
|
unsigned char value_in;
|
|
|
|
/* Create a file. */
|
|
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
|
|
|
|
/* Create an enum type based on unsigned bytes. */
|
|
if (nc_def_enum(ncid, NC_UBYTE, BRADYS, &typeid)) ERR;
|
|
for (i = 0; i < NUM_BRADYS; i++)
|
|
if (nc_insert_enum(ncid, typeid, brady_name[i],
|
|
&brady_value[i])) ERR;
|
|
|
|
/* Check it out. */
|
|
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, BRADYS) || base_size_in != 1 ||
|
|
base_nc_type_in != NC_UBYTE || nfields_in != NUM_BRADYS || class_in != NC_ENUM) ERR;
|
|
if (nc_inq_enum(ncid, typeid, name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
|
|
if (strcmp(name_in, BRADYS) || base_nc_type != NC_UBYTE || base_size_in != 1 ||
|
|
num_members != NUM_BRADYS) ERR;
|
|
for (i = 0; i < NUM_BRADYS; i++)
|
|
{
|
|
if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR;
|
|
if (strcmp(name_in, brady_name[i]) || value_in != brady_value[i]) ERR;
|
|
if (nc_inq_enum_ident(ncid, typeid, brady_value[i], name_in)) ERR;
|
|
if (strcmp(name_in, brady_name[i])) ERR;
|
|
}
|
|
|
|
/* Write an att of this enum type. */
|
|
if (nc_put_att(ncid, NC_GLOBAL, ATT_NAME, typeid, BRADY_DIM_LEN, data)) ERR;
|
|
|
|
/* Close the file. */
|
|
if (nc_close(ncid)) ERR;
|
|
|
|
/* Reopen. */
|
|
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
|
|
|
|
/* Check it out. */
|
|
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, BRADYS) || base_size_in != 1 ||
|
|
base_nc_type_in != NC_UBYTE || nfields_in != NUM_BRADYS || class_in != NC_ENUM) ERR;
|
|
if (nc_inq_enum(ncid, typeid, name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
|
|
if (strcmp(name_in, BRADYS) || base_nc_type != NC_UBYTE || base_size_in != 1 ||
|
|
num_members != NUM_BRADYS) ERR;
|
|
for (i = 0; i < NUM_BRADYS; i++)
|
|
{
|
|
if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR;
|
|
if (strcmp(name_in, brady_name[i]) || value_in != brady_value[i]) ERR;
|
|
if (nc_inq_enum_ident(ncid, typeid, brady_value[i], name_in)) ERR;
|
|
if (strcmp(name_in, brady_name[i])) ERR;
|
|
}
|
|
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
|
|
#define TYPE2_NAME "cloud_type"
|
|
#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
|
|
|
|
printf("*** testing enum fill value ...");
|
|
{
|
|
int dimid, varid;
|
|
size_t num_members_in;
|
|
int class_in;
|
|
unsigned char value_in;
|
|
unsigned char att_value_in;
|
|
|
|
enum clouds { /* a C enumeration */
|
|
CLEAR=0,
|
|
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[] = {
|
|
{"Clear", CLEAR},
|
|
{"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 att_val;
|
|
unsigned char cloud_data[DIM2_LEN] = {
|
|
CLEAR, STRATUS, CLEAR, CUMULONIMBUS, MISSING};
|
|
unsigned char cloud_data_in[DIM2_LEN];
|
|
|
|
if (nc_create(FILE_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;
|
|
/* Create and write a variable attribute of the enum type */
|
|
att_val = MISSING;
|
|
if (nc_put_att(ncid, varid, ATT2_NAME, typeid, ATT2_LEN, &att_val)) ERR;
|
|
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(FILE_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;
|
|
|
|
if (nc_get_att(ncid, varid, ATT2_NAME, &att_value_in)) ERR;
|
|
if (att_value_in != MISSING) ERR;
|
|
|
|
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;
|
|
printf("*** testing enum interuptus...");
|
|
{
|
|
unsigned char ubyte_value = 42;
|
|
#define GEEKY_NAME "Galadriel"
|
|
|
|
/* Create a file. */
|
|
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
|
|
|
|
/* Create an enum type based on unsigned bytes. */
|
|
if (nc_def_enum(ncid, NC_UBYTE, GEEKY_NAME, &typeid)) ERR;
|
|
|
|
/* Check it out. */
|
|
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, GEEKY_NAME) || base_size_in != 1 ||
|
|
base_nc_type_in != NC_UBYTE || nfields_in != 0 || class_in != NC_ENUM) ERR;
|
|
if (nc_inq_enum(ncid, typeid, name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
|
|
if (strcmp(name_in, GEEKY_NAME) || base_nc_type != NC_UBYTE || base_size_in != 1 ||
|
|
num_members != 0) ERR;
|
|
|
|
/* Close the file. */
|
|
if (nc_close(ncid) != NC_EINVAL) ERR;
|
|
|
|
if (nc_redef(ncid)) ERR;
|
|
if (nc_insert_enum(ncid, typeid, "name", &ubyte_value)) ERR;
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
SUMMARIZE_ERR;
|
|
printf("*** testing enum ncdump...");
|
|
#define ENUM_NAME "cargo"
|
|
#define ENUM_VAR_NAME "in_the_hold_of_the_Irish_Rover"
|
|
#define NUM_ENUM_FIELDS 8
|
|
#define DIMSIZE 4
|
|
#define NDIMS1 1
|
|
{
|
|
int ncid, dimid, v1id, typeid;
|
|
int f;
|
|
size_t start[NDIMS1] = {0}, count[NDIMS1] = {1};
|
|
char field_name[NUM_ENUM_FIELDS][NC_MAX_NAME + 1] = {"bags of the best Sligo rags", "barrels of bones",
|
|
"bails of old nanny goats' tails", "barrels of stones",
|
|
"dogs", "hogs", "barrels of porter",
|
|
"sides of old blind horses hides"};
|
|
unsigned long long field_value[NUM_ENUM_FIELDS] = {1000000, 2000000, 3000000, 4000000,
|
|
5000000, 6000000, 7000000, 8000000};
|
|
unsigned long long data = 1000000, data_in;
|
|
|
|
/* Create a netcdf-4 file. */
|
|
/*nc_set_log_level(3);*/
|
|
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
|
|
|
|
/* Create a dimension. */
|
|
if (nc_def_dim(ncid, DIM_NAME, DIMSIZE, &dimid)) ERR;
|
|
|
|
/* Create an enum type. */
|
|
if (nc_def_enum(ncid, NC_UINT64, ENUM_NAME, &typeid)) ERR;
|
|
for (f = 0; f < NUM_ENUM_FIELDS; f++)
|
|
if (nc_insert_enum(ncid, typeid, field_name[f], &field_value[f])) ERR;
|
|
|
|
/* Create one var. */
|
|
if (nc_def_var(ncid, ENUM_VAR_NAME, typeid, NDIMS1, &dimid, &v1id)) ERR;
|
|
|
|
/* Write metadata to file. */
|
|
if (nc_enddef(ncid)) ERR;
|
|
|
|
/* Write phoney data. */
|
|
if (nc_put_vara(ncid, v1id, start, count, &data)) ERR;
|
|
|
|
if (nc_sync(ncid)) ERR;
|
|
|
|
/* Read phoney data. */
|
|
if (nc_get_vara(ncid, v1id, start, count, &data_in)) ERR;
|
|
if (data_in != data) ERR;
|
|
|
|
/* Close the netcdf file. */
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
SUMMARIZE_ERR;
|
|
FINAL_RESULTS;
|
|
}
|