| 44 const CxJsonObjValue *left = l; |
45 const CxJsonObjValue *left = l; |
| 45 const CxJsonObjValue *right = r; |
46 const CxJsonObjValue *right = r; |
| 46 return cx_strcmp(cx_strcast(left->name), cx_strcast(right->name)); |
47 return cx_strcmp(cx_strcast(left->name), cx_strcast(right->name)); |
| 47 } |
48 } |
| 48 |
49 |
| 49 static CxJsonObjValue *json_find_objvalue(const CxJsonValue *obj, cxstring name) { |
50 static size_t json_find_objvalue(const CxJsonValue *obj, cxstring name) { |
| 50 assert(obj->type == CX_JSON_OBJECT); |
51 assert(obj->type == CX_JSON_OBJECT); |
| 51 CxJsonObjValue kv_dummy; |
52 CxJsonObjValue kv_dummy; |
| 52 kv_dummy.name = cx_mutstrn((char*) name.ptr, name.length); |
53 kv_dummy.name = cx_mutstrn((char*) name.ptr, name.length); |
| 53 size_t index = cx_array_binary_search( |
54 return cx_array_binary_search( |
| 54 obj->value.object.values, |
55 obj->value.object.values, |
| 55 obj->value.object.values_size, |
56 obj->value.object.values_size, |
| 56 sizeof(CxJsonObjValue), |
57 sizeof(CxJsonObjValue), |
| 57 &kv_dummy, |
58 &kv_dummy, |
| 58 json_cmp_objvalue |
59 json_cmp_objvalue |
| 59 ); |
60 ); |
| 60 if (index == obj->value.object.values_size) { |
|
| 61 return NULL; |
|
| 62 } else { |
|
| 63 return &obj->value.object.values[index]; |
|
| 64 } |
|
| 65 } |
61 } |
| 66 |
62 |
| 67 static int json_add_objvalue(CxJsonValue *objv, CxJsonObjValue member) { |
63 static int json_add_objvalue(CxJsonValue *objv, CxJsonObjValue member) { |
| 68 assert(objv->type == CX_JSON_OBJECT); |
64 assert(objv->type == CX_JSON_OBJECT); |
| 69 const CxAllocator * const al = objv->allocator; |
65 const CxAllocator * const al = objv->allocator; |
| 629 } |
615 } |
| 630 |
616 |
| 631 void cxJsonDestroy(CxJson *json) { |
617 void cxJsonDestroy(CxJson *json) { |
| 632 cxBufferDestroy(&json->buffer); |
618 cxBufferDestroy(&json->buffer); |
| 633 if (json->states != json->states_internal) { |
619 if (json->states != json->states_internal) { |
| 634 free(json->states); |
620 cxFreeDefault(json->states); |
| 635 } |
621 } |
| 636 if (json->vbuf != json->vbuf_internal) { |
622 if (json->vbuf != json->vbuf_internal) { |
| 637 free(json->vbuf); |
623 cxFreeDefault(json->vbuf); |
| 638 } |
624 } |
| 639 cxJsonValueFree(json->parsed); |
625 cxJsonValueFree(json->parsed); |
| 640 json->parsed = NULL; |
626 json->parsed = NULL; |
| 641 if (json->uncompleted_member.name.ptr != NULL) { |
627 if (json->uncompleted_member.name.ptr != NULL) { |
| 642 cx_strfree_a(json->allocator, &json->uncompleted_member.name); |
628 cx_strfree_a(json->allocator, &json->uncompleted_member.name); |
| 643 json->uncompleted_member = (CxJsonObjValue){{NULL, 0}, NULL}; |
629 json->uncompleted_member = (CxJsonObjValue){{NULL, 0}, NULL}; |
| 644 } |
630 } |
| |
631 } |
| |
632 |
| |
633 void cxJsonReset(CxJson *json) { |
| |
634 const CxAllocator *allocator = json->allocator; |
| |
635 cxJsonDestroy(json); |
| |
636 cxJsonInit(json, allocator); |
| 645 } |
637 } |
| 646 |
638 |
| 647 int cxJsonFilln(CxJson *json, const char *buf, size_t size) { |
639 int cxJsonFilln(CxJson *json, const char *buf, size_t size) { |
| 648 if (cxBufferEof(&json->buffer)) { |
640 if (cxBufferEof(&json->buffer)) { |
| 649 // reinitialize the buffer |
641 // reinitialize the buffer |
| 982 static void json_arr_free_temp(CxJsonValue** values, size_t count) { |
974 static void json_arr_free_temp(CxJsonValue** values, size_t count) { |
| 983 for (size_t i = 0; i < count; i++) { |
975 for (size_t i = 0; i < count; i++) { |
| 984 if (values[i] == NULL) break; |
976 if (values[i] == NULL) break; |
| 985 cxJsonValueFree(values[i]); |
977 cxJsonValueFree(values[i]); |
| 986 } |
978 } |
| 987 free(values); |
979 cxFreeDefault(values); |
| 988 } |
980 } |
| 989 // LCOV_EXCL_STOP |
981 // LCOV_EXCL_STOP |
| 990 |
982 |
| 991 int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count) { |
983 int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count) { |
| 992 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
984 CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); |
| 993 if (values == NULL) return -1; |
985 if (values == NULL) return -1; |
| 994 for (size_t i = 0; i < count; i++) { |
986 for (size_t i = 0; i < count; i++) { |
| 995 values[i] = cxJsonCreateNumber(arr->allocator, num[i]); |
987 values[i] = cxJsonCreateNumber(arr->allocator, num[i]); |
| 996 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
988 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
| 997 } |
989 } |
| 998 int ret = cxJsonArrAddValues(arr, values, count); |
990 int ret = cxJsonArrAddValues(arr, values, count); |
| 999 free(values); |
991 cxFreeDefault(values); |
| 1000 return ret; |
992 return ret; |
| 1001 } |
993 } |
| 1002 |
994 |
| 1003 int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count) { |
995 int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count) { |
| 1004 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
996 CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); |
| 1005 if (values == NULL) return -1; |
997 if (values == NULL) return -1; |
| 1006 for (size_t i = 0; i < count; i++) { |
998 for (size_t i = 0; i < count; i++) { |
| 1007 values[i] = cxJsonCreateInteger(arr->allocator, num[i]); |
999 values[i] = cxJsonCreateInteger(arr->allocator, num[i]); |
| 1008 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
1000 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
| 1009 } |
1001 } |
| 1010 int ret = cxJsonArrAddValues(arr, values, count); |
1002 int ret = cxJsonArrAddValues(arr, values, count); |
| 1011 free(values); |
1003 cxFreeDefault(values); |
| 1012 return ret; |
1004 return ret; |
| 1013 } |
1005 } |
| 1014 |
1006 |
| 1015 int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count) { |
1007 int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count) { |
| 1016 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
1008 CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); |
| 1017 if (values == NULL) return -1; |
1009 if (values == NULL) return -1; |
| 1018 for (size_t i = 0; i < count; i++) { |
1010 for (size_t i = 0; i < count; i++) { |
| 1019 values[i] = cxJsonCreateString(arr->allocator, str[i]); |
1011 values[i] = cxJsonCreateString(arr->allocator, str[i]); |
| 1020 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
1012 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
| 1021 } |
1013 } |
| 1022 int ret = cxJsonArrAddValues(arr, values, count); |
1014 int ret = cxJsonArrAddValues(arr, values, count); |
| 1023 free(values); |
1015 cxFreeDefault(values); |
| 1024 return ret; |
1016 return ret; |
| 1025 } |
1017 } |
| 1026 |
1018 |
| 1027 int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count) { |
1019 int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count) { |
| 1028 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
1020 CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); |
| 1029 if (values == NULL) return -1; |
1021 if (values == NULL) return -1; |
| 1030 for (size_t i = 0; i < count; i++) { |
1022 for (size_t i = 0; i < count; i++) { |
| 1031 values[i] = cxJsonCreateCxString(arr->allocator, str[i]); |
1023 values[i] = cxJsonCreateCxString(arr->allocator, str[i]); |
| 1032 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
1024 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
| 1033 } |
1025 } |
| 1034 int ret = cxJsonArrAddValues(arr, values, count); |
1026 int ret = cxJsonArrAddValues(arr, values, count); |
| 1035 free(values); |
1027 cxFreeDefault(values); |
| 1036 return ret; |
1028 return ret; |
| 1037 } |
1029 } |
| 1038 |
1030 |
| 1039 int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count) { |
1031 int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count) { |
| 1040 CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); |
1032 CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); |
| 1041 if (values == NULL) return -1; |
1033 if (values == NULL) return -1; |
| 1042 for (size_t i = 0; i < count; i++) { |
1034 for (size_t i = 0; i < count; i++) { |
| 1043 values[i] = cxJsonCreateLiteral(arr->allocator, lit[i]); |
1035 values[i] = cxJsonCreateLiteral(arr->allocator, lit[i]); |
| 1044 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
1036 if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } |
| 1045 } |
1037 } |
| 1046 int ret = cxJsonArrAddValues(arr, values, count); |
1038 int ret = cxJsonArrAddValues(arr, values, count); |
| 1047 free(values); |
1039 cxFreeDefault(values); |
| 1048 return ret; |
1040 return ret; |
| 1049 } |
1041 } |
| 1050 |
1042 |
| 1051 int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count) { |
1043 int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count) { |
| 1052 CxArrayReallocator value_realloc = cx_array_reallocator(arr->allocator, NULL); |
1044 CxArrayReallocator value_realloc = cx_array_reallocator(arr->allocator, NULL); |
| 1124 return &cx_json_value_nothing; |
1116 return &cx_json_value_nothing; |
| 1125 } |
1117 } |
| 1126 return value->value.array.array[index]; |
1118 return value->value.array.array[index]; |
| 1127 } |
1119 } |
| 1128 |
1120 |
| |
1121 CxJsonValue *cxJsonArrRemove(CxJsonValue *value, size_t index) { |
| |
1122 if (index >= value->value.array.array_size) { |
| |
1123 return NULL; |
| |
1124 } |
| |
1125 CxJsonValue *ret = value->value.array.array[index]; |
| |
1126 // TODO: replace with a low level cx_array_remove() |
| |
1127 size_t count = value->value.array.array_size - index - 1; |
| |
1128 if (count > 0) { |
| |
1129 memmove(value->value.array.array + index, value->value.array.array + index + 1, count * sizeof(CxJsonValue*)); |
| |
1130 } |
| |
1131 value->value.array.array_size--; |
| |
1132 return ret; |
| |
1133 } |
| |
1134 |
| |
1135 char *cxJsonAsString(const CxJsonValue *value) { |
| |
1136 return value->value.string.ptr; |
| |
1137 } |
| |
1138 |
| |
1139 cxstring cxJsonAsCxString(const CxJsonValue *value) { |
| |
1140 return cx_strcast(value->value.string); |
| |
1141 } |
| |
1142 |
| |
1143 cxmutstr cxJsonAsCxMutStr(const CxJsonValue *value) { |
| |
1144 return value->value.string; |
| |
1145 } |
| |
1146 |
| |
1147 double cxJsonAsDouble(const CxJsonValue *value) { |
| |
1148 if (value->type == CX_JSON_INTEGER) { |
| |
1149 return (double) value->value.integer; |
| |
1150 } else { |
| |
1151 return value->value.number; |
| |
1152 } |
| |
1153 } |
| |
1154 |
| |
1155 int64_t cxJsonAsInteger(const CxJsonValue *value) { |
| |
1156 if (value->type == CX_JSON_INTEGER) { |
| |
1157 return value->value.integer; |
| |
1158 } else { |
| |
1159 return (int64_t) value->value.number; |
| |
1160 } |
| |
1161 } |
| |
1162 |
| 1129 CxIterator cxJsonArrIter(const CxJsonValue *value) { |
1163 CxIterator cxJsonArrIter(const CxJsonValue *value) { |
| 1130 return cxIteratorPtr( |
1164 return cxIteratorPtr( |
| 1131 value->value.array.array, |
1165 value->value.array.array, |
| 1132 value->value.array.array_size |
1166 value->value.array.array_size, |
| |
1167 true // arrays need to keep order |
| 1133 ); |
1168 ); |
| 1134 } |
1169 } |
| 1135 |
1170 |
| 1136 CxIterator cxJsonObjIter(const CxJsonValue *value) { |
1171 CxIterator cxJsonObjIter(const CxJsonValue *value) { |
| 1137 return cxIterator( |
1172 return cxIterator( |
| 1138 value->value.object.values, |
1173 value->value.object.values, |
| 1139 sizeof(CxJsonObjValue), |
1174 sizeof(CxJsonObjValue), |
| 1140 value->value.object.values_size |
1175 value->value.object.values_size, |
| |
1176 true // TODO: objects do not always need to keep order |
| 1141 ); |
1177 ); |
| 1142 } |
1178 } |
| 1143 |
1179 |
| 1144 CxJsonValue *cx_json_obj_get_cxstr(const CxJsonValue *value, cxstring name) { |
1180 CxJsonValue *cx_json_obj_get(const CxJsonValue *value, cxstring name) { |
| 1145 CxJsonObjValue *member = json_find_objvalue(value, name); |
1181 size_t index = json_find_objvalue(value, name); |
| 1146 if (member == NULL) { |
1182 if (index >= value->value.object.values_size) { |
| 1147 return &cx_json_value_nothing; |
1183 return &cx_json_value_nothing; |
| 1148 } else { |
1184 } else { |
| 1149 return member->value; |
1185 return value->value.object.values[index].value; |
| |
1186 } |
| |
1187 } |
| |
1188 |
| |
1189 CxJsonValue *cx_json_obj_remove(CxJsonValue *value, cxstring name) { |
| |
1190 size_t index = json_find_objvalue(value, name); |
| |
1191 if (index >= value->value.object.values_size) { |
| |
1192 return NULL; |
| |
1193 } else { |
| |
1194 CxJsonObjValue kv = value->value.object.values[index]; |
| |
1195 cx_strfree_a(value->allocator, &kv.name); |
| |
1196 // TODO: replace with cx_array_remove() / cx_array_remove_fast() |
| |
1197 value->value.object.values_size--; |
| |
1198 memmove(value->value.object.values + index, value->value.object.values + index + 1, (value->value.object.values_size - index) * sizeof(CxJsonObjValue)); |
| |
1199 return kv.value; |
| 1150 } |
1200 } |
| 1151 } |
1201 } |
| 1152 |
1202 |
| 1153 CxJsonWriter cxJsonWriterCompact(void) { |
1203 CxJsonWriter cxJsonWriterCompact(void) { |
| 1154 return (CxJsonWriter) { |
1204 return (CxJsonWriter) { |