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