| 299 result.ptr[result.length] = 0; |
299 result.ptr[result.length] = 0; |
| 300 |
300 |
| 301 return result; |
301 return result; |
| 302 } |
302 } |
| 303 |
303 |
| 304 static int parse_integer(const char *str, size_t len, int64_t *value) { |
304 static int parse_number(const char *str, size_t len, void *value, bool asint) { |
| 305 char *endptr = NULL; |
305 char *endptr = NULL; |
| 306 char buf[32]; |
306 char buf[32]; |
| 307 if (len > 30) { |
307 if (len > 30) { |
| 308 return 1; |
308 return 1; |
| 309 } |
309 } |
| |
310 // TODO: if we can guarantee that we are working on a copied string already, we can avoid this memcpy |
| 310 memcpy(buf, str, len); |
311 memcpy(buf, str, len); |
| 311 buf[len] = 0; |
312 buf[len] = 0; |
| 312 |
313 |
| 313 long long v = strtoll(buf, &endptr, 10); |
314 if (asint) { |
| 314 if (endptr != &buf[len]) { |
315 long long v = strtoll(buf, &endptr, 10); |
| 315 return 1; |
316 *((int64_t*)value) = (int64_t) v; |
| 316 } |
317 } else { |
| 317 *value = (int64_t) v; |
318 // TODO: proper JSON spec number parser |
| 318 |
319 double v = strtod(buf, &endptr); |
| 319 return 0; |
320 *((double*)value) = v; |
| 320 } |
321 } |
| 321 |
322 |
| 322 static int parse_number(const char *str, size_t len, double *value) { |
323 return (endptr != &buf[len]); |
| 323 char *endptr = NULL; |
|
| 324 char buf[32]; |
|
| 325 if (len > 30) { |
|
| 326 return 1; |
|
| 327 } |
|
| 328 memcpy(buf, str, len); |
|
| 329 buf[len] = 0; |
|
| 330 |
|
| 331 double v = strtod(buf, &endptr); |
|
| 332 if (endptr != &buf[len]) { |
|
| 333 return 1; |
|
| 334 } |
|
| 335 *value = v; |
|
| 336 |
|
| 337 return 0; |
|
| 338 } |
324 } |
| 339 |
325 |
| 340 static int add_state(CxJson *p, int state) { |
326 static int add_state(CxJson *p, int state) { |
| 341 CxArrayReallocator alloc = cx_array_reallocator(NULL, p->states_internal); |
327 CxArrayReallocator alloc = cx_array_reallocator(NULL, p->states_internal); |
| 342 size_t size = p->nstates + 1; |
328 size_t size = p->nstates + 1; |
| 460 } |
446 } |
| 461 break; |
447 break; |
| 462 } |
448 } |
| 463 case CX_JSON_TOKEN_INTEGER: { |
449 case CX_JSON_TOKEN_INTEGER: { |
| 464 p->reader_type = CX_JSON_READER_INTEGER; |
450 p->reader_type = CX_JSON_READER_INTEGER; |
| 465 int64_t value; |
451 if (parse_number(token.content, token.length, |
| 466 if (parse_integer(token.content, token.length, &value)) { |
452 &p->value_int, true)) { |
| 467 ret = -1; |
453 ret = -1; |
| 468 } else { |
|
| 469 p->value_int = value; |
|
| 470 p->value_double = (double) value; |
|
| 471 } |
454 } |
| 472 break; |
455 break; |
| 473 } |
456 } |
| 474 case CX_JSON_TOKEN_NUMBER: { |
457 case CX_JSON_TOKEN_NUMBER: { |
| 475 p->reader_type = CX_JSON_READER_NUMBER; |
458 p->reader_type = CX_JSON_READER_NUMBER; |
| 476 double value; |
459 if (parse_number(token.content, token.length, |
| 477 if (parse_number(token.content, token.length, &value)) { |
460 &p->value_double, false)) { |
| 478 ret = -1; |
461 ret = -1; |
| 479 } else { |
|
| 480 p->value_double = value; |
|
| 481 p->value_int = (int64_t) value; |
|
| 482 } |
462 } |
| 483 break; |
463 break; |
| 484 } |
464 } |
| 485 case CX_JSON_TOKEN_LITERAL: { |
465 case CX_JSON_TOKEN_LITERAL: { |
| 486 p->reader_type = CX_JSON_READER_LITERAL; |
466 p->reader_type = CX_JSON_READER_LITERAL; |