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; |