/* Copyright 2018, UCAR/Unidata See COPYRIGHT file for copying and redistribution conditions. */ /*! \file Example program for write then read of a variable using bzip2 compression. \ingroup tutorial This is an example which creates a file with a variable that is compressed using bzip2. Then it reads that file and verifies that it returned the correct uncompressed data. The meta-data (.cdl) for the created file is as follows: \code netcdf bzip2 { dimensions: dim0 = 4 ; dim1 = 4 ; dim2 = 4 ; dim3 = 4 ; variables: float var(dim0, dim1, dim2, dim3) ; var:_Storage = "chunked" ; var:_ChunkSizes = 4, 4, 4, 4 ; var:_Filter = "307,9" ; var:_NoFill = "true" ; data: var = 0, 1, 2, 3, 4, 5, 6, 7, ... 252, 253, 254, 255 ; } \endcode */ #include "config.h" #include #include #include #include #include "netcdf.h" /* The HDF assigned id for bzip compression */ #define BZIP2_ID 307 /* The compression level used in this example */ #define BZIP2_LEVEL 9 #define DFALT_TESTFILE "tmp_bzip2.nc" /* Point at which we give up */ #define MAXERRS 8 #define NDIMS 4 #define DIMSIZE 4 #define CHUNKSIZE 4 /* Note: not the total size of the chunk, but size wrt a dim*/ static size_t dimsize = DIMSIZE; static size_t chunksize = CHUNKSIZE; static size_t actualdims = NDIMS; static size_t actualproduct = 1; /* x-product over dim sizes */ static size_t chunkproduct = 1; /* x-product over chunksizes */ static size_t dims[NDIMS]; static size_t chunks[NDIMS]; static int nerrs = 0; static const char* testfile = NULL; static int ncid, varid; static int dimids[NDIMS]; static float* array = NULL; static float* expected = NULL; static unsigned int filterid = 0; static unsigned int* params = NULL; /* Forward */ static void init(int argc, char** argv); static int test_bzip2(void); static int verifychunks(void); #define ERRR do { \ fflush(stdout); /* Make sure our stdout is synced with stderr. */ \ fprintf(stderr, "Sorry! Unexpected result, %s, line: %d\n", \ __FILE__, __LINE__); \ nerrs++;\ } while (0) static int check(int err,int line) { if(err != NC_NOERR) { fprintf(stderr,"fail (%d): %s\n",line,nc_strerror(err)); fflush(stderr); exit(1); } return NC_NOERR; } #define CHECK(x) check(x,__LINE__) /* Read the chunking information about the variable and verify that it is as expected. */ static int verifychunks(void) { int i; int store = -1; size_t chunksizes[NDIMS]; memset(chunksizes,0,sizeof(chunksizes)); CHECK(nc_inq_var_chunking(ncid, varid, &store, chunksizes)); /* Storate must be chunked, not contiguous */ if(store != NC_CHUNKED) { fprintf(stderr,"bad chunk store\n"); return NC_ESTORAGE; } /* Chunk sizes must match our predefined set */ for(i=0;i= MAXERRS) break; } } if(errs == 0) printf("no data errors\n"); if(actualproduct <= 1) return NC_EBADDIM; return (errs == 0 ? NC_NOERR: NC_EINVAL); } /* Create the file, write it, then re-read for comparison. */ static int test_bzip2(void) { int i; unsigned int level = BZIP2_LEVEL; unsigned int id=0; size_t nparams = 0; printf("\n*** Testing API: bzip2 compression.\n"); /* Clear the data array */ memset(array,0,sizeof(float)*actualproduct); /* Create a file */ CHECK(nc_create(testfile, NC_NETCDF4|NC_CLOBBER, &ncid)); /* Do not use fill for this file */ CHECK(nc_set_fill(ncid, NC_NOFILL, NULL)); /* Define the dimensions */ for(i=0;i 0) { params = (unsigned int*)malloc(sizeof(unsigned int)*nparams); if(params == NULL) return NC_ENOMEM; CHECK(nc_inq_var_filter(ncid,varid,&filterid,&nparams,params)); } if(filterid != BZIP2_ID) { printf("Bzip2 id mismatch: %d\n",filterid); return NC_EFILTER; } if(nparams != 1 && params != NULL && params[0] != BZIP2_LEVEL) { printf("Compression parameter mismatch\n"); return NC_EFILTER; } /* Verify chunking */ if(!verifychunks()) return 0; /* Read the data */ CHECK(nc_get_var_float(ncid, varid, array)); /* Close the file */ CHECK(nc_close(ncid)); return (compare() == NC_NOERR ? 0 : 1); } /**************************************************/ /* Utilities */ static void init(int argc, char** argv) { int i; /* get the testfile path */ if(argc > 1) testfile = argv[1]; else testfile = DFALT_TESTFILE; /* Setup various variables */ actualproduct = 1; chunkproduct = 1; for(i=0;i 0?1:0); }