mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-01-12 15:45:21 +08:00
fix discovered bug in opaque data handling
This commit is contained in:
parent
c39c006039
commit
766b45b459
@ -1,13 +1,17 @@
|
||||
netcdf ref_tst_opaque_data {
|
||||
types:
|
||||
opaque(11) raw_obs_t ;
|
||||
opaque(10) raw_obs_t ;
|
||||
opaque(3) raw_obs2_t ;
|
||||
dimensions:
|
||||
time = 5 ;
|
||||
variables:
|
||||
raw_obs_t raw_obs(time) ;
|
||||
raw_obs_t raw_obs:_FillValue = 0XCAFEBABECAFEBABECAFEBA ;
|
||||
raw_obs_t raw_obs:_FillValue = 0XCAFEBABECAFEBABECAF ;
|
||||
raw_obs2_t raw_obs2(time) ;
|
||||
raw_obs2_t raw_obs2:_FillValue = 0XABC;
|
||||
data:
|
||||
|
||||
raw_obs = 0X0102030405060708090A0B, 0XAABBCCDDEEFFEEDDCCBBAA,
|
||||
0XFFFFFFFFFFFFFFFFFFFFFF, _, 0XCF0DEFACED0CAFE0FACADE ;
|
||||
raw_obs = 0X02030405060708090A0B, 0XAABBCCDDEEFFEEDDC,
|
||||
0XFFFFFFFFFFFFFFFFFFFF, _, 0XCF0DEFACED0CAFE0FACA ;
|
||||
raw_obs2 = 0X123, _, 0XFFF, _, 0X357 ;
|
||||
}
|
||||
|
@ -1,13 +1,18 @@
|
||||
netcdf ref_tst_opaque_data {
|
||||
types:
|
||||
opaque(11) raw_obs_t ;
|
||||
opaque(10) raw_obs_t ;
|
||||
opaque(3) raw_obs2_t ;
|
||||
dimensions:
|
||||
time = 5 ;
|
||||
variables:
|
||||
raw_obs_t raw_obs(time) ;
|
||||
raw_obs_t raw_obs:_FillValue = 0XCAFEBABECAFEBABECAFEBA ;
|
||||
raw_obs_t raw_obs:_FillValue = 0XCAFEBABECAFEBABECAF0 ;
|
||||
raw_obs2_t raw_obs2(time) ;
|
||||
raw_obs2_t raw_obs2:_FillValue = 0XABC000 ;
|
||||
data:
|
||||
|
||||
raw_obs = 0X0102030405060708090A0B, 0XAABBCCDDEEFFEEDDCCBBAA,
|
||||
0XFFFFFFFFFFFFFFFFFFFFFF, _, 0XCF0DEFACED0CAFE0FACADE ;
|
||||
raw_obs = 0X02030405060708090A0B, 0XAABBCCDDEEFFEEDDC000,
|
||||
0XFFFFFFFFFFFFFFFFFFFF, _, 0XCF0DEFACED0CAFE0FACA ;
|
||||
|
||||
raw_obs2 = 0X123000, _, 0XFFF000, _, 0X357000 ;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ bin_constant(Generator* generator, Constant* con, Bytebuffer* buf,...)
|
||||
case NC_OPAQUE: {
|
||||
unsigned char* bytes;
|
||||
size_t len;
|
||||
/* Assume the opaque string has been normalized */
|
||||
bytes=makebytestring(con->value.opaquev.stringv,&len);
|
||||
bbAppendn(buf,(void*)bytes,len);
|
||||
} break;
|
||||
|
11
ncgen/cvt.c
11
ncgen/cvt.c
@ -49,7 +49,6 @@ convert1(Constant* src, Constant* dst)
|
||||
}
|
||||
|
||||
if(src->nctype == NC_OPAQUE) {
|
||||
ASSERT(src->value.opaquev.len >= 16);
|
||||
bytes = makebytestring(src->value.opaquev.stringv,&bytelen);
|
||||
}
|
||||
|
||||
@ -524,7 +523,8 @@ case CASE(NC_OPAQUE,NC_DOUBLE):
|
||||
tmp.doublev = *(double*)bytes;
|
||||
break;
|
||||
case CASE(NC_OPAQUE,NC_OPAQUE):
|
||||
tmp.opaquev.stringv = nulldup(src->value.opaquev.stringv);
|
||||
tmp.opaquev.stringv = (char*)malloc(src->value.opaquev.len);
|
||||
memcpy(tmp.opaquev.stringv,src->value.opaquev.stringv,src->value.opaquev.len);
|
||||
tmp.opaquev.len = src->value.opaquev.len;
|
||||
break;
|
||||
|
||||
@ -543,6 +543,7 @@ case CASE(NC_OPAQUE,NC_OPAQUE):
|
||||
dst->value = tmp;
|
||||
}
|
||||
|
||||
#ifdef IGNORE
|
||||
/* Force an Opaque or string to conform to a given length*/
|
||||
void
|
||||
setprimlength(Constant* prim, unsigned long len)
|
||||
@ -565,15 +566,16 @@ setprimlength(Constant* prim, unsigned long len)
|
||||
prim->value.stringv.len = len;
|
||||
}
|
||||
} else if(prim->nctype == NC_OPAQUE) {
|
||||
/* Note that expansion/contraction is in terms of whole
|
||||
bytes = 2 nibbles */
|
||||
ASSERT((len % 2) == 0);
|
||||
if(prim->value.opaquev.len == len) {
|
||||
/* do nothing*/
|
||||
} else if(prim->value.opaquev.len > len) { /* truncate*/
|
||||
if((len % 2) != 0) len--;
|
||||
prim->value.opaquev.stringv[len] = '\0';
|
||||
prim->value.opaquev.len = len;
|
||||
} else {/* prim->value.opaquev.len < len => expand*/
|
||||
char* s;
|
||||
if((len % 2) != 0) len++;
|
||||
s = (char*)emalloc(len+1);
|
||||
memset(s,'0',len);
|
||||
memcpy(s,prim->value.opaquev.stringv,prim->value.opaquev.len);
|
||||
@ -584,6 +586,7 @@ setprimlength(Constant* prim, unsigned long len)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Datalist*
|
||||
convertstringtochars(Constant* str)
|
||||
|
@ -80,6 +80,7 @@ generate_vardata(Symbol* vsym, Generator* generator, Writer writer, Bytebuffer*
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int rank = dimset->ndims;
|
||||
Symbol* basetype = vsym->typ.basetype;
|
||||
Datalist* filler = getfiller(vsym);
|
||||
|
||||
if(vsym->data == NULL) return;
|
||||
|
||||
@ -88,10 +89,10 @@ generate_vardata(Symbol* vsym, Generator* generator, Writer writer, Bytebuffer*
|
||||
|
||||
if(rank == 0) {/*scalar case*/
|
||||
Constant* c0 = datalistith(vsym->data,0);
|
||||
generate_basetype(basetype,c0,code,NULL,generator);
|
||||
generate_basetype(basetype,c0,code,filler,generator);
|
||||
writer(generator,vsym,code,0,NULL,NULL);
|
||||
} else {/*rank > 0*/
|
||||
generate_array(vsym,code,NULL,generator,writer);
|
||||
generate_array(vsym,code,filler,generator,writer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,6 +278,8 @@ generate_arrayr(Symbol* vsym,
|
||||
break;
|
||||
#endif
|
||||
if(con == NULL || con->nctype == NC_FILL) {
|
||||
if(filler == NULL)
|
||||
filler = getfiller(vsym);
|
||||
generate_arrayr(vsym,code,filler,odom,nextunlimited,NULL,generator);
|
||||
|
||||
} else if(!islistconst(con))
|
||||
@ -418,6 +421,35 @@ generate_fieldarray(Symbol* basetype, Constant* con, Dimset* dimset,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* An opaque string value might not conform
|
||||
to the size of the opaque to which it is being
|
||||
assigned. Normalize it to match the required
|
||||
opaque length (in bytes).
|
||||
Note that the string is a sequence of nibbles (4 bits).
|
||||
*/
|
||||
static void
|
||||
normalizeopaquelength(Constant* prim, unsigned long nbytes)
|
||||
{
|
||||
int nnibs = 2*nbytes;
|
||||
ASSERT(prim->nctype==NC_OPAQUE);
|
||||
if(prim->value.opaquev.len == nnibs) {
|
||||
/* do nothing*/
|
||||
} else if(prim->value.opaquev.len > nnibs) { /* truncate*/
|
||||
prim->value.opaquev.stringv[nnibs] = '\0';
|
||||
prim->value.opaquev.len = nnibs;
|
||||
} else {/* prim->value.opaquev.len < nnibs => expand*/
|
||||
char* s;
|
||||
s = (char*)emalloc(nnibs+1);
|
||||
memset(s,'0',nnibs);
|
||||
memcpy(s,prim->value.opaquev.stringv,prim->value.opaquev.len);
|
||||
s[nnibs] = '\0';
|
||||
efree(prim->value.opaquev.stringv);
|
||||
prim->value.opaquev.stringv=s;
|
||||
prim->value.opaquev.len = nnibs;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
generate_primdata(Symbol* basetype, Constant* prim, Bytebuffer* codebuf,
|
||||
Datalist* filler, Generator* generator)
|
||||
@ -443,8 +475,8 @@ generate_primdata(Symbol* basetype, Constant* prim, Bytebuffer* codebuf,
|
||||
if(basetype->subclass != NC_ENUM) {
|
||||
semerror(constline(prim),"Conversion to enum not supported (yet)");
|
||||
} break;
|
||||
case NC_OPAQUE:
|
||||
setprimlength(&target,basetype->typ.size*2);
|
||||
case NC_OPAQUE:
|
||||
normalizeopaquelength(&target,basetype->typ.size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -931,11 +931,12 @@ makeprimitivetype(nc_type nctype)
|
||||
sym->objectclass=NC_TYPE;
|
||||
sym->subclass=NC_PRIM;
|
||||
sym->ncid = nctype;
|
||||
sym->typ.basetype = NULL;
|
||||
sym->typ.typecode = nctype;
|
||||
sym->typ.size = ncsize(nctype);
|
||||
sym->typ.nelems = 1;
|
||||
sym->typ.alignment = nctypealignment(nctype);
|
||||
/* Make the basetype circular so we can always ask for it */
|
||||
sym->typ.basetype = sym;
|
||||
sym->prefix = listnew();
|
||||
return sym;
|
||||
}
|
||||
|
926
ncgen/ncgentab.c
926
ncgen/ncgentab.c
File diff suppressed because it is too large
Load Diff
@ -439,12 +439,12 @@ makebytestring(char* s, size_t* lenp)
|
||||
{
|
||||
unsigned char* bytes;
|
||||
unsigned char* b;
|
||||
size_t slen = strlen(s);
|
||||
size_t blen = slen/2;
|
||||
size_t slen = strlen(s); /* # nibbles */
|
||||
size_t blen = slen/2; /* # bytes */
|
||||
int i;
|
||||
|
||||
ASSERT((slen%2) == 0);
|
||||
ASSERT(blen > 0);
|
||||
ASSERT(blen > 0);
|
||||
bytes = (unsigned char*)emalloc(blen);
|
||||
b = bytes;
|
||||
for(i=0;i<slen;i+=2) {
|
||||
|
Loading…
Reference in New Issue
Block a user