427 } |
425 } |
428 cxBufferDestroy(&buf); |
426 cxBufferDestroy(&buf); |
429 return str; |
427 return str; |
430 } |
428 } |
431 |
429 |
432 static CxJsonValue* create_json_value(CxJson *json, CxJsonValueType type) { |
430 static CxJsonValue* json_create_value(CxJson *json, CxJsonValueType type) { |
433 CxJsonValue *v = cxCalloc(json->allocator, 1, sizeof(CxJsonValue)); |
431 CxJsonValue *v = cxCalloc(json->allocator, 1, sizeof(CxJsonValue)); |
434 if (v == NULL) return NULL; // LCOV_EXCL_LINE |
432 if (v == NULL) return NULL; // LCOV_EXCL_LINE |
435 |
433 |
436 // initialize the value |
434 // initialize the value |
437 v->type = type; |
435 v->type = type; |
593 if (state < 3) { |
591 if (state < 3) { |
594 // push expected end state to the stack |
592 // push expected end state to the stack |
595 json_add_state(json, 10 + state); |
593 json_add_state(json, 10 + state); |
596 switch (token.tokentype) { |
594 switch (token.tokentype) { |
597 case CX_JSON_TOKEN_BEGIN_ARRAY: { |
595 case CX_JSON_TOKEN_BEGIN_ARRAY: { |
598 if (create_json_value(json, CX_JSON_ARRAY) == NULL) { |
596 if (json_create_value(json, CX_JSON_ARRAY) == NULL) { |
599 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
597 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
600 } |
598 } |
601 json_add_state(json, JP_STATE_VALUE_BEGIN_AR); |
599 json_add_state(json, JP_STATE_VALUE_BEGIN_AR); |
602 return_rec(CX_JSON_NO_ERROR); |
600 return_rec(CX_JSON_NO_ERROR); |
603 } |
601 } |
604 case CX_JSON_TOKEN_BEGIN_OBJECT: { |
602 case CX_JSON_TOKEN_BEGIN_OBJECT: { |
605 if (create_json_value(json, CX_JSON_OBJECT) == NULL) { |
603 if (json_create_value(json, CX_JSON_OBJECT) == NULL) { |
606 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
604 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
607 } |
605 } |
608 json_add_state(json, JP_STATE_OBJ_NAME_OR_CLOSE); |
606 json_add_state(json, JP_STATE_OBJ_NAME_OR_CLOSE); |
609 return_rec(CX_JSON_NO_ERROR); |
607 return_rec(CX_JSON_NO_ERROR); |
610 } |
608 } |
611 case CX_JSON_TOKEN_STRING: { |
609 case CX_JSON_TOKEN_STRING: { |
612 if ((vbuf = create_json_value(json, CX_JSON_STRING)) == NULL) { |
610 if ((vbuf = json_create_value(json, CX_JSON_STRING)) == NULL) { |
613 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
611 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
614 } |
612 } |
615 cxmutstr str = unescape_string(json->allocator, token.content); |
613 cxmutstr str = unescape_string(json->allocator, token.content); |
616 if (str.ptr == NULL) { |
614 if (str.ptr == NULL) { |
617 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
615 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
620 return_rec(CX_JSON_NO_ERROR); |
618 return_rec(CX_JSON_NO_ERROR); |
621 } |
619 } |
622 case CX_JSON_TOKEN_INTEGER: |
620 case CX_JSON_TOKEN_INTEGER: |
623 case CX_JSON_TOKEN_NUMBER: { |
621 case CX_JSON_TOKEN_NUMBER: { |
624 int type = token.tokentype == CX_JSON_TOKEN_INTEGER ? CX_JSON_INTEGER : CX_JSON_NUMBER; |
622 int type = token.tokentype == CX_JSON_TOKEN_INTEGER ? CX_JSON_INTEGER : CX_JSON_NUMBER; |
625 if (NULL == (vbuf = create_json_value(json, type))) { |
623 if (NULL == (vbuf = json_create_value(json, type))) { |
626 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
624 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
627 } |
625 } |
628 if (type == CX_JSON_INTEGER) { |
626 if (type == CX_JSON_INTEGER) { |
629 if (cx_strtoi64(token.content, &vbuf->value.integer, 10)) { |
627 if (cx_strtoi64(token.content, &vbuf->value.integer, 10)) { |
630 return_rec(CX_JSON_FORMAT_ERROR_NUMBER); |
628 return_rec(CX_JSON_FORMAT_ERROR_NUMBER); |
635 } |
633 } |
636 } |
634 } |
637 return_rec(CX_JSON_NO_ERROR); |
635 return_rec(CX_JSON_NO_ERROR); |
638 } |
636 } |
639 case CX_JSON_TOKEN_LITERAL: { |
637 case CX_JSON_TOKEN_LITERAL: { |
640 if ((vbuf = create_json_value(json, CX_JSON_LITERAL)) == NULL) { |
638 if ((vbuf = json_create_value(json, CX_JSON_LITERAL)) == NULL) { |
641 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
639 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
642 } |
640 } |
643 if (0 == cx_strcmp(cx_strcast(token.content), cx_str("true"))) { |
641 if (0 == cx_strcmp(cx_strcast(token.content), cx_str("true"))) { |
644 vbuf->value.literal = CX_JSON_TRUE; |
642 vbuf->value.literal = CX_JSON_TRUE; |
645 } else if (0 == cx_strcmp(cx_strcast(token.content), cx_str("false"))) { |
643 } else if (0 == cx_strcmp(cx_strcast(token.content), cx_str("false"))) { |
866 return v; |
864 return v; |
867 } |
865 } |
868 |
866 |
869 // LCOV_EXCL_START |
867 // LCOV_EXCL_START |
870 // never called as long as malloc() does not return NULL |
868 // never called as long as malloc() does not return NULL |
871 static void cx_json_arr_free_temp(CxJsonValue** values, size_t count) { |
869 static void json_arr_free_temp(CxJsonValue** values, size_t count) { |
872 for (size_t i = 0; i < count; i++) { |
870 for (size_t i = 0; i < count; i++) { |
873 if (values[i] == NULL) break; |
871 if (values[i] == NULL) break; |
874 cxJsonValueFree(values[i]); |
872 cxJsonValueFree(values[i]); |
875 } |
873 } |
876 free(values); |
874 free(values); |
880 int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count) { |
878 int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count) { |
881 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
879 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
882 if (values == NULL) return -1; |
880 if (values == NULL) return -1; |
883 for (size_t i = 0; i < count; i++) { |
881 for (size_t i = 0; i < count; i++) { |
884 values[i] = cxJsonCreateNumber(arr->allocator, num[i]); |
882 values[i] = cxJsonCreateNumber(arr->allocator, num[i]); |
885 if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } |
883 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
886 } |
884 } |
887 int ret = cxJsonArrAddValues(arr, values, count); |
885 int ret = cxJsonArrAddValues(arr, values, count); |
888 free(values); |
886 free(values); |
889 return ret; |
887 return ret; |
890 } |
888 } |
892 int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count) { |
890 int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count) { |
893 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
891 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
894 if (values == NULL) return -1; |
892 if (values == NULL) return -1; |
895 for (size_t i = 0; i < count; i++) { |
893 for (size_t i = 0; i < count; i++) { |
896 values[i] = cxJsonCreateInteger(arr->allocator, num[i]); |
894 values[i] = cxJsonCreateInteger(arr->allocator, num[i]); |
897 if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } |
895 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
898 } |
896 } |
899 int ret = cxJsonArrAddValues(arr, values, count); |
897 int ret = cxJsonArrAddValues(arr, values, count); |
900 free(values); |
898 free(values); |
901 return ret; |
899 return ret; |
902 } |
900 } |
904 int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count) { |
902 int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count) { |
905 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
903 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
906 if (values == NULL) return -1; |
904 if (values == NULL) return -1; |
907 for (size_t i = 0; i < count; i++) { |
905 for (size_t i = 0; i < count; i++) { |
908 values[i] = cxJsonCreateString(arr->allocator, str[i]); |
906 values[i] = cxJsonCreateString(arr->allocator, str[i]); |
909 if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } |
907 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
910 } |
908 } |
911 int ret = cxJsonArrAddValues(arr, values, count); |
909 int ret = cxJsonArrAddValues(arr, values, count); |
912 free(values); |
910 free(values); |
913 return ret; |
911 return ret; |
914 } |
912 } |
916 int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count) { |
914 int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count) { |
917 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
915 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
918 if (values == NULL) return -1; |
916 if (values == NULL) return -1; |
919 for (size_t i = 0; i < count; i++) { |
917 for (size_t i = 0; i < count; i++) { |
920 values[i] = cxJsonCreateCxString(arr->allocator, str[i]); |
918 values[i] = cxJsonCreateCxString(arr->allocator, str[i]); |
921 if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } |
919 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
922 } |
920 } |
923 int ret = cxJsonArrAddValues(arr, values, count); |
921 int ret = cxJsonArrAddValues(arr, values, count); |
924 free(values); |
922 free(values); |
925 return ret; |
923 return ret; |
926 } |
924 } |
928 int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count) { |
926 int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count) { |
929 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
927 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
930 if (values == NULL) return -1; |
928 if (values == NULL) return -1; |
931 for (size_t i = 0; i < count; i++) { |
929 for (size_t i = 0; i < count; i++) { |
932 values[i] = cxJsonCreateLiteral(arr->allocator, lit[i]); |
930 values[i] = cxJsonCreateLiteral(arr->allocator, lit[i]); |
933 if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } |
931 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
934 } |
932 } |
935 int ret = cxJsonArrAddValues(arr, values, count); |
933 int ret = cxJsonArrAddValues(arr, values, count); |
936 free(values); |
934 free(values); |
937 return ret; |
935 return ret; |
938 } |
936 } |
1037 } else { |
1035 } else { |
1038 return member->value; |
1036 return member->value; |
1039 } |
1037 } |
1040 } |
1038 } |
1041 |
1039 |
1042 static const CxJsonWriter cx_json_writer_default = { |
|
1043 false, |
|
1044 true, |
|
1045 6, |
|
1046 false, |
|
1047 4 |
|
1048 }; |
|
1049 |
|
1050 CxJsonWriter cxJsonWriterCompact(void) { |
1040 CxJsonWriter cxJsonWriterCompact(void) { |
1051 return cx_json_writer_default; |
1041 return (CxJsonWriter) { |
|
1042 false, |
|
1043 true, |
|
1044 6, |
|
1045 false, |
|
1046 4 |
|
1047 }; |
1052 } |
1048 } |
1053 |
1049 |
1054 CxJsonWriter cxJsonWriterPretty(bool use_spaces) { |
1050 CxJsonWriter cxJsonWriterPretty(bool use_spaces) { |
1055 return (CxJsonWriter) { |
1051 return (CxJsonWriter) { |
1056 true, |
1052 true, |
1322 void *target, |
1318 void *target, |
1323 const CxJsonValue *value, |
1319 const CxJsonValue *value, |
1324 cx_write_func wfunc, |
1320 cx_write_func wfunc, |
1325 const CxJsonWriter *settings |
1321 const CxJsonWriter *settings |
1326 ) { |
1322 ) { |
1327 if (settings == NULL) { |
|
1328 settings = &cx_json_writer_default; |
|
1329 } |
|
1330 assert(target != NULL); |
1323 assert(target != NULL); |
1331 assert(value != NULL); |
1324 assert(value != NULL); |
1332 assert(wfunc != NULL); |
1325 assert(wfunc != NULL); |
1333 |
1326 |
|
1327 CxJsonWriter writer_default = cxJsonWriterCompact(); |
|
1328 if (settings == NULL) { |
|
1329 settings = &writer_default; |
|
1330 } |
1334 return cx_json_write_rec(target, value, wfunc, settings, 0); |
1331 return cx_json_write_rec(target, value, wfunc, settings, 0); |
1335 } |
1332 } |