src/json.c

changeset 996
333155f234c4
parent 976
d9063c14d3fb
equal deleted inserted replaced
995:d3d4f245b843 996:333155f234c4
264 264
265 CxJsonToken ret = {CX_JSON_NO_TOKEN, NULL, 0, 0}; 265 CxJsonToken ret = {CX_JSON_NO_TOKEN, NULL, 0, 0};
266 return ret; 266 return ret;
267 } 267 }
268 268
269 static cxmutstr unescape_string(const char *str, size_t len) { 269 static cxmutstr unescape_string(const CxAllocator *a, const char *str, size_t len) {
270 // TODO: support more escape sequences 270 // TODO: support more escape sequences
271 // we know that the unescaped string will be shorter by at least 2 chars 271 // we know that the unescaped string will be shorter by at least 2 chars
272 cxmutstr result; 272 cxmutstr result;
273 result.length = 0; 273 result.length = 0;
274 result.ptr = malloc(len - 1); 274 result.ptr = cxMalloc(a, len - 1);
275 if (result.ptr == NULL) { 275 if (result.ptr == NULL) {
276 // TODO: check if this actually leads to correct error handling 276 // TODO: check if this actually leads to correct error handling
277 return result; 277 return result;
278 } 278 }
279 279
435 end_elm(p, CX_JSON_READER_ARRAY_END); 435 end_elm(p, CX_JSON_READER_ARRAY_END);
436 break; 436 break;
437 } 437 }
438 case CX_JSON_TOKEN_STRING: { 438 case CX_JSON_TOKEN_STRING: {
439 p->reader_type = CX_JSON_READER_STRING; 439 p->reader_type = CX_JSON_READER_STRING;
440 cxmutstr str = unescape_string(token.content, token.length); 440 cxmutstr str = unescape_string(p->allocator, token.content, token.length);
441 if (str.ptr) { 441 if (str.ptr) {
442 p->value_str = str.ptr; 442 p->value_str = str.ptr;
443 p->value_str_len = str.length; 443 p->value_str_len = str.length;
444 } else { 444 } else {
445 ret = -1; 445 ret = -1;
485 } else { 485 } else {
486 // expect string 486 // expect string
487 if (token.tokentype != CX_JSON_TOKEN_STRING) return -1; 487 if (token.tokentype != CX_JSON_TOKEN_STRING) return -1;
488 488
489 if (p->value_name) free(p->value_name); 489 if (p->value_name) free(p->value_name);
490 cxmutstr valname = unescape_string(token.content, token.length); 490 cxmutstr valname = unescape_string(p->allocator, token.content, token.length);
491 p->value_name = valname.ptr; 491 p->value_name = valname.ptr;
492 p->value_name_len = valname.length; 492 p->value_name_len = valname.length;
493 493
494 // next state 494 // next state
495 p->states[p->nstates] = JP_STATE_OBJ_COLON; 495 p->states[p->nstates] = JP_STATE_OBJ_COLON;
547 547
548 static int add_to_parent(CxJson *p, CxJsonValue *parent, CxJsonValue *v) { 548 static int add_to_parent(CxJson *p, CxJsonValue *parent, CxJsonValue *v) {
549 if (!parent) { 549 if (!parent) {
550 return -1; // shouldn't happen but who knows 550 return -1; // shouldn't happen but who knows
551 } 551 }
552 552
553 CxArrayReallocator reallocator = cx_array_reallocator(p->allocator, NULL);
553 if (parent->type == CX_JSON_OBJECT) { 554 if (parent->type == CX_JSON_OBJECT) {
554 if (!p->value_name || p->value_name_len == 0) { 555 if (!p->value_name || p->value_name_len == 0) {
555 return -1; 556 return -1;
556 } 557 }
557 char *valuename = p->value_name; 558 char *valuename = p->value_name;
559 560
560 CxJsonObjValue newvalue; 561 CxJsonObjValue newvalue;
561 newvalue.name = valuename; 562 newvalue.name = valuename;
562 newvalue.value = v; 563 newvalue.value = v;
563 564
564 return cx_array_simple_add(parent->value.object.values, newvalue); 565 return cx_array_add(
566 &parent->value.object.values,
567 &parent->value.object.values_size,
568 &parent->value.object.values_capacity,
569 sizeof(CxJsonObjValue),
570 &newvalue,
571 &reallocator);
565 } else if (parent->type == CX_JSON_ARRAY) { 572 } else if (parent->type == CX_JSON_ARRAY) {
566 return cx_array_simple_add(parent->value.array.array, v); 573 return cx_array_add(
574 &parent->value.array.array,
575 &parent->value.array.array_size,
576 &parent->value.array.array_capacity,
577 sizeof(CxJsonValue*),
578 &v,
579 &reallocator);
567 } else { 580 } else {
568 return -1; // should also never happen 581 return -1; // should also never happen
569 } 582 }
570 } 583 }
571 584
579 } 592 }
580 p->readvalue_stack[p->readvalue_nelm++] = v; 593 p->readvalue_stack[p->readvalue_nelm++] = v;
581 return 0; 594 return 0;
582 } 595 }
583 596
584 void cxJsonInit(CxJson *json) { 597 void cxJsonInit(const CxAllocator *allocator, CxJson *json) {
598 if (allocator == NULL) {
599 allocator = cxDefaultAllocator;
600 }
601
585 memset(json, 0, sizeof(CxJson)); 602 memset(json, 0, sizeof(CxJson));
603 json->allocator = allocator;
586 json->states = json->states_internal; 604 json->states = json->states_internal;
587 json->states_alloc = cx_nmemb(json->states_internal); 605 json->states_alloc = cx_nmemb(json->states_internal);
588 // TODO: find better way to configure the initial allocation size for arrays and objects 606 // TODO: find better way to configure the initial allocation size for arrays and objects
589 json->reader_array_alloc = 8; 607 json->reader_array_alloc = 8;
590 } 608 }
616 } 634 }
617 635
618 while (p->readvalue_nelm > 0 || !p->read_value) { 636 while (p->readvalue_nelm > 0 || !p->read_value) {
619 if (p->value_ready) { 637 if (p->value_ready) {
620 // value available without another read 638 // value available without another read
621 CxJsonValue *v = calloc(1, sizeof(CxJsonValue)); 639 CxJsonValue *v = cxCalloc(p->allocator, 1, sizeof(CxJsonValue));
622 if (!v) return -1; 640 if (!v) return -1;
641 v->allocator = p->allocator;
623 642
624 if (p->readvalue_nelm > 0) { 643 if (p->readvalue_nelm > 0) {
625 if (add_to_parent(p, p->readvalue_stack[p->readvalue_nelm - 1], v)) { 644 if (add_to_parent(p, p->readvalue_stack[p->readvalue_nelm - 1], v)) {
626 free(v); 645 free(v);
627 return -1; 646 return -1;
702 } 721 }
703 722
704 void cxJsonValueFree(CxJsonValue *value) { 723 void cxJsonValueFree(CxJsonValue *value) {
705 if (value == NULL || value == &cx_json_value_nothing) return; 724 if (value == NULL || value == &cx_json_value_nothing) return;
706 725
707 // TODO: discuss if we should keep freeing the stuff recursively
708 switch (value->type) { 726 switch (value->type) {
709 case CX_JSON_OBJECT: { 727 case CX_JSON_OBJECT: {
710 CxJsonObject obj = value->value.object; 728 CxJsonObject obj = value->value.object;
711 for (size_t i = 0; i < obj.values_size; i++) { 729 for (size_t i = 0; i < obj.values_size; i++) {
712 cxJsonValueFree(obj.values[i].value); 730 cxJsonValueFree(obj.values[i].value);
713 free(obj.values[i].name); 731 cxFree(value->allocator, obj.values[i].name);
714 } 732 }
715 free(obj.values); 733 cxFree(value->allocator, obj.values);
716 break; 734 break;
717 } 735 }
718 case CX_JSON_ARRAY: { 736 case CX_JSON_ARRAY: {
719 CxJsonArray array = value->value.array; 737 CxJsonArray array = value->value.array;
720 for (size_t i = 0; i < array.array_size; i++) { 738 for (size_t i = 0; i < array.array_size; i++) {
721 cxJsonValueFree(array.array[i]); 739 cxJsonValueFree(array.array[i]);
722 } 740 }
723 free(array.array); 741 cxFree(value->allocator, array.array);
724 break; 742 break;
725 } 743 }
726 case CX_JSON_STRING: { 744 case CX_JSON_STRING: {
727 free(value->value.string.ptr); 745 cxFree(value->allocator, value->value.string.ptr);
728 break; 746 break;
729 } 747 }
730 default: { 748 default: {
731 break; 749 break;
732 } 750 }
733 } 751 }
734 free(value); 752 cxFree(value->allocator, value);
735 } 753 }
736 754
737 CxJsonValue *cxJsonArrGet(CxJsonValue *value, size_t index) { 755 CxJsonValue *cxJsonArrGet(CxJsonValue *value, size_t index) {
738 if (index >= value->value.array.array_size) { 756 if (index >= value->value.array.array_size) {
739 return &cx_json_value_nothing; 757 return &cx_json_value_nothing;

mercurial