src/json.c

changeset 1607
0ecb13118cac
parent 1605
55b13f583356
equal deleted inserted replaced
1606:f5883f6e42e7 1607:0ecb13118cac
470 470
471 // initialize the value 471 // initialize the value
472 v->type = type; 472 v->type = type;
473 v->allocator = json->allocator; 473 v->allocator = json->allocator;
474 if (type == CX_JSON_ARRAY) { 474 if (type == CX_JSON_ARRAY) {
475 cx_array_initialize_a(json->allocator, v->array.data, 16); 475 if (cx_array_init_a(json->allocator, v->array, 16)) {
476 if (v->array.data == NULL) goto create_json_value_exit_error; // LCOV_EXCL_LINE 476 goto create_json_value_exit_error; // LCOV_EXCL_LINE
477 }
477 } else if (type == CX_JSON_OBJECT) { 478 } else if (type == CX_JSON_OBJECT) {
478 v->object = json_create_object_map(json->allocator); 479 v->object = json_create_object_map(json->allocator);
479 if (v->object == NULL) goto create_json_value_exit_error; // LCOV_EXCL_LINE 480 if (v->object == NULL) goto create_json_value_exit_error; // LCOV_EXCL_LINE
480 } 481 }
481 482
482 // add the new value to a possible parent 483 // add the new value to a possible parent
483 if (json->vbuf_size > 0) { 484 if (json->vbuf.size > 0) {
484 CxJsonValue *parent = json->vbuf[json->vbuf_size - 1]; 485 CxJsonValue *parent = json->vbuf.data[json->vbuf.size - 1];
485 assert(parent != NULL); 486 assert(parent != NULL);
486 if (parent->type == CX_JSON_ARRAY) { 487 if (parent->type == CX_JSON_ARRAY) {
487 CxArrayReallocator value_realloc = cx_array_reallocator(json->allocator, NULL); 488 if (cx_array_add_a(json->allocator, parent->array, &v)) {
488 if (cx_array_simple_add_a(&value_realloc, parent->array.data, v)) {
489 goto create_json_value_exit_error; // LCOV_EXCL_LINE 489 goto create_json_value_exit_error; // LCOV_EXCL_LINE
490 } 490 }
491 } else if (parent->type == CX_JSON_OBJECT) { 491 } else if (parent->type == CX_JSON_OBJECT) {
492 // the member was already created after parsing the name 492 // the member was already created after parsing the name
493 // store the pointer of the uncompleted value in the map 493 // store the pointer of the uncompleted value in the map
501 } 501 }
502 } 502 }
503 503
504 // add the new value to the stack, if it is an array or object 504 // add the new value to the stack, if it is an array or object
505 if (type == CX_JSON_ARRAY || type == CX_JSON_OBJECT) { 505 if (type == CX_JSON_ARRAY || type == CX_JSON_OBJECT) {
506 CxArrayReallocator vbuf_realloc = cx_array_reallocator(NULL, json->vbuf_internal); 506 if (json->vbuf.size >= json->vbuf.capacity) {
507 if (cx_array_simple_add_a(&vbuf_realloc, json->vbuf, v)) { 507 int alloc_error;
508 goto create_json_value_exit_error; // LCOV_EXCL_LINE 508 if (json->vbuf.data == json->vbuf_internal) {
509 } 509 alloc_error = cx_array_move_to_new(json->vbuf, json->vbuf.size+1);
510 } else {
511 alloc_error = cx_array_reserve(json->vbuf, json->vbuf.size+1);
512 }
513 if (alloc_error) {
514 goto create_json_value_exit_error; // LCOV_EXCL_LINE
515 }
516 }
517 json->vbuf.data[json->vbuf.size] = v;
518 json->vbuf.size++;
510 } 519 }
511 520
512 // if currently no value is parsed, this is now the value of interest 521 // if currently no value is parsed, this is now the value of interest
513 if (json->parsed == NULL) { 522 if (json->parsed == NULL) {
514 json->parsed = v; 523 json->parsed = v;
538 } 547 }
539 548
540 memset(json, 0, sizeof(CxJson)); 549 memset(json, 0, sizeof(CxJson));
541 json->allocator = allocator; 550 json->allocator = allocator;
542 551
543 json->states = json->states_internal; 552 json->states.data = json->states_internal;
544 json->states_capacity = cx_nmemb(json->states_internal); 553 json->states.capacity = cx_nmemb(json->states_internal);
545 json->states[0] = JP_STATE_VALUE_BEGIN; 554 json->states.data[0] = JP_STATE_VALUE_BEGIN;
546 json->states_size = 1; 555 json->states.size = 1;
547 556
548 json->vbuf = json->vbuf_internal; 557 json->vbuf.data = json->vbuf_internal;
549 json->vbuf_capacity = cx_nmemb(json->vbuf_internal); 558 json->vbuf.capacity = cx_nmemb(json->vbuf_internal);
550 } 559 }
551 560
552 void cxJsonDestroy(CxJson *json) { 561 void cxJsonDestroy(CxJson *json) {
553 cxBufferDestroy(&json->buffer); 562 cxBufferDestroy(&json->buffer);
554 if (json->states != json->states_internal) { 563 if (json->states.data != json->states_internal) {
555 cxFreeDefault(json->states); 564 cx_array_free(json->states);
556 } 565 }
557 if (json->vbuf != json->vbuf_internal) { 566 if (json->vbuf.data != json->vbuf_internal) {
558 cxFreeDefault(json->vbuf); 567 cx_array_free(json->vbuf);
559 } 568 }
560 cxJsonValueFree(json->parsed); 569 cxJsonValueFree(json->parsed);
561 json->parsed = NULL; 570 json->parsed = NULL;
562 token_destroy(&json->uncompleted); 571 token_destroy(&json->uncompleted);
563 cx_strfree_a(json->allocator, &json->uncompleted_member_name); 572 cx_strfree_a(json->allocator, &json->uncompleted_member_name);
582 return size != cxBufferAppend(buf, 1, size, &json->buffer); 591 return size != cxBufferAppend(buf, 1, size, &json->buffer);
583 } 592 }
584 } 593 }
585 594
586 static void json_add_state(CxJson *json, int state) { 595 static void json_add_state(CxJson *json, int state) {
587 // we have guaranteed the necessary space with cx_array_simple_reserve() 596 // we have guaranteed the necessary space
588 // therefore, we can safely add the state in the simplest way possible 597 // therefore, we can safely add the state in the simplest way possible
589 json->states[json->states_size++] = state; 598 json->states.data[json->states.size++] = state;
590 } 599 }
591 600
592 #define return_rec(code) \ 601 #define return_rec(code) \
593 token_destroy(&token); \ 602 token_destroy(&token); \
594 return code 603 return code
605 return ret; 614 return ret;
606 } 615 }
607 } 616 }
608 617
609 // pop the current state 618 // pop the current state
610 assert(json->states_size > 0); 619 assert(json->states.size > 0);
611 int state = json->states[--json->states_size]; 620 int state = json->states.data[--json->states.size];
612 621
613 // guarantee that at least two more states fit on the stack 622 // guarantee that at least two more states fit into the array
614 CxArrayReallocator state_realloc = cx_array_reallocator(NULL, json->states_internal); 623 const size_t required_states_depth = json->states.size + 2;
615 if (cx_array_simple_reserve_a(&state_realloc, json->states, 2)) { 624 if (required_states_depth >= json->states.capacity) {
616 return CX_JSON_BUFFER_ALLOC_FAILED; // LCOV_EXCL_LINE 625 int alloc_error;
626 if (json->states.data == json->states_internal) {
627 alloc_error = cx_array_move_to_new(json->states, required_states_depth);
628 } else {
629 alloc_error = cx_array_reserve(json->states, required_states_depth);
630 }
631 if (alloc_error) {
632 return CX_JSON_BUFFER_ALLOC_FAILED; // LCOV_EXCL_LINE
633 }
617 } 634 }
618 635
619 636
620 // 0 JP_STATE_VALUE_BEGIN value begin 637 // 0 JP_STATE_VALUE_BEGIN value begin
621 // 10 JP_STATE_VALUE_END expect value end 638 // 10 JP_STATE_VALUE_END expect value end
646 return_rec(CX_JSON_NO_ERROR); 663 return_rec(CX_JSON_NO_ERROR);
647 } 664 }
648 case CX_JSON_TOKEN_END_ARRAY: { 665 case CX_JSON_TOKEN_END_ARRAY: {
649 if (state == JP_STATE_VALUE_BEGIN_AR) { 666 if (state == JP_STATE_VALUE_BEGIN_AR) {
650 // discard the array from the value buffer 667 // discard the array from the value buffer
651 json->vbuf_size--; 668 json->vbuf.size--;
652 json->states_size--; 669 json->states.size--;
653 return_rec(CX_JSON_NO_ERROR); 670 return_rec(CX_JSON_NO_ERROR);
654 } else { 671 } else {
655 return_rec(CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN); 672 return_rec(CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN);
656 } 673 }
657 } 674 }
706 if (token.tokentype == CX_JSON_TOKEN_VALUE_SEPARATOR) { 723 if (token.tokentype == CX_JSON_TOKEN_VALUE_SEPARATOR) {
707 json_add_state(json, JP_STATE_VALUE_BEGIN_AR); 724 json_add_state(json, JP_STATE_VALUE_BEGIN_AR);
708 return_rec(CX_JSON_NO_ERROR); 725 return_rec(CX_JSON_NO_ERROR);
709 } else if (token.tokentype == CX_JSON_TOKEN_END_ARRAY) { 726 } else if (token.tokentype == CX_JSON_TOKEN_END_ARRAY) {
710 // discard the array from the value buffer 727 // discard the array from the value buffer
711 json->vbuf_size--; 728 json->vbuf.size--;
712 return_rec(CX_JSON_NO_ERROR); 729 return_rec(CX_JSON_NO_ERROR);
713 } else { 730 } else {
714 return_rec(CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN); 731 return_rec(CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN);
715 } 732 }
716 } else if (state == JP_STATE_OBJ_NAME_OR_CLOSE || state == JP_STATE_OBJ_NAME) { 733 } else if (state == JP_STATE_OBJ_NAME_OR_CLOSE || state == JP_STATE_OBJ_NAME) {
717 if (state == JP_STATE_OBJ_NAME_OR_CLOSE && token.tokentype == CX_JSON_TOKEN_END_OBJECT) { 734 if (state == JP_STATE_OBJ_NAME_OR_CLOSE && token.tokentype == CX_JSON_TOKEN_END_OBJECT) {
718 // discard the obj from the value buffer 735 // discard the obj from the value buffer
719 json->vbuf_size--; 736 json->vbuf.size--;
720 return_rec(CX_JSON_NO_ERROR); 737 return_rec(CX_JSON_NO_ERROR);
721 } else { 738 } else {
722 // expect string 739 // expect string
723 if (token.tokentype != CX_JSON_TOKEN_STRING) { 740 if (token.tokentype != CX_JSON_TOKEN_STRING) {
724 return_rec(CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN); 741 return_rec(CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN);
729 if (name.ptr == NULL) { 746 if (name.ptr == NULL) {
730 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE 747 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE
731 } 748 }
732 assert(json->uncompleted_member_name.ptr == NULL); 749 assert(json->uncompleted_member_name.ptr == NULL);
733 json->uncompleted_member_name = name; 750 json->uncompleted_member_name = name;
734 assert(json->vbuf_size > 0); 751 assert(json->vbuf.size > 0);
735 752
736 // next state 753 // next state
737 json_add_state(json, JP_STATE_OBJ_COLON); 754 json_add_state(json, JP_STATE_OBJ_COLON);
738 return_rec(CX_JSON_NO_ERROR); 755 return_rec(CX_JSON_NO_ERROR);
739 } 756 }
750 if (token.tokentype == CX_JSON_TOKEN_VALUE_SEPARATOR) { 767 if (token.tokentype == CX_JSON_TOKEN_VALUE_SEPARATOR) {
751 json_add_state(json, JP_STATE_OBJ_NAME); 768 json_add_state(json, JP_STATE_OBJ_NAME);
752 return_rec(CX_JSON_NO_ERROR); 769 return_rec(CX_JSON_NO_ERROR);
753 } else if (token.tokentype == CX_JSON_TOKEN_END_OBJECT) { 770 } else if (token.tokentype == CX_JSON_TOKEN_END_OBJECT) {
754 // discard the obj from the value buffer 771 // discard the obj from the value buffer
755 json->vbuf_size--; 772 json->vbuf.size--;
756 return_rec(CX_JSON_NO_ERROR); 773 return_rec(CX_JSON_NO_ERROR);
757 } else { 774 } else {
758 return_rec(CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN); 775 return_rec(CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN);
759 } 776 }
760 } else { 777 } else {
775 792
776 // parse data 793 // parse data
777 CxJsonStatus result; 794 CxJsonStatus result;
778 do { 795 do {
779 result = json_parse(json); 796 result = json_parse(json);
780 if (result == CX_JSON_NO_ERROR && json->states_size == 1) { 797 if (result == CX_JSON_NO_ERROR && json->states.size == 1) {
781 // final state reached 798 // final state reached
782 assert(json->states[0] == JP_STATE_VALUE_END); 799 assert(json->states.data[0] == JP_STATE_VALUE_END);
783 assert(json->vbuf_size == 0); 800 assert(json->vbuf.size == 0);
784 801
785 // write output value 802 // write output value
786 *value = json->parsed; 803 *value = json->parsed;
787 json->parsed = NULL; 804 json->parsed = NULL;
788 805
789 // re-initialize state machine 806 // re-initialize state machine
790 json->states[0] = JP_STATE_VALUE_BEGIN; 807 json->states.data[0] = JP_STATE_VALUE_BEGIN;
791 808
792 return CX_JSON_NO_ERROR; 809 return CX_JSON_NO_ERROR;
793 } 810 }
794 } while (result == CX_JSON_NO_ERROR); 811 } while (result == CX_JSON_NO_ERROR);
795 812
796 // the parser might think there is no data 813 // the parser might think there is no data
797 // but when we did not reach the final state, 814 // but when we did not reach the final state,
798 // we know that there must be more to come 815 // we know that there must be more to come
799 if (result == CX_JSON_NO_DATA && json->states_size > 1) { 816 if (result == CX_JSON_NO_DATA && json->states.size > 1) {
800 return CX_JSON_INCOMPLETE_DATA; 817 return CX_JSON_INCOMPLETE_DATA;
801 } 818 }
802 819
803 return result; 820 return result;
804 } 821 }
840 case CX_JSON_OBJECT: { 857 case CX_JSON_OBJECT: {
841 json_free_object_map(value->object); 858 json_free_object_map(value->object);
842 break; 859 break;
843 } 860 }
844 case CX_JSON_ARRAY: { 861 case CX_JSON_ARRAY: {
845 CxJsonArray array = value->array; 862 for (size_t i = 0; i < value->array.size; i++) {
846 for (size_t i = 0; i < array.data_size; i++) { 863 cxJsonValueFree(value->array.data[i]);
847 cxJsonValueFree(array.data[i]); 864 }
848 } 865 cx_array_free_a(value->allocator, value->array);
849 cxFree(value->allocator, array.data);
850 break; 866 break;
851 } 867 }
852 case CX_JSON_STRING: { 868 case CX_JSON_STRING: {
853 cxFree(value->allocator, value->string.ptr); 869 cxFree(value->allocator, value->string.ptr);
854 break; 870 break;
873 // LCOV_EXCL_STOP 889 // LCOV_EXCL_STOP
874 } 890 }
875 return v; 891 return v;
876 } 892 }
877 893
878 CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator) { 894 CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator, size_t capacity) {
879 if (allocator == NULL) allocator = cxDefaultAllocator; 895 if (allocator == NULL) allocator = cxDefaultAllocator;
880 CxJsonValue* v = cxMalloc(allocator, sizeof(CxJsonValue)); 896 CxJsonValue* v = cxMalloc(allocator, sizeof(CxJsonValue));
881 if (v == NULL) return NULL; 897 if (v == NULL) return NULL;
882 v->allocator = allocator; 898 v->allocator = allocator;
883 v->type = CX_JSON_ARRAY; 899 v->type = CX_JSON_ARRAY;
884 cx_array_initialize_a(allocator, v->array.data, 16); 900 if (capacity > 0) {
885 if (v->array.data == NULL) { cxFree(allocator, v); return NULL; } 901 if (cx_array_init_a(allocator, v->array, capacity)) {
902 // LCOV_EXCL_START
903 cxFree(allocator, v);
904 return NULL;
905 // LCOV_EXCL_STOP
906 }
907 } else {
908 v->array.data = NULL;
909 v->array.size = v->array.capacity = 0;
910 }
886 return v; 911 return v;
887 } 912 }
888 913
889 CxJsonValue* cxJsonCreateNumber(const CxAllocator* allocator, double num) { 914 CxJsonValue* cxJsonCreateNumber(const CxAllocator* allocator, double num) {
890 if (allocator == NULL) allocator = cxDefaultAllocator; 915 if (allocator == NULL) allocator = cxDefaultAllocator;
998 cxFreeDefault(values); 1023 cxFreeDefault(values);
999 return ret; 1024 return ret;
1000 } 1025 }
1001 1026
1002 int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count) { 1027 int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count) {
1003 CxArrayReallocator value_realloc = cx_array_reallocator(arr->allocator, NULL);
1004 assert(arr->type == CX_JSON_ARRAY); 1028 assert(arr->type == CX_JSON_ARRAY);
1005 return cx_array_simple_copy_a(&value_realloc, 1029 return cx_array_add_array_a(arr->allocator, arr->array, val, count);
1006 arr->array.data,
1007 arr->array.data_size,
1008 val, count
1009 );
1010 } 1030 }
1011 1031
1012 int cx_json_obj_put(CxJsonValue* obj, cxstring name, CxJsonValue* child) { 1032 int cx_json_obj_put(CxJsonValue* obj, cxstring name, CxJsonValue* child) {
1013 return cxMapPut(obj->object, name, child); 1033 return cxMapPut(obj->object, name, child);
1014 } 1034 }
1018 if (v == NULL) return NULL; 1038 if (v == NULL) return NULL;
1019 if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; } 1039 if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; }
1020 return v; 1040 return v;
1021 } 1041 }
1022 1042
1023 CxJsonValue* cx_json_obj_put_arr(CxJsonValue* obj, cxstring name) { 1043 CxJsonValue* cx_json_obj_put_arr(CxJsonValue* obj, cxstring name, size_t capacity) {
1024 CxJsonValue* v = cxJsonCreateArr(obj->allocator); 1044 CxJsonValue* v = cxJsonCreateArr(obj->allocator, capacity);
1025 if (v == NULL) return NULL; 1045 if (v == NULL) return NULL;
1026 if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; } 1046 if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; }
1027 return v; 1047 return v;
1028 } 1048 }
1029 1049
1054 if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL;} 1074 if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL;}
1055 return v; 1075 return v;
1056 } 1076 }
1057 1077
1058 CxJsonValue *cxJsonArrGet(const CxJsonValue *value, size_t index) { 1078 CxJsonValue *cxJsonArrGet(const CxJsonValue *value, size_t index) {
1059 if (index >= value->array.data_size) { 1079 if (index >= value->array.size) {
1060 return &cx_json_value_nothing; 1080 return &cx_json_value_nothing;
1061 } 1081 }
1062 return value->array.data[index]; 1082 return value->array.data[index];
1063 } 1083 }
1064 1084
1065 CxJsonValue *cxJsonArrRemove(CxJsonValue *value, size_t index) { 1085 CxJsonValue *cxJsonArrRemove(CxJsonValue *value, size_t index) {
1066 if (index >= value->array.data_size) { 1086 if (index >= value->array.size) {
1067 return NULL; 1087 return NULL;
1068 } 1088 }
1069 CxJsonValue *ret = value->array.data[index]; 1089 CxJsonValue *ret = value->array.data[index];
1070 // TODO: replace with a low level cx_array_remove() 1090 // TODO: replace with a low level cx_array_remove()
1071 size_t count = value->array.data_size - index - 1; 1091 size_t count = value->array.size - index - 1;
1072 if (count > 0) { 1092 if (count > 0) {
1073 memmove(value->array.data + index, value->array.data + index + 1, count * sizeof(CxJsonValue*)); 1093 memmove(value->array.data + index, value->array.data + index + 1, count * sizeof(CxJsonValue*));
1074 } 1094 }
1075 value->array.data_size--; 1095 value->array.size--;
1076 return ret; 1096 return ret;
1077 } 1097 }
1078 1098
1079 char *cxJsonAsString(const CxJsonValue *value) { 1099 char *cxJsonAsString(const CxJsonValue *value) {
1080 return value->string.ptr; 1100 return value->string.ptr;
1103 return (int64_t) value->number; 1123 return (int64_t) value->number;
1104 } 1124 }
1105 } 1125 }
1106 1126
1107 CxIterator cxJsonArrIter(const CxJsonValue *value) { 1127 CxIterator cxJsonArrIter(const CxJsonValue *value) {
1108 return cxIteratorPtr( 1128 return cx_array_iterator_ptr(value->array);
1109 value->array.data,
1110 value->array.data_size,
1111 true // arrays need to keep order
1112 );
1113 } 1129 }
1114 1130
1115 CxMapIterator cxJsonObjIter(const CxJsonValue *value) { 1131 CxMapIterator cxJsonObjIter(const CxJsonValue *value) {
1116 return cxMapIterator(value->object); 1132 return cxMapIterator(value->object);
1117 } 1133 }
1463 case CX_JSON_NOTHING: 1479 case CX_JSON_NOTHING:
1464 return 0; 1480 return 0;
1465 case CX_JSON_OBJECT: 1481 case CX_JSON_OBJECT:
1466 return cxMapCompare(json->object, other->object); 1482 return cxMapCompare(json->object, other->object);
1467 case CX_JSON_ARRAY: 1483 case CX_JSON_ARRAY:
1468 if (json->array.data_size != other->array.data_size) return -1; 1484 if (json->array.size != other->array.size) return -1;
1469 for (size_t i = 0; i < json->array.data_size; i++) { 1485 for (size_t i = 0; i < json->array.size; i++) {
1470 const int d = cxJsonCompare(json->array.data[i], other->array.data[i]); 1486 const int d = cxJsonCompare(json->array.data[i], other->array.data[i]);
1471 if (d != 0) return d; 1487 if (d != 0) return d;
1472 } 1488 }
1473 return 0; 1489 return 0;
1474 case CX_JSON_STRING: 1490 case CX_JSON_STRING:
1525 // LCOV_EXCL_STOP 1541 // LCOV_EXCL_STOP
1526 } 1542 }
1527 return_value(obj); 1543 return_value(obj);
1528 } 1544 }
1529 case CX_JSON_ARRAY: { 1545 case CX_JSON_ARRAY: {
1530 const size_t elem_count = source->array.data_size; 1546 const size_t elem_count = source->array.size;
1531 CxArrayReallocator reallocator = cx_array_reallocator(allocator, NULL); 1547 CxJsonValue *arr = cxJsonCreateArr(allocator, elem_count);
1532 CxJsonValue *arr = cxJsonCreateArr(allocator);
1533 if (arr == NULL) return NULL; // LCOV_EXCL_LINE 1548 if (arr == NULL) return NULL; // LCOV_EXCL_LINE
1534 if (cx_array_simple_reserve_a(&reallocator, arr->array.data, elem_count)) { 1549 arr->array.size = elem_count;
1535 // LCOV_EXCL_START
1536 cxJsonValueFree(arr);
1537 return NULL;
1538 // LCOV_EXCL_STOP
1539 }
1540 arr->array.data_size = elem_count;
1541 for (size_t i = 0 ; i < elem_count ; i++) { 1550 for (size_t i = 0 ; i < elem_count ; i++) {
1542 CxJsonValue *e = cx_json_clone_func(NULL, source->array.data[i], allocator, NULL); 1551 CxJsonValue *e = cx_json_clone_func(NULL, source->array.data[i], allocator, NULL);
1543 if (e == NULL) { 1552 if (e == NULL) {
1544 // LCOV_EXCL_START 1553 // LCOV_EXCL_START
1545 cxJsonValueFree(arr); 1554 cxJsonValueFree(arr);

mercurial