Rebuilt the filter parameter handling code to use a common

parser everywhere.
This commit is contained in:
Dennis Heimbigner 2018-01-23 16:00:11 -07:00
parent 22ebecab23
commit 3e47f5f300
17 changed files with 301 additions and 739 deletions

View File

@ -162,8 +162,8 @@ also can easily be represented as 32 bit unsigned integers by
proper casting to an unsigned integer so that the bit pattern
is preserved. Simple integer values of type short or char
(or the unsigned versions) can also be mapped to an unsigned
integer by either sign extension or just padding with zeros in some
consistent way.
integer by truncating to 16 or 8 bits respectively and then
zero extending.
Machine byte order (aka endian-ness) is an issue for passing
some kinds of parameters. You might define the parameters when
@ -238,10 +238,10 @@ the <a href="#ParamEncode">parameter encoding section</a>.
The currently supported constants are as follows.
<table>
<tr halign="center"><th>Example<th>Type<th>Format Tag<th>Notes
<tr><td>-17b<td>signed 8-bit byte<td>b|B<td>
<tr><td>23ub<td>unsigned 8-bit byte<td>u|U b|B<td>
<tr><td>-25S<td>signed 16-bit short<td>s|S<td>
<tr><td>27US<td>unsigned 16-bit short<td>u|U s|S<td>
<tr><td>-17b<td>signed 8-bit byte<td>b|B<td>Truncated to 8 bits and zero extended to 32 bits
<tr><td>23ub<td>unsigned 8-bit byte<td>u|U b|B<td>Truncated to 8 bits and zero extended to 32 bits
<tr><td>-25S<td>signed 16-bit short<td>s|S<td>Truncated to 16 bits and zero extended to 32 bits
<tr><td>27US<td>unsigned 16-bit short<td>u|U s|S<td>Truncated to 16 bits and zero extended to 32 bits
<tr><td>-77<td>implicit signed 32-bit integer<td>Leading minus sign and no tag<td>
<tr><td>77<td>implicit unsigned 32-bit integer<td>No tag<td>
<tr><td>93U<td>explicit unsigned 32-bit integer<td>u|U<td>

View File

@ -1,8 +1,14 @@
SET(CMAKE_BUILD_TYPE "")
SET(libbzip2_SOURCES blocksort.c huffman.c crctable.c randtable.c compress.c decompress.c bzlib.c H5Zbzip2.c)
SET(libbzip2_SOURCES bzlib.h bzlib_private.h
blocksort.c huffman.c crctable.c randtable.c compress.c decompress.c bzlib.c
H5Zbzip2.c h5bzip2.h
)
SET(libmisc_SOURCES H5Zmisc.c)
# Get the compilable sources from nc_test4/hdf5plugins
FOREACH(S ${libbzip2_SOURCES})
FILE(COPY ${CMAKE_SOURCE_DIR}/nc_test4/hdf5plugins/${S} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR})
ENDFOREACH(S)
IF(ENABLE_FILTER_TESTING)
IF(BUILD_UTILITIES)

View File

@ -1,228 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <hdf5.h>
/* Older versions of the hdf library may define H5PL_type_t here */
#include <H5PLextern.h>
#ifndef DLL_EXPORT
#define DLL_EXPORT
#endif
#include "h5misc.h"
#undef DEBUG
static int paramcheck(size_t nparams, const unsigned int* params);
static void byteswap8(unsigned char* mem);
static void mismatch(size_t i, const char* which);
const H5Z_class2_t H5Z_TEST[1] = {{
H5Z_CLASS_T_VERS, /* H5Z_class_t version */
(H5Z_filter_t)(H5Z_FILTER_TEST), /* Filter id number */
1, /* encoder_present flag (set to true) */
1, /* decoder_present flag (set to true) */
"test", /* Filter name for debugging */
(H5Z_can_apply_func_t)H5Z_test_can_apply, /* The "can apply" callback */
NULL, /* The "set local" callback */
(H5Z_func_t)H5Z_filter_test, /* The actual filter function */
}};
/* External Discovery Functions */
H5PL_type_t
H5PLget_plugin_type(void)
{
return H5PL_TYPE_FILTER;
}
const void*
H5PLget_plugin_info(void)
{
return H5Z_TEST;
}
/* Make this explicit */
/*
* The "can_apply" callback returns positive a valid combination, zero for an
* invalid combination and negative for an error.
*/
htri_t
H5Z_test_can_apply(hid_t dcpl_id, hid_t type_id, hid_t space_id)
{
return 1; /* Assume it can always apply */
}
/*
This filter does some verification
that the parameters passed to the filter
are correct. Specifically, that endian-ness
is correct. As a filter, it is the identify
function, passing input to output unchanged.
Test cases format:
1.The first param is the test index i.e. which test to execute.
2. The remaining parameters are those for the test chosen in #1
*/
size_t
H5Z_filter_test(unsigned int flags, size_t cd_nelmts,
const unsigned int cd_values[], size_t nbytes,
size_t *buf_size, void **buf)
{
void* newbuf;
unsigned int testcase = 0;
if(cd_nelmts == 0)
goto fail;
testcase = cd_values[0];
if(testcase == TC_ENDIAN) {
if(!paramcheck(cd_nelmts,cd_values))
goto fail;
}
if (flags & H5Z_FLAG_REVERSE) {
/* Replace buffer */
newbuf = malloc(*buf_size);
if(newbuf == NULL) abort();
memcpy(newbuf,*buf,*buf_size);
*buf = newbuf;
} else {
/* Replace buffer */
newbuf = malloc(*buf_size);
if(newbuf == NULL) abort();
memcpy(newbuf,*buf,*buf_size);
*buf = newbuf;
}
return *buf_size;
fail:
return 0;
}
static int
paramcheck(size_t nparams, const unsigned int* params)
{
size_t i;
/* Test endianness of this machine */
const unsigned char b[4] = {0x0,0x0,0x0,0x1}; /* value 1 in big-endian*/
int bigendian = (1 == *(unsigned int*)b); /* 1=>big 0=>little*/
if(nparams != 14) {
fprintf(stderr,"Too few parameters: need=16 sent=%ld\n",(unsigned long)nparams);
return 0;
}
for(i=0;i<nparams;i++) {
switch (i) {
case 0: break; /* this is the testcase # */
case 1: if(((signed char)-17) != (signed int)(params[i]))
{mismatch(i,"signed byte"); return 0; };
break;
case 2: if(((unsigned char)23) != (unsigned int)(params[i]))
{mismatch(i,"unsigned byte"); return 0; };
break;
case 3: if(((signed short)-25) != (signed int)(params[i]))
{mismatch(i,"signed short"); return 0; };
break;
case 4: if(((unsigned short)27) != (unsigned int)(params[i]))
{mismatch(i,"unsigned short"); return 0; };
break;
case 5: if(77 != (signed int)(params[i]))
{mismatch(i,"signed int"); return 0; };
break;
case 6: if(93u != (unsigned int)(params[i]))
{mismatch(i,"unsigned int"); return 0; };
break;
case 7: if(789.0f != *(float*)(&params[i]))
{mismatch(i,"float"); return 0; };
break;
case 8: {/*double*/
double x = *(double*)&params[i];
i++; /* takes two parameters */
if(bigendian)
byteswap8((unsigned char*)&x);
#if defined _MSC_VER || defined __APPLE__
#define DBLVAL 12345678.12345678
#else
#define DBLVAL 12345678.12345678d
#endif
if(DBLVAL != x) {
mismatch(i,"double");
return 0;
}
}; break;
case 10: {/*signed long long*/
signed long long x = *(signed long long*)&params[i];
i++; /* takes two parameters */
if(bigendian)
byteswap8((unsigned char*)&x);
if(-9223372036854775807L != x) {
mismatch(i,"signed long long");
return 0;
}
}; break;
case 12: {/*unsigned long long*/
unsigned long long x = *(unsigned long long*)&params[i];
i++; /* takes two parameters */
if(bigendian)
byteswap8((unsigned char*)&x);
if(18446744073709551615UL != x) {
mismatch(i,"unsigned long long");
return 0;
}
}; break;
default:
mismatch(i,"unexpected parameter");
return 0;
break;
}
}
#ifdef DEBUG
{
size_t i;
fprintf(stderr,"bigendian=%d nparams=%d params=\n",bigendian,nparams);
for(i=0;i<nparams;i++) {
fprintf(stderr,"[%d] %ud %d %f\n", (unsigned int)i, params[i],(signed int)params[i],*(float*)&params[i]);
}
fflush(stderr);
}
#endif
return 1;
}
static void
byteswap8(unsigned char* mem)
{
unsigned char c;
c = mem[0];
mem[0] = mem[7];
mem[7] = c;
c = mem[1];
mem[1] = mem[6];
mem[6] = c;
c = mem[2];
mem[2] = mem[5];
mem[5] = c;
c = mem[3];
mem[3] = mem[4];
mem[4] = c;
}
static void
mismatch(size_t i, const char* which)
{
fprintf(stderr,"mismatch: [%ld] %s\n",(unsigned long)i,which);
fflush(stderr);
}

View File

@ -1,104 +0,0 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <hdf5.h>
/* Older versions of the hdf library may define H5PL_type_t here */
#include <H5PLextern.h>
#include "xxxx.h"
/*
Provide a textual template (not a C++ template)
from which one can construct a new filter.
The filter "name is marked with "XXXX" or "xxxx"
*/
const H5Z_class2_t H5Z_XXXX[1] = {{
H5Z_CLASS_T_VERS, /* H5Z_class_t version */
(H5Z_filter_t)H5Z_FILTER_XXXX, /* Filter id number */
1, /* encoder_present flag (set to true) */
1, /* decoder_present flag (set to true) */
"xxxx", /* Filter name for debugging */
NULL, /* The "can apply" callback */
NULL, /* The "set local" callback */
(H5Z_func_t)H5Z_filter_xxxx, /* The actual filter function */
}};
/* External Discovery Functions */
H5PL_type_t
H5PLget_plugin_type(void)
{
return H5PL_TYPE_FILTER;
}
const void*
H5PLget_plugin_info(void)
{
return H5Z_XXXX;
}
size_t H5Z_filter_xxxx(unsigned int flags, size_t cd_nelmts,
const unsigned int cd_values[], size_t nbytes,
size_t *buf_size, void **buf);
size_t H5Z_filter_xxxx(unsigned int flags, size_t cd_nelmts,
const unsigned int cd_values[], size_t nbytes,
size_t *buf_size, void **buf)
{
char *outbuf = NULL;
size_t outbuflen, outdatalen;
int ret;
if (flags & H5Z_FLAG_REVERSE) {
/** Decompress data.
**
** This process is troublesome since the size of uncompressed data
** is unknown, so the low-level interface must be used.
** Data is decompressed to the output buffer (which is sized
** for the average case); if it gets full, its size is doubled
** and decompression continues. This avoids repeatedly trying to
** decompress the whole block, which could be really inefficient.
**/
char *newbuf = NULL;
size_t newbuflen;
} else {
/** Compress data.
**
** This is quite simple, since the size of compressed data in the worst
** case is known and it is not much bigger than the size of uncompressed
** data. This allows us to use the simplified one-shot interface to
** compression.
**/
unsigned int odatalen; /* maybe not the same size as outdatalen */
/* Prepare the output buffer. */
outbuflen = M; /* worst case */
outbuf = malloc(outbuflen);
if (outbuf == NULL) {
fprintf(stderr, "memory allocation failed for xxxx compression\n");
goto cleanupAndFail;
}
/* Compress data. */
}
/* Always replace the input buffer with the output buffer. */
free(*buf);
*buf = outbuf;
*buf_size = outbuflen;
return outdatalen;
cleanupAndFail:
if (outbuf)
free(outbuf);
return 0;
}

View File

@ -1,26 +1,26 @@
# Copyright 2018, UCAR/Unidata
# See netcdf/COPYRIGHT file for copying and redistribution conditions.
BZIP2HDRS=bzlib.h bzlib_private.h
BZIP2SRC= blocksort.c huffman.c crctable.c randtable.c compress.c decompress.c bzlib.c
BZIP2SRC = bzlib.h bzlib_private.h blocksort.c huffman.c crctable.c randtable.c compress.c decompress.c bzlib.c
PLUGINSRC=H5Zbzip2.c
PLUGINHDRS=h5bzip2.h
PLUGINSRC = H5Zbzip2.c h5bzip2.h
EXTRA_DIST=${PLUGINSRC} ${BZIP2SRC} ${PLUGINHDRS} ${BZIP2HDRS} \
H5Ztemplate.c H5Zmisc.c
TARGETS = ${PLUGINSRC} ${BZIP2SRC}
BUILT_SOURCES = ${TARGETS}
${TARGETS}:
for x in ${TARGETS} ; do 'cp' -f ${top_srcdir}/nc_test4/hdf5plugins/$$x . ; done
CLEANFILES = ${TARGETS}
if ENABLE_FILTER_TESTING
DLLSRC=${PLUGINSRC} ${BZIP2SRC} ${PLUGINHDRS} ${BZIP2HDRS}
DLLSRC=${PLUGINSRC} ${BZIP2SRC}
lib_LTLIBRARIES = libbzip2.la libmisc.la
lib_LTLIBRARIES = libbzip2.la
libbzip2_la_SOURCES = ${DLLSRC}
libbzip2_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -no-undefined
libmisc_la_SOURCES = H5Zmisc.c h5misc.h
libmisc_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -no-undefined
endif #ENABLE_FILTER_TESTING

View File

@ -1,34 +0,0 @@
#ifndef H5MISC_H
#define H5MISC_H
#ifdef _MSC_VER
#ifdef DLL_EXPORT /* define when building the library */
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif
#else
#define DECLSPEC extern
#endif
/* use an integer greater than 256 to be id of the registered filter. */
#define H5Z_FILTER_TEST 32768
/* Define the test cases */
typedef enum H5testcase {
TC_NONE = 0,
TC_ENDIAN = 1,
} H5testcase;
/* declare the hdf5 interface */
DECLSPEC H5PL_type_t H5PLget_plugin_type(void);
DECLSPEC const void* H5PLget_plugin_info(void);
DECLSPEC const H5Z_class2_t H5Z_TEST[1];
/* Declare filter specific functions */
DECLSPEC htri_t H5Z_test_can_apply(hid_t dcpl_id, hid_t type_id, hid_t space_id);
DECLSPEC size_t H5Z_filter_test(unsigned flags,size_t cd_nelmts,const unsigned cd_values[],
size_t nbytes,size_t *buf_size,void**buf);
#endif /*H5MISC_H*/

View File

@ -5,8 +5,6 @@
if test "x$srcdir" = x ; then srcdir=`pwd`; fi
. ../../test_common.sh
set -x
echo "*** Running examples for netCDF-4."
set -e

View File

@ -18,6 +18,8 @@ extern "C" {
/* Provide consistent filter spec parser */
EXTERNL int NC_parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsigned int** paramsp);
EXTERNL void NC_byteswap8(unsigned char* mem);
#if defined(__cplusplus)
}
#endif

View File

@ -19,9 +19,7 @@ Common utilities related to filters.
/* Forward */
#ifdef WORDS_BIGENDIAN
static void byteswap8(unsigned char* mem);
#endif
static int gettype(const int q0, const int q1, int* unsignedp);
/**************************************************/
/*
@ -39,13 +37,15 @@ of unsigned ints.
EXTERNL int
NC_parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsigned int** paramsp)
{
int stat = NC_NOERR;
int sstat; /* for scanf */
char* p;
char* sdata = NULL;
int stat;
unsigned int id;
size_t count; /* no. of comma delimited params */
size_t nparams; /* final no. of unsigned ints */
size_t i;
size_t len;
int i;
unsigned int* ulist = NULL;
unsigned char mem[8]; /* to convert to network byte order */
@ -67,9 +67,10 @@ NC_parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsign
/* Extract the filter id */
p = sdata;
stat = sscanf(p,"%u",&id);
if(stat != 1) goto fail;
p = p + strlen(p) + 1; /* skip the filter id */
sstat = sscanf(p,"%u",&id);
if(sstat != 1) goto fail;
/* skip past the filter id */
p = p + strlen(p) + 1;
count--;
/* Allocate the max needed space; *2 in case the params are all doubles */
@ -77,41 +78,38 @@ NC_parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsign
if(ulist == NULL) goto fail;
/* walk and convert */
nparams = 0;
for(i=0;i<count;i++) {
char* q;
nparams = 0; /* actual count */
for(i=0;i<count;i++) { /* step thru param strings */
unsigned long long val64u;
unsigned int val32u;
double vald;
float valf;
unsigned int *vector;
int isunsigned;
int isnegative;
int type;
int isunsigned = 0;
int isnegative = 0;
int type = 0;
char* q;
/* Get trailing discrimination characters */
isunsigned = 0;
isnegative = 0;
type = 0;
if(strchr(p,'-') != NULL) isnegative = 1;
q = p+strlen(p)-2;
if(*q == 'U' || *q == 'u') isunsigned = 1;
q++;
switch (*q) {
case 'f': case 'F': type = 'f'; break; /* short */
case 'd': case 'D': type = 'd'; break; /* double */
case 'b': case 'B': type = 'b'; break; /* byte */
case 's': case 'S': type = 's'; break; /* short */
case 'l': case 'L': type = 'l'; break; /* long long */
case 'u': case 'U': type = 'i'; isunsigned = 1; break; /* integer */
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': type = 'i'; break;
default:
if(*q == '\0')
type = 'i';
else goto fail;
len = strlen(p);
/* skip leading white space */
while(strchr(" ",*p) != NULL) {p++; len--;}
/* Get leading sign character, if any */
if(*p == '-') isnegative = 1;
/* Get trailing type tag characters */
switch (len) {
case 0:
goto fail; /* empty parameter */
case 1:
case 2:
q = (p + len) - 1; /* point to last char */
type = gettype(*q,'\0',&isunsigned);
break;
default: /* > 2 => we might have a two letter tag */
q = (p + len) - 2;
type = gettype(*q,*(q+1),&isunsigned);
break;
}
/* Now parse */
switch (type) {
case 'b':
@ -119,25 +117,31 @@ NC_parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsign
case 'i':
/* special case for a positive integer;for back compatibility.*/
if(!isnegative)
stat = sscanf(p,"%u",&val32u);
sstat = sscanf(p,"%u",&val32u);
else
stat = sscanf(p,"%d",(int*)&val32u);
if(stat != 1) goto fail;
sstat = sscanf(p,"%d",(int*)&val32u);
if(sstat != 1) goto fail;
switch(type) {
case 'b': val32u = (val32u & 0xFF); break;
case 's': val32u = (val32u & 0xFFFF); break;
}
ulist[nparams++] = val32u;
break;
case 'f':
stat = sscanf(p,"%lf",&vald);
if(stat != 1) goto fail;
sstat = sscanf(p,"%lf",&vald);
if(sstat != 1) goto fail;
valf = (float)vald;
ulist[nparams++] = *(unsigned int*)&valf;
break;
case 'd':
stat = sscanf(p,"%lf",&vald);
if(stat != 1) goto fail;
sstat = sscanf(p,"%lf",&vald);
if(sstat != 1) goto fail;
/* convert to network byte order */
memcpy(mem,&vald,sizeof(mem));
#ifdef WORDS_BIGENDIAN
byteswap8(mem); /* convert big endian to little endian */
NC_byteswap8(mem); /* convert big endian to little endian */
#endif
vector = (unsigned int*)mem;
ulist[nparams++] = vector[0];
@ -145,10 +149,10 @@ NC_parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsign
break;
case 'l': /* long long */
if(isunsigned)
stat = sscanf(p,"%llu",&val64u);
sstat = sscanf(p,"%llu",&val64u);
else
stat = sscanf(p,"%lld",(long long*)&val64u);
if(stat != 1) goto fail;
sstat = sscanf(p,"%lld",(long long*)&val64u);
if(sstat != 1) goto fail;
/* convert to network byte order */
memcpy(mem,&val64u,sizeof(mem));
#ifdef WORDS_BIGENDIAN
@ -170,19 +174,51 @@ NC_parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsign
*paramsp = ulist;
ulist = NULL; /* avoid duplicate free */
}
done:
if(sdata) free(sdata);
if(ulist) free(ulist);
return 1;
return stat;
fail:
if(sdata) free(sdata);
if(ulist) free(ulist);
return 0;
stat = NC_EFILTER;
goto done;
}
/* Look at q0 and q1) to determine type */
static int
gettype(const int q0, const int q1, int* isunsignedp)
{
int type = 0;
int isunsigned = 0;
char typechar;
isunsigned = (q0 == 'u' || q0 == 'U');
if(q1 == '\0')
typechar = q0; /* we were given only a single char */
else if(isunsigned)
typechar = q1; /* we have something like Ux as the tag */
else
typechar = q1; /* look at last char for tag */
switch (typechar) {
case 'f': case 'F': case '.': type = 'f'; break; /* float */
case 'd': case 'D': type = 'd'; break; /* double */
case 'b': case 'B': type = 'b'; break; /* byte */
case 's': case 'S': type = 's'; break; /* short */
case 'l': case 'L': type = 'l'; break; /* long long */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': type = 'i'; break;
case 'u': case 'U': type = 'i'; isunsigned = 1; break; /* unsigned int */
case '\0': type = 'i'; break;
default: break;
}
if(isunsignedp) *isunsignedp = isunsigned;
return type;
}
#ifdef WORDS_BIGENDIAN
/* Byte swap an 8-byte integer in place */
static void
byteswap8(unsigned char* mem)
EXTERNL
void
NC_byteswap8(unsigned char* mem)
{
unsigned char c;
c = mem[0];

View File

@ -1,9 +1,12 @@
# Test c output
T=test_filter_misc
#SRC=hdf5plugins/H5Zmisc.c
#CMD=valgrind --leak-check=full
CMD=gdb --args
FILTER=H5Zmisc
#FILTER=H5Zmisc
#FILTEROBJ=hdf5plugins/${FILTER}.o
#PAR=1
#SZIP=1
@ -31,7 +34,7 @@ all:: cmp
cmp::
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
${CC} -o t ${CFLAGS} ${T}.c ${SRC} hdf5plugins/${FILTER}.o ${LDFLAGS}
${CC} -o t ${CFLAGS} ${T}.c ${SRC} ${FILTEROBJ} ${LDFLAGS}
filter::
${CC} ${CFLAGS} -c hdf5plugins/${FILTER}.c ${LDFLAGS}

View File

@ -13,6 +13,12 @@
#include "h5misc.h"
#if defined _MSC_VER || defined __APPLE__
#define DBLVAL 12345678.12345678
#else
#define DBLVAL 12345678.12345678d
#endif
#undef DEBUG
static int paramcheck(size_t nparams, const unsigned int* params);
@ -119,72 +125,88 @@ paramcheck(size_t nparams, const unsigned int* params)
if(nparams != 14) {
fprintf(stderr,"Too few parameters: need=16 sent=%ld\n",(unsigned long)nparams);
return 0;
goto fail;
}
for(i=0;i<nparams;i++) {
unsigned int ival;
unsigned long long lval;
float fval;
double dval;
switch (i) {
case 0: break; /* this is the testcase # */
case 1: if(((signed char)-17) != (signed int)(params[i]))
{mismatch(i,"signed byte"); return 0; };
case 1:
ival = (-17) & 0xff;
if(ival != (signed int)(params[i]))
{mismatch(i,"signed byte"); goto fail; };
break;
case 2: if(((unsigned char)23) != (unsigned int)(params[i]))
{mismatch(i,"unsigned byte"); return 0; };
case 2:
ival = 23;
if(ival != (unsigned int)(params[i]))
{mismatch(i,"unsigned byte"); goto fail; };
break;
case 3: if(((signed short)-25) != (signed int)(params[i]))
{mismatch(i,"signed short"); return 0; };
case 3:
ival = (-25) & 0xffff;
if(ival != (signed int)(params[i]))
{mismatch(i,"signed short"); goto fail; };
break;
case 4: if(((unsigned short)27) != (unsigned int)(params[i]))
{mismatch(i,"unsigned short"); return 0; };
case 4:
ival = 27;
if(ival != (unsigned int)(params[i]))
{mismatch(i,"unsigned short"); goto fail; };
break;
case 5: if(77 != (signed int)(params[i]))
{mismatch(i,"signed int"); return 0; };
case 5:
ival = 77;
if(ival != (signed int)(params[i]))
{mismatch(i,"signed int"); goto fail; };
break;
case 6: if(93u != (unsigned int)(params[i]))
{mismatch(i,"unsigned int"); return 0; };
case 6:
ival = 93u;
if(ival != (unsigned int)(params[i]))
{mismatch(i,"unsigned int"); goto fail; };
break;
case 7: if(789.0f != *(float*)(&params[i]))
{mismatch(i,"float"); return 0; };
case 7:
fval = 789.0f;
if(fval != *(float*)(&params[i]))
{mismatch(i,"float"); goto fail; };
break;
case 8: {/*double*/
double x = *(double*)&params[i];
dval = DBLVAL;
i++; /* takes two parameters */
if(bigendian)
byteswap8((unsigned char*)&x);
#if defined _MSC_VER || defined __APPLE__
#define DBLVAL 12345678.12345678
#else
#define DBLVAL 12345678.12345678d
#endif
if(DBLVAL != x) {
if(dval != x) {
mismatch(i,"double");
return 0;
goto fail;
}
}; break;
case 10: {/*signed long long*/
signed long long x = *(signed long long*)&params[i];
lval = -9223372036854775807L;
i++; /* takes two parameters */
if(bigendian)
byteswap8((unsigned char*)&x);
if(-9223372036854775807L != x) {
if(lval != x) {
mismatch(i,"signed long long");
return 0;
goto fail;
}
}; break;
case 12: {/*unsigned long long*/
unsigned long long x = *(unsigned long long*)&params[i];
lval = 18446744073709551615UL;
i++; /* takes two parameters */
if(bigendian)
byteswap8((unsigned char*)&x);
if(18446744073709551615UL != x) {
if(lval != x) {
mismatch(i,"unsigned long long");
return 0;
goto fail;
}
}; break;
default:
mismatch(i,"unexpected parameter");
return 0;
goto fail;
break;
}
}
@ -200,6 +222,8 @@ paramcheck(size_t nparams, const unsigned int* params)
}
#endif
return 1;
fail:
return 0;
}
static void

View File

@ -11,15 +11,21 @@
#include <hdf5.h>
#include "netcdf.h"
#if defined _MSC_VER || defined __APPLE__
#define DBLVAL 12345678.12345678
#else
#define DBLVAL 12345678.12345678d
#endif
#define TEST_ID 32768
#define MAXERRS 8
#define MAXPARAMS 32
#define NBASELINE 14
#define NPARAMS 14
static unsigned int baseline[NBASELINE];
static unsigned int baseline[NPARAMS];
#define MAXDIMS 8
@ -29,6 +35,8 @@ static unsigned int baseline[NBASELINE];
#define TESTFILE "testmisc.nc"
#define spec "32768, -17b, 23ub, -25S, 27US, 77, 93U, 789f, 12345678.12345678d, -9223372036854775807L, 18446744073709551615UL"
static size_t dimsize = DEFAULTDIMSIZE;
static size_t chunksize = DEFAULTCHUNKSIZE;
static size_t actualdims = DEFAULTACTUALDIMS;
@ -131,7 +139,7 @@ create(void)
static void
setvarfilter(void)
{
CHECK(nc_def_var_filter(ncid,varid,TEST_ID,NBASELINE,baseline));
CHECK(nc_def_var_filter(ncid,varid,TEST_ID,NPARAMS,baseline));
verifyparams();
}
@ -141,7 +149,7 @@ verifyparams(void)
int i;
CHECK(nc_inq_var_filter(ncid,varid,&filterid,&nparams,params));
if(filterid != TEST_ID) REPORT("id mismatch");
if(nparams != NBASELINE) REPORT("nparams mismatch");
if(nparams != NPARAMS) REPORT("nparams mismatch");
for(i=0;i<nparams;i++) {
if(params[i] != baseline[i])
REPORT("param mismatch");
@ -166,16 +174,16 @@ openfile(void)
CHECK(nc_inq_var_filter(ncid,varid,&filterid,&nparams,params));
}
if(filterid != TEST_ID) {
printf("open: test id mismatch: %d\n",filterid);
fprintf(stderr,"open: test id mismatch: %d\n",filterid);
return NC_EFILTER;
}
if(nparams != NBASELINE) {
if(nparams != NPARAMS) {
size_t i;
unsigned int inqparams[MAXPARAMS];
printf("nparams mismatch\n");
fprintf(stderr,"nparams mismatch\n");
for(nerrs=0,i=0;i<nparams;i++) {
if(inqparams[i] != baseline[i]) {
printf("open: testparam mismatch: %ld\n",(unsigned long)i);
fprintf(stderr,"open: testparam mismatch: %ld\n",(unsigned long)i);
nerrs++;
}
}
@ -231,7 +239,7 @@ compare(void)
int i;
for(i=0;i<actualproduct;i++) {
if(expected[i] != array[i]) {
fprintf(stderr,"mismatch: array[%d]=%f expected[%d]=%f\n",
fprintf(stderr,"data mismatch: array[%d]=%f expected[%d]=%f\n",
i,array[i],i,expected[i]);
errs++;
if(errs >= MAXERRS)
@ -245,7 +253,7 @@ compare(void)
int offset = odom_offset();
float expect = expectedvalue();
if(array[offset] != expect) {
fprintf(stderr,"mismatch: array[%d]=%f expected=%f\n",
fprintf(stderr,"data mismatch: array[%d]=%f expected=%f\n",
offset,array[offset],expect);
errs++;
if(errs >= MAXERRS)
@ -264,14 +272,15 @@ static void
showparameters(void)
{
int i;
printf("test: nparams=%ld: params=",(unsigned long)nparams);
fprintf(stderr,"test: nparams=%ld: params=",(unsigned long)nparams);
for(i=0;i<nparams;i++) {
printf(" %u",params[i]);
fprintf(stderr," %u",params[i]);
}
printf("\n");
fprintf(stderr,"\n");
for(i=0;i<actualdims;i++)
printf("%s%ld",(i==0?" chunks=":","),(unsigned long)chunks[i]);
printf("\n");
fprintf(stderr,"%s%ld",(i==0?" chunks=":","),(unsigned long)chunks[i]);
fprintf(stderr,"\n");
fflush(stderr);
}
static void
@ -292,11 +301,11 @@ buildbaseline(unsigned int testcasenumber)
baseline[0] = testcasenumber;
switch (testcasenumber) {
case 1:
val4 = (unsigned int)-17;
val4 = ((unsigned int)-17) & 0xff;
insert(1,&val4,sizeof(val4)); /* 1 signed int*/
val4 = (unsigned int)23;
insert(2,&val4,sizeof(val4)); /* 2 unsigned int*/
val4 = (unsigned int)-25;
val4 = ((unsigned int)-25) & 0xffff;
insert(3,&val4,sizeof(val4)); /* 3 signed int*/
val4 = (unsigned int)27;
insert(4,&val4,sizeof(val4)); /* 4 unsigned int*/
@ -306,11 +315,6 @@ buildbaseline(unsigned int testcasenumber)
insert(6,&val4,sizeof(val4)); /* 6 unsigned int*/
float4 = 789.0f;
insert(7,&float4,sizeof(float4)); /* 7 float */
#if defined _MSC_VER || defined __APPLE__
#define DBLVAL 12345678.12345678
#else
#define DBLVAL 12345678.12345678d
#endif
float8 = DBLVAL;
insert(8,&float8,sizeof(float8)); /* 8 double */
val8 = -9223372036854775807L;
@ -333,7 +337,7 @@ test_test1(void)
buildbaseline(1);
printf("test1: compression.\n");
fprintf(stderr,"test1: compression.\n");
create();
setchunking();
setvarfilter();
@ -346,7 +350,7 @@ test_test1(void)
CHECK(nc_put_var(ncid,varid,expected));
CHECK(nc_close(ncid));
printf("test1: decompression.\n");
fprintf(stderr,"test1: decompression.\n");
reset();
openfile();
CHECK(nc_get_var_float(ncid, varid, array));
@ -441,6 +445,7 @@ int
main(int argc, char **argv)
{
H5Eprint(stderr);
nc_set_log_level(1);
init(argc,argv);
if(!test_test1()) ERRR;
exit(nerrs > 0?1:0);

View File

@ -3,8 +3,6 @@
if test "x$srcdir" = x ; then srcdir=`pwd`; fi
. ../test_common.sh
set -e
# Which test cases to exercise
API=1
NG=1
@ -79,7 +77,7 @@ rm -f ./tmp
trimleft ./tmp2 ./tmp
rm -f ./tmp2
cat >./tmp2 <<EOF
var:_Filter = "32768,1,4294967279,23,4294967271,27,77,93,1145389056,3287505826,1097305129,1,2147483648,4294967295,4294967295" ;
var:_Filter = "32768,1,239,23,65511,27,77,93,1145389056,3287505826,1097305129,1,2147483648,4294967295,4294967295" ;
EOF
diff -b -w ./tmp ./tmp2
echo "*** Pass: parameter passing"

View File

@ -11,30 +11,28 @@
#include "netcdf.h"
#include "ncfilter.h"
#undef USE_INTERNAL
#define PARAMS_ID 32768
static const unsigned int baseline[] = {
-17, /* 0 signed int*/
23, /* 1 unsigned int*/
-25, /* 2 signed int*/
27, /* 3 unsigned int*/
77, /* 4 signed int*/
93, /* 5 unsigned int*/
1145389056U, /* 6 float*/
3287505826, 1097305129, /* 7-8 double*/
1, 2147483648, /* 9-10 signed long long*/
4294967295, 4294967295, /* 11-12 unsigned long long*/
/* Edge cases */
2147483647, /* 13 max signed int*/
-2147483648, /* 14 min signed int*/
4294967295 /* 15 max unsigned int with no trailing U*/
};
#if defined _MSC_VER || defined __APPLE__
#define DBLVAL 12345678.12345678
#else
#define DBLVAL 12345678.12345678d
#endif
#define MAXPARAMS 32
#define NPARAMS 16 /* # of unsigned ints in params */
static unsigned int baseline[NPARAMS];
/* Expected contents of baseline:
id = 32768
params = 4294967279, 23, 4294967271, 27, 77, 93, 1145389056, 3287505826, 1097305129, 1, 2147483648, 4294967295, 4294967295
*/
static const char* spec =
"32768, -17b, 23ub, -25S, 27US, 77, 93U, 789f, 12345678.12345678d, -9223372036854775807L, 18446744073709551615UL, 2147483647, -2147483648, 4294967295";
/* Test support for the conversions */
/* Not sure if this kind of casting via union is legal C99 */
static union {
@ -55,30 +53,66 @@ static union {
static int nerrs = 0;
#ifdef USE_INTERNAL
static int parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsigned int** paramsp);
#endif
#ifdef WORD_BIGENDIAN
static void byteswap8(unsigned char* mem);
#endif
static void
report(const char* which)
mismatch(size_t i, unsigned int *params, const char* tag)
{
fprintf(stderr,"mismatch: %s\n",which);
fprintf(stderr,"mismatch: %s [%d] baseline=%ud params=%u\n",tag,(int)i,baseline[i],params[i]);
fflush(stderr);
nerrs++;
}
static void
mismatch(size_t i, unsigned int baseline, unsigned int params)
mismatch2(size_t i, unsigned int *params, const char* tag)
{
fprintf(stderr,"mismatch: [%d] baseline=%ud spec=%ud\n",(int)i,baseline,params);
fprintf(stderr,"mismatch2: %s [%d-%d] baseline=%ud,%ud params=%u,%u\n",
tag,(int)i,i+1,baseline[i],baseline[i+1],params[i],params[i+1]);
fflush(stderr);
nerrs++;
}
static void
insert(int index, void* src, size_t size)
{
void* dst = &baseline[index];
memcpy(dst,src,size);
}
static void
buildbaseline(void)
{
unsigned int val4;
unsigned long long val8;
float float4;
double float8;
val4 = ((unsigned int)-17) & 0xff;
insert(0,&val4,sizeof(val4)); /* 0 signed int*/
val4 = (unsigned int)23;
insert(1,&val4,sizeof(val4)); /* 1 unsigned int*/
val4 = ((unsigned int)-25) & 0xffff;
insert(2,&val4,sizeof(val4)); /* 3 signed int*/
val4 = (unsigned int)27;
insert(3,&val4,sizeof(val4)); /* 4 unsigned int*/
val4 = (unsigned int)77;
insert(4,&val4,sizeof(val4)); /* 4 signed int*/
val4 = (unsigned int)93;
insert(5,&val4,sizeof(val4)); /* 5 unsigned int*/
float4 = 789.0f;
insert(6,&float4,sizeof(float4)); /* 6 float */
float8 = DBLVAL;
insert(7,&float8,sizeof(float8)); /* 7 double */
val8 = -9223372036854775807L;
insert(9,&val8,sizeof(val8)); /* 9 signed long long */
val8 = 18446744073709551615UL;
insert(11,&val8,sizeof(val8)); /* 11 unsigned long long */
val4 = 2147483647;
insert(13,&val4,sizeof(val4)); /* 13 signed int */
val4 = -2147483648;
insert(14,&val4,sizeof(val4)); /* 14 signed int */
val4 = 4294967295;
insert(15,&val4,sizeof(val4)); /* 15 unsigned int */
}
/**************************************************/
int
main(int argc, char **argv)
@ -90,44 +124,44 @@ main(int argc, char **argv)
printf("\nTesting filter parser.\n");
#ifdef USE_INTERNAL
stat = parsefilterspec(spec,&id,&nparams,&params);
#else
buildbaseline(); /* Build our comparison vector */
stat = NC_parsefilterspec(spec,&id,&nparams,&params);
#endif
if(!stat) {
report("NC_parsefilterspec failed");
if(stat) {
fprintf(stderr,"NC_parsefilterspec failed\n");
exit(1);
}
if(id != PARAMS_ID)
fprintf(stderr,"mismatch: id: expected=%u actual=%u\n",PARAMS_ID,id);
for(i=0;i<nparams;i++) {
if(baseline[i] != params[i])
mismatch(i,baseline[i],params[i]);
mismatch(i,params,"N.A.");
}
/* Now some specialized tests */
uf.ui = params[6];
if(uf.f != (float)789.0)
report("uf.f");
mismatch(6,params,"uf.f");
ud.ui[0] = params[7];
ud.ui[1] = params[8];
#ifdef WORD_BIGENDIAN
byteswap8((unsigned char*)&ud.d);
#endif
if(ud.d != (double)12345678.12345678)
report("ud.d");
if(ud.d != DBLVAL)
mismatch2(7,params,"ud.d");
ul.ui[0] = params[9];
ul.ui[1] = params[10];
#ifdef WORD_BIGENDIAN
byteswap8((unsigned char*)&ul.ll);
#endif
if(ul.ll != -9223372036854775807LL)
report("ul.ll");
mismatch2(9,params,"ul.ll");
ul.ui[0] = params[11];
ul.ui[1] = params[12];
#ifdef WORD_BIGENDIAN
byteswap8((unsigned char*)&ul.ull);
#endif
if(ul.ull != 18446744073709551615ULL)
report("ul.ull");
mismatch2(11,params,"ul.ull");
if (params)
free(params);
@ -158,146 +192,3 @@ byteswap8(unsigned char* mem)
mem[4] = c;
}
#endif
#ifdef USE_INTERNAL
static int
parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsigned int** paramsp)
{
char* p;
char* sdata = NULL;
int stat;
unsigned int uval, id;
size_t count; /* no. of comma delimited params */
size_t nparams; /* final no. of unsigned ints */
size_t i;
unsigned int* ulist = NULL;
unsigned char mem[8]; /* to convert to network byte order */
if(spec == NULL || strlen(spec) == 0) goto fail;
sdata = strdup(spec);
/* Count number of parameters + id and delimit */
p=sdata;
for(count=0;;count++) {
char* q = strchr(p,',');
if(q == NULL) break;
*q++ = '\0';
p = q;
}
count++; /* for final piece */
if(count == 0)
goto fail; /* no id and no parameters */
/* Extract the filter id */
p = sdata;
stat = sscanf(p,"%u",&id);
if(stat != 1) goto fail;
p = p + strlen(p) + 1; /* skip the filter id */
count--;
/* Allocate the max needed space; *2 in case the params are all doubles */
ulist = (unsigned int*)malloc(sizeof(unsigned int)*(count)*2);
if(ulist == NULL) goto fail;
/* walk and convert */
nparams = 0;
for(i=0;i<count;i++) {
char* q;
unsigned long long val64u;
unsigned int val32u;
double vald;
float valf;
unsigned int *vector;
int isunsigned;
int isnegative;
int type;
/* Get trailing discrimination characters */
isunsigned = 0;
isnegative = 0;
type = 0;
if(strchr(p,'-') != NULL) isnegative = 1;
q = p+strlen(p)-2;
if(*q == 'U' || *q == 'u') isunsigned = 1;
q++;
switch (*q) {
case 'f': case 'F': type = 'f'; break; /* short */
case 'd': case 'D': type = 'd'; break; /* double */
case 'b': case 'B': type = 'b'; break; /* byte */
case 's': case 'S': type = 's'; break; /* short */
case 'l': case 'L': type = 'l'; break; /* long long */
case 'u': case 'U': type = 'i'; isunsigned = 1; break; /* integer */
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': type = 'i'; break;
default:
if(*q == '\0')
type = 'i';
else goto fail;
}
/* Now parse */
switch (type) {
case 'b':
case 's':
case 'i':
/* special case for a positive integer;for back compatibility.*/
if(!isnegative)
stat = sscanf(p,"%u",&val32u);
else
stat = sscanf(p,"%d",(int*)&val32u);
if(stat != 1) goto fail;
ulist[nparams++] = val32u;
break;
case 'f':
stat = sscanf(p,"%lf",&vald);
if(stat != 1) goto fail;
valf = (float)vald;
ulist[nparams++] = *(unsigned int*)&valf;
break;
case 'd':
stat = sscanf(p,"%lf",&vald);
if(stat != 1) goto fail;
/* convert to network byte order */
memcpy(mem,&vald,sizeof(mem));
#ifdef WORDS_BIGENDIAN
byteswap8(mem); /* convert little endian to big endian */
#endif
vector = (unsigned int*)mem;
ulist[nparams++] = vector[0];
ulist[nparams++] = vector[1];
break;
case 'l': /* long long */
if(isunsigned)
stat = sscanf(p,"%llu",&val64u);
else
stat = sscanf(p,"%lld",(long long*)&val64u);
if(stat != 1) goto fail;
/* convert to network byte order */
memcpy(mem,&val64u,sizeof(mem));
#ifdef WORDS_BIGENDIAN
byteswap8(mem); /* convert little endian to big endian */
#endif
vector = (unsigned int*)mem;
ulist[nparams++] = vector[0];
ulist[nparams++] = vector[1];
break;
default:
goto fail;
}
p = p + strlen(p) + 1; /* move to next param */
}
/* Now return results */
if(idp) *idp = id;
if(nparamsp) *nparamsp = nparams;
if(paramsp) *paramsp = ulist;
ulist = NULL; /* avoid duplicate free */
if(sdata) free(sdata);
if(ulist) free(ulist);
return 1;
fail:
if(sdata) free(sdata);
if(ulist) free(ulist);
return 0;
}
#endif /*USE_INTERNAL*/

View File

@ -233,6 +233,7 @@ done:
static int
parsefilterspec(const char* optarg0, struct FilterSpec* spec)
{
int stat = NC_NOERR;
char* optarg = NULL;
unsigned int* params = NULL;
size_t nparams;
@ -263,14 +264,14 @@ parsefilterspec(const char* optarg0, struct FilterSpec* spec)
}
/* Collect the id+parameters */
if(!NC_parsefilterspec(remainder,&id,&nparams,&params))
return 0;
if((stat = NC_parsefilterspec(remainder,&id,&nparams,&params)) == NC_NOERR) {
if(spec != NULL) {
spec->filterid = id;
spec->nparams = nparams;
spec->params = params;
}
return 1;
}
return stat;
}
@ -1969,7 +1970,8 @@ main(int argc, char**argv)
break;
case 'F': /* optional filter spec for a specified variable */
#ifdef USE_NETCDF4
if(!parsefilterspec(optarg,&filterspec)) usage();
if(parsefilterspec(optarg,&filterspec) != NC_NOERR)
usage();
if(nfilterspecs >= (MAX_FILTER_SPECS-1))
error("too many -F filterspecs\n");
filterspecs[nfilterspecs] = filterspec;
@ -2015,7 +2017,6 @@ main(int argc, char**argv)
#endif /*DEBUGFILTER*/
#endif /*USE_NETCDF4*/
if(copy(inputfile, outputfile) != NC_NOERR)
exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);

View File

@ -141,8 +141,8 @@ typedef struct Specialdata {
int _Endianness; /* 1 =>little, 2 => big*/
int _Fill ; /* 0 => false, 1 => true WATCHOUT: this is inverse of NOFILL*/
unsigned int _FilterID;
unsigned int* _FilterParams; /* NULL => defaults*/
size_t nparams; /* |_FilterParms| ; 0 => not specified*/
unsigned int* _FilterParams; /* NULL => defaults*/
} Specialdata;
typedef struct GlobalSpecialdata {

View File

@ -1330,8 +1330,12 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
} break;
case _FILTER_FLAG:
/* Parse the filter spec */
if(parsefilterflag(sdata,special))
if(parsefilterflag(sdata,special) == NC_NOERR)
special->flags |= _FILTER_FLAG;
else {
efree(special->_FilterParams);
derror("_Filter: unparseable filter spec: %s",sdata);
}
break;
default: PANIC1("makespecial: illegal token: %d",tag);
}
@ -1448,55 +1452,15 @@ Parse a filter spec string and store it in special
static int
parsefilterflag(const char* sdata0, Specialdata* special)
{
char* p;
char* sdata = NULL;
int stat;
size_t count;
unsigned int* ulist = NULL;
int stat = NC_NOERR;
if(sdata0 == NULL || strlen(sdata0) == 0) goto fail;
sdata = strdup(sdata0);
/* Count number of unsigned integers and delimit */
p=sdata;
for(count=0;;count++) {
char* q = strchr(p,',');
if(q == NULL) break;
*q++ = '\0'; /* delimit */
p = q;
}
count++; /* for final piece */
/* Start by collecting the filter id */
p = sdata;
stat = sscanf(p,"%u",&special->_FilterID);
if(stat != 1) goto fail;
count--; /* actual param count minus the id */
ulist = (unsigned int*)malloc(sizeof(unsigned int)*(count));
if(ulist == NULL) goto fail;
special->nparams = count;
for(count=0;count < special->nparams ;) {
unsigned int uval;
p = p + strlen(p) + 1; /* move to next param */
stat = sscanf(p,"%u",&uval);
if(stat != 1) goto fail;
ulist[count++] = uval;
}
special->_FilterParams = ulist;
ulist = NULL; /* avoid duplicate free */
if(sdata) free(sdata);
if(ulist) free(ulist);
return 1;
fail:
if(sdata) free(sdata);
if(ulist) free(ulist);
if(special) special->_FilterID = 0;
stat = NC_parsefilterspec(sdata0, &special->_FilterID, &special->nparams, &special->_FilterParams);
if(stat)
derror("Malformed filter spec: %s",sdata);
return 0;
return stat;
}
/*