Coverage Report

Created: 2023-05-28 06:42

/src/netcdf-c/libnczarr/zcvt.c
Line
Count
Source (jump to first uncovered line)
1
/*********************************************************************
2
 *   Copyright 2018, UCAR/Unidata
3
 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4
 *********************************************************************/
5
6
#include "zincludes.h"
7
#include <math.h>
8
#ifdef _MSC_VER
9
#include <crtdbg.h>
10
#endif
11
12
#include "isnan.h"
13
14
/*
15
Code taken directly from libdap4/d4cvt.c
16
*/
17
18
static const int ncz_type_size[NC_MAX_ATOMIC_TYPE+1] = {
19
0, /*NC_NAT*/
20
sizeof(char), /*NC_BYTE*/
21
sizeof(char), /*NC_CHAR*/
22
sizeof(short), /*NC_SHORT*/
23
sizeof(int), /*NC_INT*/
24
sizeof(float), /*NC_FLOAT*/
25
sizeof(double), /*NC_DOUBLE*/
26
sizeof(unsigned char), /*NC_UBYTE*/
27
sizeof(unsigned short), /*NC_USHORT*/
28
sizeof(unsigned int), /*NC_UINT*/
29
sizeof(long long), /*NC_INT64*/
30
sizeof(unsigned long long), /*NC_UINT64*/
31
sizeof(char *), /*NC_STRING*/
32
};
33
34
/* Forward */
35
static int typeid2jtype(nc_type typeid);
36
static int naninftest(const char* s, double* dcase, float* fcase);
37
38
#if 0
39
/* Convert a JSON value to a struct ZCVT value and also return the type */
40
int
41
NCZ_string2cvt(char* src, nc_type srctype, struct ZCVT* zcvt, nc_type* typeidp)
42
{
43
    int stat = NC_NOERR;
44
    nc_type dsttype = NC_NAT;
45
46
    assert(zcvt);
47
    
48
    /* Convert to a restricted set of values */
49
    switch (srctype) {
50
    case NC_BYTE: {
51
  zcvt->int64v = (signed long long)(*((signed char*)src));
52
  dsttype = NC_INT64;
53
  } break;
54
    case NC_UBYTE: {
55
  zcvt->uint64v = (unsigned long long)(*((unsigned char*)src));
56
  dsttype = NC_UINT64;
57
  } break;
58
    case NC_SHORT: {
59
  zcvt->int64v = (signed long long)(*((signed short*)src));
60
  dsttype = NC_INT64;
61
  } break;
62
    case NC_USHORT: {
63
  zcvt->uint64v = (unsigned long long)(*((unsigned short*)src));
64
  dsttype = NC_UINT64;
65
  } break;
66
    case NC_INT: {
67
  zcvt->int64v = (signed long long)(*((signed int*)src));
68
  dsttype = NC_INT64;
69
  } break;
70
    case NC_UINT: {
71
  zcvt->uint64v = (unsigned long long)(*((unsigned int*)src));
72
  dsttype = NC_UINT64;
73
  } break;
74
    case NC_INT64: {
75
  zcvt->int64v = (signed long long)(*((signed long long*)src));
76
  dsttype = NC_INT64;
77
  } break;
78
    case NC_UINT64: {
79
  zcvt->uint64v = (unsigned long long)(*((unsigned long long*)src));
80
  dsttype = NC_UINT64;
81
  } break;
82
    case NC_FLOAT: {
83
  zcvt->float64v = (double)(*((float*)src));
84
  dsttype = NC_DOUBLE;
85
  } break;
86
    case NC_DOUBLE: {
87
  dsttype = NC_DOUBLE;
88
  zcvt->float64v= (double)(*((double*)src));
89
  } break;
90
    case NC_STRING: {
91
  dsttype = NC_STRING;
92
  zcvt->strv= *((char**)src);
93
  } break;
94
    default: stat = NC_EINTERNAL; goto done;
95
    }
96
    if(typeidp) *typeidp = dsttype;
97
done:
98
    return stat;
99
}
100
#endif
101
102
/* Warning: not free returned zcvt.strv; it may point into a string in jsrc */
103
int
104
NCZ_json2cvt(NCjson* jsrc, struct ZCVT* zcvt, nc_type* typeidp)
105
0
{
106
0
    int stat = NC_NOERR;
107
0
    nc_type srctype = NC_NAT;
108
0
    double naninf;
109
0
    float naninff;
110
    
111
    /* Convert the incoming jsrc to a restricted set of values */
112
0
    switch (NCJsort(jsrc)) {
113
0
    case NCJ_INT: /* convert to (u)int64 */
114
0
  if(NCJstring(jsrc)[0] == '-') {
115
0
      if(sscanf(NCJstring(jsrc),"%lld",&zcvt->int64v) != 1)
116
0
    {stat = NC_EINVAL; goto done;}
117
0
      srctype = NC_INT64;
118
0
  } else {
119
0
      if(sscanf(NCJstring(jsrc),"%llu",&zcvt->uint64v) != 1)
120
0
    {stat = NC_EINVAL; goto done;}
121
0
      srctype = NC_UINT64;
122
0
  }
123
0
  break;
124
0
    case NCJ_DOUBLE:
125
0
  switch (naninftest(NCJstring(jsrc),&naninf,&naninff)) {
126
0
  case NC_NAT:
127
0
      if(sscanf(NCJstring(jsrc),"%lg",&zcvt->float64v) != 1)
128
0
          {stat = NC_EINVAL; goto done;}
129
0
      break;
130
0
  default:
131
0
      zcvt->float64v = naninf;
132
0
      break;
133
0
  }
134
0
  srctype = NC_DOUBLE;
135
0
  break;
136
0
    case NCJ_BOOLEAN:
137
0
  srctype = NC_UINT64;
138
0
  if(strcasecmp(NCJstring(jsrc),"false")==0)
139
0
      zcvt->uint64v = 0;
140
0
  else
141
0
      zcvt->uint64v = 1;
142
0
  break;
143
0
    case NCJ_STRING:
144
0
  srctype = NC_STRING;
145
0
  zcvt->strv = NCJstring(jsrc);
146
0
  break;
147
0
    default: stat = NC_EINTERNAL; goto done;
148
0
    }
149
150
0
    if(typeidp) *typeidp = srctype;
151
0
done:
152
0
    return stat;
153
0
}
154
155
/* Convert a singleton NCjson value to a memory equivalent value of specified dsttype; */
156
int
157
NCZ_convert1(NCjson* jsrc, nc_type dsttype, NCbytes* buf)
158
0
{
159
0
    int stat = NC_NOERR;
160
0
    nc_type srctype;
161
0
    struct ZCVT zcvt = zcvt_empty;
162
0
    int outofrange = 0;
163
0
    size_t len = 0;
164
0
    double naninf;
165
0
    float naninff;
166
167
0
    assert(dsttype != NC_NAT && dsttype <= NC_MAX_ATOMIC_TYPE && buf);
168
169
0
    switch (NCJsort(jsrc)) {
170
0
    case NCJ_STRING: case NCJ_INT: case NCJ_DOUBLE: case NCJ_BOOLEAN:
171
0
        if((stat = NCZ_json2cvt(jsrc,&zcvt,&srctype))) goto done;
172
0
  break;
173
0
    default: stat = NC_EINVAL; goto done; /* Illegal JSON */
174
0
    }
175
176
0
    len = ncz_type_size[dsttype]; /* may change later */
177
178
    /* Now, do the down conversion */
179
0
    switch (dsttype) {
180
0
    case NC_BYTE: {
181
0
        signed char c = 0;
182
0
  switch (srctype) {
183
0
  case NC_DOUBLE:
184
0
      zcvt.int64v = (long long)zcvt.float64v; /* Convert to int64 */
185
      /* fall thru */
186
0
  case NC_INT64:
187
0
      if(zcvt.int64v < NC_MIN_BYTE || zcvt.int64v > NC_MAX_BYTE) outofrange = 1;
188
0
      c = (signed char)zcvt.int64v;
189
0
      ncbytesappend(buf,(char)c);
190
0
      break;
191
0
  case NC_UINT64:
192
0
      if(zcvt.uint64v > NC_MAX_BYTE) outofrange = 1;
193
0
      c = (signed char)zcvt.uint64v;
194
0
      ncbytesappend(buf,(char)c);
195
0
      break;
196
0
  default: abort();
197
0
  }
198
0
  } break;
199
0
    case NC_UBYTE: {
200
0
  unsigned char c = 0;
201
0
  switch (srctype) {
202
0
  case NC_DOUBLE:
203
0
      zcvt.int64v = (long long)zcvt.float64v; /* Convert to int64 */
204
      /* fall thru */
205
0
  case NC_INT64:
206
0
      if(zcvt.int64v < 0 || zcvt.int64v > NC_MAX_BYTE) outofrange = 1;
207
0
      c = (unsigned char)zcvt.int64v;
208
0
      ncbytesappend(buf,(char)c);
209
0
      break;
210
0
  case NC_UINT64:
211
0
      if(zcvt.uint64v > NC_MAX_UBYTE) outofrange = 1;
212
0
      c = (unsigned char)zcvt.uint64v;
213
0
      ncbytesappend(buf,(char)c);
214
0
      break;
215
0
  default: abort();
216
0
  }
217
0
  } break;
218
0
    case NC_SHORT: {
219
0
  signed short s = 0;
220
0
  switch (srctype) {
221
0
  case NC_DOUBLE:
222
0
      zcvt.int64v = (long long)zcvt.float64v; /* Convert to int64 */
223
      /* fall thru */
224
0
  case NC_INT64:
225
0
      if(zcvt.int64v < NC_MIN_SHORT || zcvt.int64v > NC_MAX_SHORT) outofrange = 1;
226
0
      s = (signed short)zcvt.int64v;
227
0
      ncbytesappendn(buf,(char*)&s,sizeof(s));
228
0
      break;
229
0
  case NC_UINT64:
230
0
      if(zcvt.uint64v > NC_MAX_SHORT) outofrange = 1;
231
0
      s = (signed short)zcvt.uint64v;
232
0
      ncbytesappendn(buf,(char*)&s,sizeof(s));
233
0
      break;
234
0
  default: abort();
235
0
  }
236
0
  } break;
237
0
    case NC_USHORT: {
238
0
  unsigned short s = 0;
239
0
  switch (srctype) {
240
0
  case NC_DOUBLE:
241
0
      zcvt.int64v = (long long)zcvt.float64v; /* Convert to int64 */
242
      /* fall thru */
243
0
  case NC_INT64:
244
0
      if(zcvt.int64v < 0 || zcvt.int64v > NC_MAX_USHORT) outofrange = 1;
245
0
      s = (unsigned short)zcvt.int64v;
246
0
      ncbytesappendn(buf,(char*)&s,sizeof(s));
247
0
      break;
248
0
  case NC_UINT64:
249
0
      if(zcvt.uint64v > NC_MAX_USHORT) outofrange = 1;
250
0
      s = (unsigned short)zcvt.uint64v;
251
0
      ncbytesappendn(buf,(char*)&s,sizeof(s));
252
0
      break;
253
0
  default: abort();
254
0
  }
255
0
  } break;
256
0
    case NC_INT: {
257
0
  signed int ii = 0;
258
0
  switch (srctype) {
259
0
  case NC_DOUBLE:
260
0
      zcvt.int64v = (long long)zcvt.float64v; /* Convert to int64 */
261
      /* fall thru */
262
0
  case NC_INT64:
263
0
      if(zcvt.int64v < NC_MIN_INT || zcvt.int64v > NC_MAX_INT) outofrange = 1;
264
0
      ii = (signed int)zcvt.int64v;
265
0
      ncbytesappendn(buf,(char*)&ii,sizeof(ii));
266
0
      break;
267
0
  case NC_UINT64:
268
0
      if(zcvt.uint64v > NC_MAX_INT) outofrange = 1;
269
0
      ii = (signed int)zcvt.uint64v;
270
0
      ncbytesappendn(buf,(char*)&ii,sizeof(ii));
271
0
      break;
272
0
  default: abort();
273
0
  }
274
0
  } break;
275
0
    case NC_UINT: {
276
0
  unsigned int ii = 0;
277
0
  switch (srctype) {
278
0
  case NC_DOUBLE:
279
0
      zcvt.int64v = (long long)zcvt.float64v; /* Convert to int64 */
280
      /* fall thru */
281
0
  case NC_INT64:
282
0
      if(zcvt.int64v < 0 || zcvt.int64v > NC_MAX_UINT) outofrange = 1;
283
0
      ii = (unsigned int)zcvt.int64v;
284
0
      ncbytesappendn(buf,(char*)&ii,sizeof(ii));
285
0
      break;
286
0
  case NC_UINT64:
287
0
      if(zcvt.uint64v > NC_MAX_UINT) outofrange = 1;
288
0
      ii = (unsigned int)zcvt.uint64v;
289
0
      ncbytesappendn(buf,(char*)&ii,sizeof(ii));
290
0
      break;
291
0
  default: abort();
292
0
  }
293
0
  } break;
294
0
    case NC_INT64: {
295
0
  signed long long ll = 0;
296
0
  switch (srctype) {
297
0
  case NC_DOUBLE:
298
0
      zcvt.int64v = (long long)zcvt.float64v; /* Convert to int64 */
299
      /* fall thru */
300
0
  case NC_INT64:
301
0
      ll = (signed long long)zcvt.int64v;
302
0
      ncbytesappendn(buf,(char*)&ll,sizeof(ll));
303
0
      break;
304
0
  case NC_UINT64:
305
0
      if(zcvt.uint64v > NC_MAX_INT64) outofrange = 1;
306
0
      ll = (signed long long)zcvt.uint64v;
307
0
      ncbytesappendn(buf,(char*)&ll,sizeof(ll));
308
0
      break;
309
0
  default: abort();
310
0
  }
311
0
  } break;
312
0
    case NC_UINT64: {
313
0
  unsigned long long ll = 0;
314
0
  switch (srctype) {
315
0
  case NC_DOUBLE:
316
0
      zcvt.int64v = (signed long long)zcvt.float64v;
317
      /* fall thru */
318
0
  case NC_INT64:
319
0
      if(zcvt.int64v < 0) outofrange = 1;
320
0
      ll = (unsigned long long)zcvt.int64v;
321
0
      ncbytesappendn(buf,(char*)&ll,sizeof(ll));
322
0
      break;
323
0
  case NC_UINT64:
324
0
      ll = (unsigned long long)zcvt.uint64v;
325
0
      ncbytesappendn(buf,(char*)&ll,sizeof(ll));
326
0
      break;
327
0
  default: abort();
328
0
  }
329
0
  } break;
330
0
    case NC_FLOAT: {
331
0
  float f = 0;
332
0
  switch (srctype) {
333
0
  case NC_DOUBLE:
334
0
      f = (float)zcvt.float64v;
335
0
      break;
336
0
  case NC_INT64:
337
0
      f = (float)zcvt.int64v;
338
0
      break;
339
0
  case NC_UINT64:
340
0
      f = (float)zcvt.uint64v;
341
0
      break;
342
0
  case NC_STRING: /* Detect special constants encoded as strings e.g. "Nan" */
343
0
      switch (naninftest(zcvt.strv,&naninf,&naninff)) {
344
0
      case NC_NAT: abort();
345
0
          case NC_FLOAT:
346
0
            case NC_DOUBLE:
347
0
          f = naninff; break;
348
0
    break;
349
0
      }
350
0
      break;
351
0
  default: abort();
352
0
  }
353
0
        ncbytesappendn(buf,(char*)&f,sizeof(f));
354
0
  } break;
355
0
    case NC_DOUBLE: {
356
0
  double d = 0;
357
0
  switch (srctype) {
358
0
  case NC_DOUBLE:
359
0
      d = (double)zcvt.float64v;
360
0
      break;
361
0
  case NC_INT64:
362
0
      d = (double)zcvt.int64v;
363
0
      break;
364
0
      case NC_UINT64:
365
0
      d = (double)zcvt.uint64v;
366
0
      break;
367
0
  case NC_STRING: /* NaN might be quoted */
368
0
      switch (naninftest(zcvt.strv,&naninf,&naninff)) {
369
0
      case NC_NAT: abort();
370
0
          case NC_FLOAT:
371
0
            case NC_DOUBLE:
372
0
          d = naninf; break;
373
0
    break;
374
0
      }
375
0
      break;
376
0
  default: abort();
377
0
  }
378
0
        ncbytesappendn(buf,(char*)&d,sizeof(d));
379
0
  } break;
380
0
    case NC_STRING: {
381
0
  char* scopy = NULL;
382
0
  if(srctype != NC_STRING) {stat = NC_EINVAL; goto done;}
383
  /* Need to append the pointer and not what it points to */
384
0
  scopy = nulldup(zcvt.strv);
385
0
  ncbytesappendn(buf,(void*)&scopy,sizeof(scopy));
386
0
  scopy = NULL;
387
0
  } break;
388
0
    case NC_CHAR: {
389
0
  char digits[64];
390
0
  switch (srctype) {
391
0
  case NC_DOUBLE:
392
0
      snprintf(digits,sizeof(digits),"%lf",(double)zcvt.float64v);
393
0
      ncbytesappendn(buf,digits,strlen(digits));
394
0
      break;
395
0
  case NC_INT64:
396
0
      snprintf(digits,sizeof(digits),"%lli",(long long)zcvt.int64v);
397
0
      ncbytesappendn(buf,digits,strlen(digits));
398
0
      case NC_UINT64:
399
0
      snprintf(digits,sizeof(digits),"%lli",(unsigned long long)zcvt.uint64v);
400
0
      ncbytesappendn(buf,digits,strlen(digits));
401
0
      break;
402
0
  case NC_STRING: 
403
0
      len = strlen(zcvt.strv);
404
0
      ncbytesappendn(buf,zcvt.strv,len);
405
0
  default: abort();
406
0
  } 
407
0
  } break;
408
0
    default: stat = NC_EINTERNAL; goto done;
409
0
    }
410
411
0
done:
412
0
    if(stat == NC_NOERR && outofrange) stat = NC_ERANGE;
413
0
    return stat;
414
0
}
415
416
/* Convert a memory value to a JSON string value */
417
int
418
NCZ_stringconvert1(nc_type srctype, char* src, NCjson* jvalue)
419
0
{
420
0
    int stat = NC_NOERR;
421
0
    struct ZCVT zcvt;
422
0
    nc_type dsttype = NC_NAT;
423
0
    char s[1024];
424
0
    char sq[1024+2+1];
425
0
    char* p = NULL;
426
0
    int isnanorinf = 0;
427
428
0
    assert(srctype >= NC_NAT && srctype != NC_CHAR && srctype <= NC_STRING);    
429
    /* Convert to a restricted set of values */
430
0
    switch (srctype) {
431
0
    case NC_BYTE: {
432
0
  zcvt.int64v = (signed long long)(*((signed char*)src));
433
0
  dsttype = NC_INT64;
434
0
  } break;
435
0
    case NC_UBYTE: {
436
0
  zcvt.uint64v = (unsigned long long)(*((unsigned char*)src));
437
0
  dsttype = NC_UINT64;
438
0
  } break;
439
0
    case NC_SHORT: {
440
0
  zcvt.int64v = (signed long long)(*((signed short*)src));
441
0
  dsttype = NC_INT64;
442
0
  } break;
443
0
    case NC_USHORT: {
444
0
  zcvt.uint64v = (unsigned long long)(*((unsigned short*)src));
445
0
  dsttype = NC_UINT64;
446
0
  } break;
447
0
    case NC_INT: {
448
0
  zcvt.int64v = (signed long long)(*((signed int*)src));
449
0
  dsttype = NC_INT64;
450
0
  } break;
451
0
    case NC_UINT: {
452
0
  zcvt.uint64v = (unsigned long long)(*((unsigned int*)src));
453
0
  dsttype = NC_UINT64;
454
0
  } break;
455
0
    case NC_INT64: {
456
0
  zcvt.int64v = (signed long long)(*((signed long long*)src));
457
0
  dsttype = NC_INT64;
458
0
  } break;
459
0
    case NC_UINT64: {
460
0
  zcvt.uint64v = (unsigned long long)(*((unsigned long long*)src));
461
0
  dsttype = NC_UINT64;
462
0
  } break;
463
0
    case NC_FLOAT: {
464
0
  zcvt.float64v = (double)(*((float*)src));
465
0
  dsttype = NC_DOUBLE;
466
0
  } break;
467
0
    case NC_DOUBLE: {
468
0
  dsttype = NC_DOUBLE;
469
0
  zcvt.float64v= (double)(*((double*)src));
470
0
  } break;
471
0
    case NC_STRING: {
472
0
  dsttype = NC_STRING;
473
0
  zcvt.strv= *((char**)src);
474
0
  } break;
475
0
    default: stat = NC_EINTERNAL; goto done;
476
0
    }
477
478
    /* Convert from restricted set of values to standardized string form*/
479
0
    switch (dsttype) {
480
0
    case NC_INT64: {
481
0
  snprintf(s,sizeof(s),"%lld",zcvt.int64v);
482
0
  } break;
483
0
    case NC_UINT64: {
484
0
  snprintf(s,sizeof(s),"%llu",zcvt.uint64v);
485
0
  } break;
486
0
    case NC_DOUBLE: {
487
#ifdef _MSC_VER
488
  switch (_fpclass(zcvt.float64v)) {
489
  case _FPCLASS_SNAN: case _FPCLASS_QNAN:
490
       strcpy(s,"NaN"); isnanorinf = 1; break;
491
  case _FPCLASS_NINF:
492
       strcpy(s,"-Infinity"); isnanorinf = 1; break;
493
  case _FPCLASS_PINF:
494
       strcpy(s,"Infinity"); isnanorinf = 1; break;
495
  default:
496
        snprintf(s,sizeof(s),"%lg",zcvt.float64v); /* handles NAN? */
497
        break;
498
  }
499
#else
500
0
  if(isnan(zcvt.float64v))
501
0
       {strcpy(s,"NaN"); isnanorinf = 1;}
502
0
  else if(isinf(zcvt.float64v) && zcvt.float64v < 0)
503
0
       {strcpy(s,"-Infinity"); isnanorinf = 1;}
504
0
  else if(isinf(zcvt.float64v) && zcvt.float64v > 0)
505
0
       {strcpy(s,"Infinity"); isnanorinf = 1;}
506
0
  else {
507
0
             snprintf(s,sizeof(s),"%lg",zcvt.float64v); /* handles NAN? */
508
0
  }
509
0
#endif
510
  /* Quote the nan/inf constant */
511
0
  if(isnanorinf) {
512
0
      size_t l = strlen(s);
513
0
      memcpy(sq,s,l+1);
514
0
      s[0] = '"';
515
0
      memcpy(s+1,sq,l);
516
0
      s[l+1] = '"';
517
0
          s[l+2] = '\0';
518
0
  }
519
0
  } break;
520
0
    case NC_STRING: {
521
0
  p = nulldup(zcvt.strv);
522
0
        } break;
523
0
    default: stat = NC_EINTERNAL; goto done;
524
0
    }
525
0
    if(p == NULL)
526
0
  p = strdup(s);
527
0
    NCJsetstring(jvalue,p);
528
0
    p = NULL;
529
0
done:
530
0
    nullfree(p);
531
0
    return stat;
532
0
}
533
534
/* Convert arbitrary netcdf attribute vector to equivalent JSON */
535
int
536
NCZ_stringconvert(nc_type typeid, size_t len, void* data0, NCjson** jdatap)
537
0
{
538
0
    int stat = NC_NOERR;
539
0
    int i;
540
0
    char* src = data0; /* so we can do arithmetic on it */
541
0
    size_t typelen;
542
0
    char* str = NULL;
543
0
    NCjson* jvalue = NULL;
544
0
    NCjson* jdata = NULL;
545
0
    int jtype = NCJ_UNDEF;
546
547
0
    jtype = typeid2jtype(typeid);
548
549
0
    if((stat = NC4_inq_atomic_type(typeid, NULL, &typelen)))
550
0
  goto done;
551
552
    /* Handle char type specially */
553
0
    if(typeid == NC_CHAR) {
554
  /* Apply the JSON write convention */
555
0
        if((stat = NCJparsen(len,src,0,&jdata))) { /* !parseable */
556
        /* Create a string valued json object */
557
0
      if((stat = NCJnewstringn(NCJ_STRING,len,src,&jdata))) goto done;
558
0
  }
559
0
    } else if(len == 1) { /* create singleton */
560
0
  if((stat = NCJnew(jtype,&jdata))) goto done;
561
0
        if((stat = NCZ_stringconvert1(typeid, src, jdata))) goto done;
562
0
    } else { /* len > 1 create array of values */
563
0
  if((stat = NCJnew(NCJ_ARRAY,&jdata))) goto done;
564
0
  for(i=0;i<len;i++) {
565
0
      if((stat = NCJnew(jtype,&jvalue))) goto done;
566
0
      if((stat = NCZ_stringconvert1(typeid, src, jvalue))) goto done;
567
0
      NCJappend(jdata,jvalue);
568
0
      jvalue = NULL;
569
0
      src += typelen;
570
0
  }
571
0
    }
572
0
    if(jdatap) {*jdatap = jdata; jdata = NULL;}
573
574
0
done:
575
0
    nullfree(str);
576
0
    NCJreclaim(jvalue);
577
0
    NCJreclaim(jdata);
578
0
    return stat;
579
0
}
580
581
static int
582
typeid2jtype(nc_type typeid)
583
0
{
584
0
    switch (typeid) {
585
0
    case NC_BYTE: case NC_SHORT: case NC_INT: case NC_INT64:
586
0
    case NC_UBYTE: case NC_USHORT: case NC_UINT: case NC_UINT64:
587
0
  return NCJ_INT;
588
0
    case NC_FLOAT:
589
0
    case NC_DOUBLE:
590
0
  return NCJ_DOUBLE;
591
0
    case NC_CHAR:
592
0
    case NC_STRING:
593
0
  return NCJ_STRING;
594
0
    default: break;
595
0
    }
596
0
    return NCJ_UNDEF;
597
0
}
598
599
/* Test for Nan(f) and Inf(f)
600
   return 0 if not nan or inf
601
   return NC_FLOAT if nanf or inff
602
   return NC_DOUBLE if nan or inf
603
   Always fill in both double and float cases so caller can choose
604
*/
605
static int
606
naninftest(const char* s, double* dcase, float* fcase)
607
0
{
608
0
    nc_type nctype= NC_NAT;
609
0
    assert(dcase && fcase);
610
0
    if(strcasecmp(s,"nan")==0) {
611
0
  *dcase = NAN; *fcase = NANF;
612
0
  nctype = NC_DOUBLE;
613
0
    } else if(strcasecmp(s,"-nan")==0) {
614
0
  *dcase = (- NAN); *fcase = (- NANF);
615
0
  nctype = NC_DOUBLE;
616
0
    } else if(strcasecmp(s,"nanf")==0) {
617
0
  *dcase = NAN; *fcase = NANF;
618
0
  nctype = NC_FLOAT;
619
0
    } else if(strcasecmp(s,"-nan")==0) {
620
0
  *dcase = (- NAN); *fcase = (- NANF);
621
0
  nctype = NC_FLOAT;
622
0
    } else if(strcasecmp(s,"infinity")==0) {
623
0
  *dcase = INFINITY; *fcase = INFINITYF;
624
0
  nctype = NC_DOUBLE;
625
0
    } else if(strcasecmp(s,"-infinity")==0) {
626
0
  *dcase = (- INFINITY); *fcase = (- INFINITYF);
627
0
  nctype = NC_DOUBLE;
628
0
    } else if(strcasecmp(s,"infinityf")==0) {
629
0
  *dcase = INFINITY; *fcase = INFINITYF;
630
0
  nctype = NC_FLOAT;
631
0
    } else if(strcasecmp(s,"-infinityf")==0) {
632
0
  *dcase = (- INFINITY); *fcase = (- INFINITYF);
633
0
  nctype = NC_FLOAT;
634
0
    }    
635
0
    return nctype;
636
0
}