Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some problems with PR 2492 #2497

Merged
merged 7 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/run_tests_osx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
name: Run macOS-based netCDF Tests


on: [push,pull_request, workflow_dispatch]
on: [pull_request, workflow_dispatch]

jobs:

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run_tests_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

name: Run Ubuntu/Linux netCDF Tests

on: [push,pull_request, workflow_dispatch]
on: [pull_request, workflow_dispatch]

jobs:

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run_tests_win_mingw.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
name: Run MSYS2, MinGW64-based Tests


on: [push,pull_request, workflow_dispatch]
on: [pull_request, workflow_dispatch]

jobs:

Expand Down
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This file contains a high-level description of this package's evolution. Release

## 4.9.1 - T.B.D.

* [Bug Fix] Fix some errors detected in [PR #2492](https://github.com/Unidata/netcdf-c/pull/2492) . See [Github #2497](https://github.com/Unidata/netcdf-c/pull/2497).
* [Enhancement] Add support for Zarr (fixed length) string type in nczarr. See [Github #2492](https://github.com/Unidata/netcdf-c/pull/2492).
* [Bug Fix] Split the remote tests into two parts: one for the remotetest server and one for all other external servers. Also add a configure option to enable the latter set. See [Github #2491](https://github.com/Unidata/netcdf-c/pull/2491).
* [Bug Fix] Fix support for reading arrays of HDF5 fixed size strings. See [Github #2462](https://github.com/Unidata/netcdf-c/pull/2466).
Expand Down
2 changes: 1 addition & 1 deletion docs/nczarr.md
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ handled by providing the following new attributes:
1. **_nczarr_default_maxstrlen** —
This is an attribute of the root group. It specifies the default
maximum string length for string types. If not specified, then
it has the value of 64 characters.
it has the value of 128 characters.
2. **_nczarr_maxstrlen** —
This is a per-variable attribute. It specifies the maximum
string length for the string type associated with the variable.
Expand Down
12 changes: 6 additions & 6 deletions libdispatch/ncjson.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,13 +467,13 @@ testdouble(const char* word)
double d;
int count = 0;
/* Check for Nan and Infinity */
if(strcasecmp("nan",word)==0) return NCJTHROW(NCJ_OK);
if(strcasecmp("infinity",word)==0) return NCJTHROW(NCJ_OK);
if(strcasecmp("-infinity",word)==0) return NCJTHROW(NCJ_OK);
if(0==(int)strcasecmp("nan",word)) return NCJTHROW(NCJ_OK);
if(0==(int)strcasecmp("infinity",word)) return NCJTHROW(NCJ_OK);
if(0==(int)strcasecmp("-infinity",word)) return NCJTHROW(NCJ_OK);
/* Allow the XXXf versions as well */
if(strcasecmp("nanf",word)==0) return NCJTHROW(NCJ_OK);
if(strcasecmp("infinityf",word)==0) return NCJTHROW(NCJ_OK);
if(strcasecmp("-infinityf",word)==0) return NCJTHROW(NCJ_OK);
if(0==(int)strcasecmp("nanf",word)) return NCJTHROW(NCJ_OK);
if(0==(int)strcasecmp("infinityf",word)) return NCJTHROW(NCJ_OK);
if(0==(int)strcasecmp("-infinityf",word)) return NCJTHROW(NCJ_OK);
/* Try to convert to number */
ncvt = sscanf(word,"%lg%n",&d,&count);
return NCJTHROW((ncvt == 1 && strlen(word)==count ? NCJ_OK : NCJ_ERR));
Expand Down
143 changes: 117 additions & 26 deletions libnczarr/zcvt.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ sizeof(char *), /*NC_STRING*/

/* Forward */
static int typeid2jtype(nc_type typeid);
static int naninftest(const char* s, double* dcase, float* fcase);

#if 0
/* Convert a JSON value to a struct ZCVT value and also return the type */
Expand Down Expand Up @@ -104,6 +105,8 @@ NCZ_json2cvt(NCjson* jsrc, struct ZCVT* zcvt, nc_type* typeidp)
{
int stat = NC_NOERR;
nc_type srctype = NC_NAT;
double naninf;
float naninff;

/* Convert the incoming jsrc to a restricted set of values */
switch (NCJsort(jsrc)) {
Expand All @@ -119,18 +122,14 @@ NCZ_json2cvt(NCjson* jsrc, struct ZCVT* zcvt, nc_type* typeidp)
}
break;
case NCJ_DOUBLE:
/* Capture nan and infinity values */
if(strcasecmp(NCJstring(jsrc),"nan")==0)
zcvt->float64v = NAN;
else if(strcasecmp(NCJstring(jsrc),"-nan")==0)
zcvt->float64v = - NAN;
else if(strcasecmp(NCJstring(jsrc),"infinity")==0)
zcvt->float64v = INFINITY;
else if(strcasecmp(NCJstring(jsrc),"-infinity")==0)
zcvt->float64v = (- INFINITY);
else {
switch (naninftest(NCJstring(jsrc),&naninf,&naninff)) {
case NC_NAT:
if(sscanf(NCJstring(jsrc),"%lg",&zcvt->float64v) != 1)
{stat = NC_EINVAL; goto done;}
break;
default:
zcvt->float64v = naninf;
break;
}
srctype = NC_DOUBLE;
break;
Expand Down Expand Up @@ -162,6 +161,8 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
struct ZCVT zcvt = zcvt_empty;
int outofrange = 0;
size_t len = 0;
double naninf;
float naninff;

assert(dsttype != NC_NAT && dsttype <= NC_MAX_ATOMIC_TYPE && buf);

Expand Down Expand Up @@ -192,6 +193,7 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
c = (signed char)zcvt.uint64v;
ncbytesappend(buf,(char)c);
break;
default: abort();
}
} break;
case NC_UBYTE: {
Expand All @@ -210,6 +212,7 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
c = (unsigned char)zcvt.uint64v;
ncbytesappend(buf,(char)c);
break;
default: abort();
}
} break;
case NC_SHORT: {
Expand All @@ -228,6 +231,7 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
s = (signed short)zcvt.uint64v;
ncbytesappendn(buf,(char*)&s,sizeof(s));
break;
default: abort();
}
} break;
case NC_USHORT: {
Expand All @@ -246,6 +250,7 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
s = (unsigned short)zcvt.uint64v;
ncbytesappendn(buf,(char*)&s,sizeof(s));
break;
default: abort();
}
} break;
case NC_INT: {
Expand All @@ -264,6 +269,7 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
ii = (signed int)zcvt.uint64v;
ncbytesappendn(buf,(char*)&ii,sizeof(ii));
break;
default: abort();
}
} break;
case NC_UINT: {
Expand All @@ -282,6 +288,7 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
ii = (unsigned int)zcvt.uint64v;
ncbytesappendn(buf,(char*)&ii,sizeof(ii));
break;
default: abort();
}
} break;
case NC_INT64: {
Expand All @@ -299,6 +306,7 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
ll = (signed long long)zcvt.uint64v;
ncbytesappendn(buf,(char*)&ll,sizeof(ll));
break;
default: abort();
}
} break;
case NC_UINT64: {
Expand All @@ -316,40 +324,58 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
ll = (unsigned long long)zcvt.uint64v;
ncbytesappendn(buf,(char*)&ll,sizeof(ll));
break;
default: abort();
}
} break;
case NC_FLOAT: {
float f = 0;
switch (srctype) {
case NC_DOUBLE:
f = (float)zcvt.float64v;
ncbytesappendn(buf,(char*)&f,sizeof(f));
break;
case NC_INT64:
f = (float)zcvt.int64v;
ncbytesappendn(buf,(char*)&f,sizeof(f));
break;
case NC_UINT64:
f = (float)zcvt.uint64v;
ncbytesappendn(buf,(char*)&f,sizeof(f));
break;
case NC_STRING: /* Detect special constants encoded as strings e.g. "Nan" */
switch (naninftest(zcvt.strv,&naninf,&naninff)) {
case NC_NAT: abort();
case NC_FLOAT:
case NC_DOUBLE:
f = naninff; break;
break;
}
break;
default: abort();
}
ncbytesappendn(buf,(char*)&f,sizeof(f));
} break;
case NC_DOUBLE: {
double d = 0;
switch (srctype) {
case NC_DOUBLE:
d = (double)zcvt.float64v;
ncbytesappendn(buf,(char*)&d,sizeof(d));
break;
case NC_INT64:
d = (double)zcvt.int64v;
ncbytesappendn(buf,(char*)&d,sizeof(d));
break;
case NC_UINT64:
d = (double)zcvt.uint64v;
ncbytesappendn(buf,(char*)&d,sizeof(d));
break;
case NC_STRING: /* NaN might be quoted */
switch (naninftest(zcvt.strv,&naninf,&naninff)) {
case NC_NAT: abort();
case NC_FLOAT:
case NC_DOUBLE:
d = naninf; break;
break;
}
break;
default: abort();
}
ncbytesappendn(buf,(char*)&d,sizeof(d));
} break;
case NC_STRING: {
char* scopy = NULL;
Expand All @@ -360,10 +386,25 @@ NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
scopy = NULL;
} break;
case NC_CHAR: {
if(srctype != NC_STRING) {stat = NC_EINVAL; goto done;}
len = strlen(zcvt.strv);
ncbytesappendn(buf,zcvt.strv,len);
} break;
char digits[64];
switch (srctype) {
case NC_DOUBLE:
snprintf(digits,sizeof(digits),"%lf",(double)zcvt.float64v);
ncbytesappendn(buf,digits,strlen(digits));
break;
case NC_INT64:
snprintf(digits,sizeof(digits),"%lli",(long long)zcvt.int64v);
ncbytesappendn(buf,digits,strlen(digits));
case NC_UINT64:
snprintf(digits,sizeof(digits),"%lli",(unsigned long long)zcvt.uint64v);
ncbytesappendn(buf,digits,strlen(digits));
break;
case NC_STRING:
len = strlen(zcvt.strv);
ncbytesappendn(buf,zcvt.strv,len);
default: abort();
}
} break;
default: stat = NC_EINTERNAL; goto done;
}

Expand All @@ -380,7 +421,9 @@ NCZ_stringconvert1(nc_type srctype, char* src, NCjson* jvalue)
struct ZCVT zcvt;
nc_type dsttype = NC_NAT;
char s[1024];
char sq[1024+2+1];
char* p = NULL;
int isnanorinf = 0;

assert(srctype >= NC_NAT && srctype != NC_CHAR && srctype <= NC_STRING);
/* Convert to a restricted set of values */
Expand Down Expand Up @@ -444,26 +487,35 @@ NCZ_stringconvert1(nc_type srctype, char* src, NCjson* jvalue)
#ifdef _MSC_VER
switch (_fpclass(zcvt.float64v)) {
case _FPCLASS_SNAN: case _FPCLASS_QNAN:
strcpy(s,"NaN"); break;
strcpy(s,"NaN"); isnanorinf = 1; break;
case _FPCLASS_NINF:
strcpy(s,"-Infinity"); break;
strcpy(s,"-Infinity"); isnanorinf = 1; break;
case _FPCLASS_PINF:
strcpy(s,"Infinity"); break;
strcpy(s,"Infinity"); isnanorinf = 1; break;
default:
snprintf(s,sizeof(s),"%lg",zcvt.float64v); /* handles NAN? */
break;
}
#else
if(isnan(zcvt.float64v))
strcpy(s,"NaN");
{strcpy(s,"NaN"); isnanorinf = 1;}
else if(isinf(zcvt.float64v) && zcvt.float64v < 0)
strcpy(s,"-Infinity");
{strcpy(s,"-Infinity"); isnanorinf = 1;}
else if(isinf(zcvt.float64v) && zcvt.float64v > 0)
strcpy(s,"Infinity");
{strcpy(s,"Infinity"); isnanorinf = 1;}
else {
snprintf(s,sizeof(s),"%lg",zcvt.float64v); /* handles NAN? */
}
#endif
/* Quote the nan/inf constant */
if(isnanorinf) {
size_t l = strlen(s);
memcpy(sq,s,l+1);
s[0] = '"';
memcpy(s+1,sq,l);
s[l+1] = '"';
s[l+2] = '\0';
}
} break;
case NC_STRING: {
p = nulldup(zcvt.strv);
Expand Down Expand Up @@ -543,3 +595,42 @@ typeid2jtype(nc_type typeid)
}
return NCJ_UNDEF;
}

/* Test for Nan(f) and Inf(f)
return 0 if not nan or inf
return NC_FLOAT if nanf or inff
return NC_DOUBLE if nan or inf
Always fill in both double and float cases so caller can choose
*/
static int
naninftest(const char* s, double* dcase, float* fcase)
{
nc_type nctype= NC_NAT;
assert(dcase && fcase);
if(strcasecmp(s,"nan")==0) {
*dcase = NAN; *fcase = NANF;
nctype = NC_DOUBLE;
} else if(strcasecmp(s,"-nan")==0) {
*dcase = (- NAN); *fcase = (- NANF);
nctype = NC_DOUBLE;
} else if(strcasecmp(s,"nanf")==0) {
*dcase = NAN; *fcase = NANF;
nctype = NC_FLOAT;
} else if(strcasecmp(s,"-nan")==0) {
*dcase = (- NAN); *fcase = (- NANF);
nctype = NC_FLOAT;
} else if(strcasecmp(s,"infinity")==0) {
*dcase = INFINITY; *fcase = INFINITYF;
nctype = NC_DOUBLE;
} else if(strcasecmp(s,"-infinity")==0) {
*dcase = (- INFINITY); *fcase = (- INFINITYF);
nctype = NC_DOUBLE;
} else if(strcasecmp(s,"infinityf")==0) {
*dcase = INFINITY; *fcase = INFINITYF;
nctype = NC_FLOAT;
} else if(strcasecmp(s,"-infinityf")==0) {
*dcase = (- INFINITY); *fcase = (- INFINITYF);
nctype = NC_FLOAT;
}
return nctype;
}
2 changes: 1 addition & 1 deletion libnczarr/zinternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Inserted into any .zattrs ? or should it go into the container?
#define DFALT_DIM_SEPARATOR '.'

/* Default max string length for fixed length strings */
#define NCZ_MAXSTR_DEFAULT 64
#define NCZ_MAXSTR_DEFAULT 128

#define islegaldimsep(c) ((c) != '\0' && strchr(LEGAL_DIM_SEPARATORS,(c)) != NULL)

Expand Down
Loading