/* This is part of the netCDF package. Copyright 2008 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 default fill values for variables of each type. $Id: tst_fills.c,v 1.12 2009/03/17 01:22:42 ed Exp $ */ #include #include #include #include #define FILE_NAME "tst_fills.nc" int main(int argc, char **argv) { /* create tst_classic_fills.nc */ printf("\n*** Testing fill values.\n"); printf("*** testing empty fill values of a string var..."); { #define STRING_VAR_NAME "The_String" #define NDIMS_STRING 1 #define FILLVALUE_LEN 1 /* There is 1 string, the empty one. */ #define DATA_START 2 /* Real data here. */ int ncid, varid, dimid, varid_in; const char *missing_val[FILLVALUE_LEN] = {""}; const char *missing_val_in[FILLVALUE_LEN]; const char *data_out[1] = {"The evil that men do lives after them; " "the good is oft interred with their bones."}; char **data_in; size_t index = DATA_START; int i; /* Create file with a 1D string var. Set its fill value to the * empty string. */ if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; if (nc_def_dim(ncid, "rec", NC_UNLIMITED, &dimid)) ERR; if (nc_def_var(ncid, STRING_VAR_NAME, NC_STRING, NDIMS_STRING, &dimid, &varid)) ERR; if (nc_put_att_string(ncid, varid, "_FillValue", FILLVALUE_LEN, missing_val)) ERR; /* Check it out. */ if (nc_inq_varid(ncid, STRING_VAR_NAME, &varid_in)) ERR; if (nc_get_att_string(ncid, varid_in, "_FillValue", (char **)missing_val_in)) ERR; if (strcmp(missing_val[0], missing_val_in[0])) ERR; if (nc_free_string(FILLVALUE_LEN, (char **)missing_val_in)) ERR; /* Write one string, leaving some blank records which will then * get the fill value. */ if (nc_put_var1_string(ncid, varid_in, &index, data_out)) ERR; /* Get all the data from the variable. */ if (!(data_in = malloc((DATA_START + 1) * sizeof(char *)))) ERR; if (nc_get_var_string(ncid, varid_in, data_in)) ERR; /* First there should be fill values, then the data value we * wrote. */ for (i = 0; i < DATA_START; i++) if (strcmp(data_in[i], "")) ERR; if (strcmp(data_in[DATA_START], data_out[0])) ERR; /* Close everything up. */ if (nc_close(ncid)) ERR; /* Now re-open file, read data, and check values again. */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; if (nc_inq_varid(ncid, STRING_VAR_NAME, &varid_in)) ERR; if (nc_get_att_string(ncid, varid_in, "_FillValue", (char **)missing_val_in)) ERR; if (strcmp(missing_val[0], missing_val_in[0])) ERR; if (nc_free_string(FILLVALUE_LEN, (char **)missing_val_in)) ERR; if (nc_close(ncid)) ERR; free(data_in); } SUMMARIZE_ERR; printf("*** testing non-empty fill values of a string var..."); { #define STRING_VAR_NAME2 "CASSIUS" #define FILLVALUE_LEN2 1 /* There is 1 string in the fillvalue array. */ #define DATA_START2 9 /* Real data starts here. */ int ncid, varid, dimid, varid_in; const char *missing_val[FILLVALUE_LEN2] = {"I know that virtue to be in you, Brutus"}; const char *missing_val_in[FILLVALUE_LEN2]; const char *data_out[1] = {"The evil that men do lives after them; " "the good is oft interred with their bones."}; char **data_in; size_t index = DATA_START2; int i; /* Create file with a 1D string var. Set its fill value to the * a non-empty string. */ if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; if (nc_def_dim(ncid, "rec", NC_UNLIMITED, &dimid)) ERR; if (nc_def_var(ncid, STRING_VAR_NAME2, NC_STRING, NDIMS_STRING, &dimid, &varid)) ERR; if (nc_put_att_string(ncid, varid, "_FillValue", FILLVALUE_LEN2, missing_val)) ERR; /* Check it out. */ if (nc_inq_varid(ncid, STRING_VAR_NAME2, &varid_in)) ERR; if (nc_get_att_string(ncid, varid_in, "_FillValue", (char **)missing_val_in)) ERR; if (strcmp(missing_val[0], missing_val_in[0])) ERR; if (nc_free_string(FILLVALUE_LEN2, (char **)missing_val_in)) ERR; /* Write one string, leaving some blank records which will then * get the fill value. */ if (nc_put_var1_string(ncid, varid_in, &index, data_out)) ERR; /* Get all the data from the variable. */ if (!(data_in = malloc((DATA_START2 + 1) * sizeof(char *)))) ERR; if (nc_get_var_string(ncid, varid_in, data_in)) ERR; /* First there should be fill values, then the data value we * wrote. */ for (i = 0; i < DATA_START2; i++) if (strcmp(data_in[i], missing_val[0])) ERR; if (strcmp(data_in[DATA_START2], data_out[0])) ERR; /* Close everything up. */ if (nc_close(ncid)) ERR; /* Now re-open file, read data, and check values again. */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; if (nc_inq_varid(ncid, STRING_VAR_NAME2, &varid_in)) ERR; if (nc_get_att_string(ncid, varid_in, "_FillValue", (char **)missing_val_in)) ERR; if (strcmp(missing_val[0], missing_val_in[0])) ERR; if (nc_free_string(FILLVALUE_LEN2, (char **)missing_val_in)) ERR; if (nc_close(ncid)) ERR; free(data_in); } SUMMARIZE_ERR; printf("*** testing fill values of one var..."); { #define V1_NAME "v1" #define MAX_VALS 10 int ncid, varid, rec_id, dims[2]; static int rec[1] = {1}; size_t start[2] = {0, 0}; size_t count[2] = {1, MAX_VALS}; char vals[MAX_VALS]; int i; if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; /* Define dimensions and two vars, a 1D coordinate var for * unlimited dimension, and a 2D var which uses the unlimited * dimension. */ if (nc_def_dim(ncid, "rec", NC_UNLIMITED, &dims[0])) ERR; if (nc_def_dim(ncid, "len", MAX_VALS, &dims[1])) ERR; if (nc_def_var(ncid, "rec", NC_INT, 1, dims, &rec_id)) ERR; if (nc_def_var(ncid, V1_NAME, NC_CHAR, 2, dims, &varid)) ERR; /* Extend record dimension by 1. */ if (nc_put_vara_int(ncid, rec_id, start, count, rec)) ERR; /* Read the other variable; it must have only fill values. */ if (nc_get_vara_text(ncid, 1, start, count, vals)) ERR; for (i = 0; i < MAX_VALS; i++) if(vals[i] != NC_FILL_CHAR) ERR; if (nc_close(ncid)) ERR; /* Now re-open file, read data, and check values again. */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; /* Read the other variable; it must have only fill values. */ if (nc_get_vara_text(ncid, 1, start, count, vals)) ERR; for (i = 0; i < MAX_VALS; i++) if(vals[i] != NC_FILL_CHAR) ERR; if(nc_close(ncid)) ERR; } SUMMARIZE_ERR; printf("*** testing fill values of lots of vars..."); { int ncid; /* netCDF id */ #define NVALS 10 /* values per fixed-size variable or record */ #define NFIXVARS 6 /* number of fixed-size vars, one of each type */ #define NRECVARS 6 /* number of record vars, one of each type */ #define RANK_REC 1 #define RANK_FIXVARS 1 #define RANK_RECVARS 2 /* dimension ids */ int rec_dim; int len_dim; /* dimension lengths */ size_t rec_len = NC_UNLIMITED; size_t len_len = NVALS; /* variable ids */ int rec_id; int fixvar_ids[NFIXVARS]; int recvar_ids[NRECVARS]; int rec_dims[RANK_REC]; int fixvar_dims[RANK_FIXVARS]; int recvar_dims[RANK_RECVARS]; int fixvar, recvar, i; char *fnames[] = {"c", "b", "s", "i", "f", "d"}; char *rnames[] = {"cr", "br", "sr", "ir", "fr", "dr"}; nc_type types[] = {NC_CHAR, NC_BYTE, NC_SHORT, NC_INT, NC_FLOAT, NC_DOUBLE}; /*if (nc_set_default_format(format + 1, NULL)) ERR;*/ if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; /* define dimensions */ if (nc_def_dim(ncid, "rec", rec_len, &rec_dim)) ERR; if (nc_def_dim(ncid, "len", len_len, &len_dim)) ERR; rec_dims[0] = rec_dim; if (nc_def_var(ncid, "rec", NC_INT, RANK_REC, rec_dims, &rec_id)) ERR; /* define fixed and record variables of all 6 primitive types */ fixvar_dims[0] = len_dim; for (fixvar = 0; fixvar < NFIXVARS; fixvar++) if (nc_def_var(ncid, fnames[fixvar], types[fixvar], RANK_FIXVARS, fixvar_dims, &fixvar_ids[fixvar])) ERR; recvar_dims[0] = rec_dim; recvar_dims[1] = len_dim; for (recvar = 0; recvar < NRECVARS; recvar++) if (nc_def_var(ncid, rnames[recvar], types[recvar], RANK_RECVARS, recvar_dims, &recvar_ids[recvar])) ERR; /* leave define mode */ if (nc_enddef(ncid)) ERR; { /* store rec */ static size_t rec_start[RANK_REC]; static size_t rec_count[RANK_REC]; static int rec[] = {1}; rec_len = 1; /* number of records of rec data */ rec_start[0] = 0; rec_count[0] = rec_len; if (nc_put_vara_int(ncid, rec_id, rec_start, rec_count, rec)) ERR; } if (nc_close(ncid)) ERR; /* Now re-open file, read data, and check values */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; /* Check that fixed-size variables are full of fill values */ for (fixvar = 0; fixvar < NFIXVARS; fixvar++) { int varid; nc_type type; if (nc_inq_varid(ncid, fnames[fixvar], &varid)) ERR; if (nc_inq_vartype(ncid, varid, &type)) ERR; switch(type) { case NC_CHAR: { char vals[NVALS]; if (nc_get_var_text(ncid, varid, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_CHAR) ERR; } break; case NC_BYTE: { signed char vals[NVALS]; if (nc_get_var_schar(ncid, varid, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_BYTE) ERR; } break; case NC_SHORT: { short vals[NVALS]; if (nc_get_var_short(ncid, varid, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_SHORT) ERR; } break; case NC_INT: { int vals[NVALS]; if (nc_get_var_int(ncid, varid, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_INT) ERR; } break; case NC_FLOAT: { float vals[NVALS]; if (nc_get_var_float(ncid, varid, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_FLOAT) ERR; } break; case NC_DOUBLE: { double vals[NVALS]; if (nc_get_var_double(ncid, varid, vals)) ERR; for (i = 0; i < NVALS; i++) if (vals[i] != NC_FILL_DOUBLE) ERR; } break; default: ERR; } } /* Read record, check record variables have only fill values */ for (recvar = 0; recvar < NRECVARS; recvar++) { int varid; nc_type type; size_t start[] = {0, 0}; size_t count[] = {1, NVALS}; if (nc_inq_varid(ncid, rnames[recvar], &varid)) ERR; if (nc_inq_vartype(ncid, varid, &type)) ERR; switch(type) { case NC_CHAR: { char vals[NVALS]; if (nc_get_vara_text(ncid, varid, start, count, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_CHAR) ERR; } break; case NC_BYTE: { signed char vals[NVALS]; if (nc_get_vara_schar(ncid, varid, start, count, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_BYTE) ERR; } break; case NC_SHORT: { short vals[NVALS]; if (nc_get_vara_short(ncid, varid, start, count, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_SHORT) ERR; } break; case NC_INT: { int vals[NVALS]; if (nc_get_vara_int(ncid, varid, start, count, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_INT) ERR; } break; case NC_FLOAT: { float vals[NVALS]; if (nc_get_vara_float(ncid, varid, start, count, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_FLOAT) ERR; } break; case NC_DOUBLE: { double vals[NVALS]; if (nc_get_vara_double(ncid, varid, start, count, vals)) ERR; for (i = 0; i < NVALS; i++) if(vals[i] != NC_FILL_DOUBLE) ERR; } break; default: ERR; } } if (nc_close(ncid)) ERR; } SUMMARIZE_ERR; FINAL_RESULTS; return 0; }