src/json.c

changeset 1060
0a7c1bb2372d
parent 1057
4e8436c3e806
equal deleted inserted replaced
1059:154eb64ce746 1060:0a7c1bb2372d
287 result.ptr[result.length] = 0; 287 result.ptr[result.length] = 0;
288 288
289 return result; 289 return result;
290 } 290 }
291 291
292 static int parse_number(cxmutstr str, void *value, bool asint) {
293 char *endptr = NULL;
294 if (str.length > 30) {
295 return 1;
296 }
297 // the buffer guarantees that we are working on a copied string
298 char c = str.ptr[str.length];
299 str.ptr[str.length] = 0;
300
301 if (asint) {
302 errno = 0;
303 long long v = strtoll(str.ptr, &endptr, 10);
304 if (errno == ERANGE) {
305 return 1;
306 }
307 *((int64_t*)value) = (int64_t) v;
308 } else {
309 // TODO: proper JSON spec number parser
310 // TODO: also return an error when loss of precision is high
311 double v = strtod(str.ptr, &endptr);
312 *((double*)value) = v;
313 }
314
315 // recover from the hack
316 str.ptr[str.length] = c;
317
318 return endptr != &str.ptr[str.length];
319 }
320
321 static CxJsonValue* create_json_value(CxJson *json, CxJsonValueType type) { 292 static CxJsonValue* create_json_value(CxJson *json, CxJsonValueType type) {
322 CxJsonValue *v = cxMalloc(json->allocator, sizeof(CxJsonValue)); 293 CxJsonValue *v = cxMalloc(json->allocator, sizeof(CxJsonValue));
323 if (v == NULL) { 294 if (v == NULL) {
324 return NULL; 295 return NULL;
325 } 296 }
398 json->states[0] = JP_STATE_VALUE_BEGIN; 369 json->states[0] = JP_STATE_VALUE_BEGIN;
399 json->states_size = 1; 370 json->states_size = 1;
400 371
401 json->vbuf = json->vbuf_internal; 372 json->vbuf = json->vbuf_internal;
402 json->vbuf_capacity = cx_nmemb(json->vbuf_internal); 373 json->vbuf_capacity = cx_nmemb(json->vbuf_internal);
403
404 cxBufferInit(&json->buffer, NULL, 256, NULL, CX_BUFFER_AUTO_EXTEND);
405 } 374 }
406 375
407 void cxJsonDestroy(CxJson *json) { 376 void cxJsonDestroy(CxJson *json) {
408 cxBufferDestroy(&json->buffer); 377 cxBufferDestroy(&json->buffer);
409 if (json->states != json->states_internal) { 378 if (json->states != json->states_internal) {
415 cxJsonValueFree(json->parsed); 384 cxJsonValueFree(json->parsed);
416 json->parsed = NULL; 385 json->parsed = NULL;
417 } 386 }
418 387
419 int cxJsonFilln(CxJson *json, const char *buf, size_t size) { 388 int cxJsonFilln(CxJson *json, const char *buf, size_t size) {
420 // we use the UCX buffer to write the data 389 if (cxBufferEof(&json->buffer)) {
421 // but reset the position immediately to enable parsing 390 // reinitialize the buffer
422 size_t old_pos = json->buffer.pos; 391 cxBufferDestroy(&json->buffer);
423 cxBufferSeek(&json->buffer, 0, SEEK_END); 392 cxBufferInit(&json->buffer, (char*) buf, size,
424 size_t written = cxBufferWrite(buf, 1, size, &json->buffer); 393 NULL, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_COPY_ON_WRITE);
425 if (0 == cxBufferTerminate(&json->buffer)) { 394 json->buffer.size = size;
426 written++; 395 return 0;
427 } 396 } else {
428 json->buffer.pos = old_pos; 397 return size != cxBufferAppend(buf, 1, size, &json->buffer);
429 return written != size + 1; 398 }
430 } 399 }
431 400
432 static void json_add_state(CxJson *json, int state) { 401 static void json_add_state(CxJson *json, int state) {
433 // we have guaranteed the necessary space with cx_array_simple_reserve() 402 // we have guaranteed the necessary space with cx_array_simple_reserve()
434 // therefore, we can safely add the state in the simplest way possible 403 // therefore, we can safely add the state in the simplest way possible
506 case CX_JSON_TOKEN_NUMBER: { 475 case CX_JSON_TOKEN_NUMBER: {
507 int type = token.tokentype == CX_JSON_TOKEN_INTEGER ? CX_JSON_INTEGER : CX_JSON_NUMBER; 476 int type = token.tokentype == CX_JSON_TOKEN_INTEGER ? CX_JSON_INTEGER : CX_JSON_NUMBER;
508 if (NULL == (vbuf = create_json_value(json, type))) { 477 if (NULL == (vbuf = create_json_value(json, type))) {
509 return_rec(CX_JSON_VALUE_ALLOC_FAILED); 478 return_rec(CX_JSON_VALUE_ALLOC_FAILED);
510 } 479 }
511 if (parse_number(token.content, &vbuf->value,type == CX_JSON_INTEGER)) { 480 if (type == CX_JSON_INTEGER) {
512 return_rec(CX_JSON_FORMAT_ERROR_NUMBER); 481 if (cx_strtoi64(token.content, &vbuf->value.integer, 10)) {
482 return_rec(CX_JSON_FORMAT_ERROR_NUMBER);
483 }
484 } else {
485 if (cx_strtod(token.content, &vbuf->value.number)) {
486 return_rec(CX_JSON_FORMAT_ERROR_NUMBER);
487 }
513 } 488 }
514 return_rec(CX_JSON_NO_ERROR); 489 return_rec(CX_JSON_NO_ERROR);
515 } 490 }
516 case CX_JSON_TOKEN_LITERAL: { 491 case CX_JSON_TOKEN_LITERAL: {
517 if ((vbuf = create_json_value(json, CX_JSON_LITERAL)) == NULL) { 492 if ((vbuf = create_json_value(json, CX_JSON_LITERAL)) == NULL) {
598 return_rec(-1); 573 return_rec(-1);
599 } 574 }
600 } 575 }
601 576
602 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value) { 577 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value) {
578 // check if buffer has been filled
579 if (json->buffer.space == NULL) {
580 return CX_JSON_NULL_DATA;
581 }
582
603 // initialize output value 583 // initialize output value
604 *value = &cx_json_value_nothing; 584 *value = &cx_json_value_nothing;
605 585
606 // parse data 586 // parse data
607 CxJsonStatus result; 587 CxJsonStatus result;
608 do { 588 do {
609 result = json_parse(json); 589 result = json_parse(json);
610 cxBufferShiftLeft(&json->buffer, json->buffer.pos);
611 if (result == CX_JSON_NO_ERROR && json->states_size == 1) { 590 if (result == CX_JSON_NO_ERROR && json->states_size == 1) {
612 // final state reached 591 // final state reached
613 assert(json->states[0] == JP_STATE_VALUE_END); 592 assert(json->states[0] == JP_STATE_VALUE_END);
614 assert(json->vbuf_size == 0); 593 assert(json->vbuf_size == 0);
615 594

mercurial