# HG changeset patch # User Mike Becker # Date 1735151584 -3600 # Node ID fb1076ead56f17057f97c876452c58a03407c4e5 # Parent 2e86cf7791353f3384c83de102c8ec34e34b7538 add implementation for creating new json values relates to #527 diff -r 2e86cf779135 -r fb1076ead56f src/cx/json.h --- a/src/cx/json.h Mon Dec 23 18:32:25 2024 +0100 +++ b/src/cx/json.h Wed Dec 25 19:33:04 2024 +0100 @@ -295,7 +295,9 @@ }; /** - * Structure for a parsed token. + * Internally used structure for a parsed token. + * + * You should never need to use this in your code. */ struct cx_json_token_s { /** @@ -549,6 +551,78 @@ } #endif +cx_attr_nodiscard +CxJsonValue* cxJsonCreateObj(const CxAllocator* allocator); + +cx_attr_nodiscard +CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator); + +cx_attr_nodiscard +CxJsonValue* cxJsonCreateNumber(const CxAllocator* allocator, double num); + +cx_attr_nodiscard +CxJsonValue* cxJsonCreateInteger(const CxAllocator* allocator, int64_t num); + +cx_attr_nodiscard +cx_attr_nonnull_arg(2) +cx_attr_cstr_arg(2) +CxJsonValue* cxJsonCreateString(const CxAllocator* allocator, const char *str); + +cx_attr_nodiscard +CxJsonValue* cxJsonCreateCxString(const CxAllocator* allocator, cxstring str); + +cx_attr_nodiscard +CxJsonValue* cxJsonCreateLiteral(const CxAllocator* allocator, CxJsonLiteral lit); + +cx_attr_nonnull +cx_attr_access_r(2, 3) +int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count); + +cx_attr_nonnull +cx_attr_access_r(2, 3) +int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count); + +cx_attr_nonnull +cx_attr_access_r(2, 3) +int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count); + +cx_attr_nonnull +cx_attr_access_r(2, 3) +int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count); + +cx_attr_nonnull +cx_attr_access_r(2, 3) +int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count); + +cx_attr_nonnull +cx_attr_access_r(2, 3) +int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count); + +cx_attr_nonnull +int cxJsonObjPut(CxJsonValue* obj, cxstring name, CxJsonValue* child); + +cx_attr_nonnull +CxJsonValue* cxJsonObjPutObj(CxJsonValue* obj, cxstring name); + +cx_attr_nonnull +CxJsonValue* cxJsonObjPutArr(CxJsonValue* obj, cxstring name); + +cx_attr_nonnull +CxJsonValue* cxJsonObjPutNumber(CxJsonValue* obj, cxstring name, double num); + +cx_attr_nonnull +CxJsonValue* cxJsonObjPutInteger(CxJsonValue* obj, cxstring name, int64_t num); + +cx_attr_nonnull +cx_attr_cstr_arg(3) +CxJsonValue* cxJsonObjPutString(CxJsonValue* obj, cxstring name, const char* str); + +cx_attr_nonnull +CxJsonValue* cxJsonObjPutCxString(CxJsonValue* obj, cxstring name, cxstring str); + +cx_attr_nonnull +CxJsonValue* cxJsonObjPutLiteral(CxJsonValue* obj, cxstring name, CxJsonLiteral lit); + /** * Recursively deallocates the memory of a JSON value. * diff -r 2e86cf779135 -r fb1076ead56f src/json.c --- a/src/json.c Mon Dec 23 18:32:25 2024 +0100 +++ b/src/json.c Wed Dec 25 19:33:04 2024 +0100 @@ -665,6 +665,203 @@ cxFree(value->allocator, value); } +CxJsonValue* cxJsonCreateObj(const CxAllocator* allocator) { + CxJsonValue* v = cxMalloc(allocator, sizeof(CxJsonValue)); + if (v == NULL) return NULL; + v->allocator = allocator; + v->type = CX_JSON_OBJECT; + cx_array_initialize_a(allocator, v->value.object.values, 16); + if (v->value.object.values == NULL) { cxFree(allocator, v); return NULL; } + return v; +} + +CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator) { + CxJsonValue* v = cxMalloc(allocator, sizeof(CxJsonValue)); + if (v == NULL) return NULL; + v->allocator = allocator; + v->type = CX_JSON_ARRAY; + cx_array_initialize_a(allocator, v->value.array.array, 16); + if (v->value.array.array == NULL) { cxFree(allocator, v); return NULL; } + return v; +} + +CxJsonValue* cxJsonCreateNumber(const CxAllocator* allocator, double num) { + CxJsonValue* v = cxMalloc(allocator, sizeof(CxJsonValue)); + if (v == NULL) return NULL; + v->allocator = allocator; + v->type = CX_JSON_NUMBER; + v->value.number = num; + return v; +} + +CxJsonValue* cxJsonCreateInteger(const CxAllocator* allocator, int64_t num) { + CxJsonValue* v = cxMalloc(allocator, sizeof(CxJsonValue)); + if (v == NULL) return NULL; + v->allocator = allocator; + v->type = CX_JSON_INTEGER; + v->value.integer = num; + return v; +} + +CxJsonValue* cxJsonCreateString(const CxAllocator* allocator, const char* str) { + return cxJsonCreateCxString(allocator, cx_str(str)); +} + +CxJsonValue* cxJsonCreateCxString(const CxAllocator* allocator, cxstring str) { + CxJsonValue* v = cxMalloc(allocator, sizeof(CxJsonValue)); + if (v == NULL) return NULL; + v->allocator = allocator; + v->type = CX_JSON_STRING; + cxmutstr s = cx_strdup_a(allocator, str); + if (s.ptr == NULL) { cxFree(allocator, v); return NULL; } + return v; +} + +CxJsonValue* cxJsonCreateLiteral(const CxAllocator* allocator, CxJsonLiteral lit) { + CxJsonValue* v = cxMalloc(allocator, sizeof(CxJsonValue)); + if (v == NULL) return NULL; + v->allocator = allocator; + v->type = CX_JSON_LITERAL; + v->value.literal = lit; + return v; +} + +static void cx_json_arr_free_temp(CxJsonValue** values, size_t count) { + for (size_t i = 0; i < count; i++) { + if (values[i] == NULL) break; + cxJsonValueFree(values[i]); + } + free(values); +} + +int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count) { + CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + if (values == NULL) return -1; + for (size_t i = 0; i < count; i++) { + values[i] = cxJsonCreateNumber(arr->allocator, num[i]); + if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } + } + int ret = cxJsonArrAddValues(arr, values, count); + free(values); + return ret; +} + +int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count) { + CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + if (values == NULL) return -1; + for (size_t i = 0; i < count; i++) { + values[i] = cxJsonCreateInteger(arr->allocator, num[i]); + if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } + } + int ret = cxJsonArrAddValues(arr, values, count); + free(values); + return ret; +} + +int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count) { + CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + if (values == NULL) return -1; + for (size_t i = 0; i < count; i++) { + values[i] = cxJsonCreateString(arr->allocator, str[i]); + if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } + } + int ret = cxJsonArrAddValues(arr, values, count); + free(values); + return ret; +} + +int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count) { + CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + if (values == NULL) return -1; + for (size_t i = 0; i < count; i++) { + values[i] = cxJsonCreateCxString(arr->allocator, str[i]); + if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } + } + int ret = cxJsonArrAddValues(arr, values, count); + free(values); + return ret; +} + +int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count) { + CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + if (values == NULL) return -1; + for (size_t i = 0; i < count; i++) { + values[i] = cxJsonCreateLiteral(arr->allocator, lit[i]); + if (values[i] == NULL) { cx_json_arr_free_temp(values, count); return -1; } + } + int ret = cxJsonArrAddValues(arr, values, count); + free(values); + return ret; +} + +int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count) { + CxArrayReallocator value_realloc = cx_array_reallocator(arr->allocator, NULL); + assert(arr->type == CX_JSON_ARRAY); + return cx_array_simple_copy_a(&value_realloc, + arr->value.array.array, + arr->value.array.array_size, + val, count + ); +} + +int cxJsonObjPut(CxJsonValue* obj, cxstring name, CxJsonValue* child) { + CxArrayReallocator value_realloc = cx_array_reallocator(obj->allocator, NULL); + assert(obj->type == CX_JSON_OBJECT); + cxmutstr k = cx_strdup_a(obj->allocator, name); + if (k.ptr == NULL) return -1; + CxJsonObjValue kv = {k, child}; + return cx_array_simple_add_a(&value_realloc, obj->value.object.values, kv); +} + +CxJsonValue* cxJsonObjPutObj(CxJsonValue* obj, cxstring name) { + CxJsonValue* v = cxJsonCreateObj(obj->allocator); + if (v == NULL) return NULL; + if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; } + return v; +} + +CxJsonValue* cxJsonObjPutArr(CxJsonValue* obj, cxstring name) { + CxJsonValue* v = cxJsonCreateArr(obj->allocator); + if (v == NULL) return NULL; + if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; } + return v; +} + +CxJsonValue* cxJsonObjPutNumber(CxJsonValue* obj, cxstring name, double num) { + CxJsonValue* v = cxJsonCreateNumber(obj->allocator, num); + if (v == NULL) return NULL; + if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; } + return v; +} + +CxJsonValue* cxJsonObjPutInteger(CxJsonValue* obj, cxstring name, int64_t num) { + CxJsonValue* v = cxJsonCreateInteger(obj->allocator, num); + if (v == NULL) return NULL; + if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; } + return v; +} + +CxJsonValue* cxJsonObjPutString(CxJsonValue* obj, cxstring name, const char* str) { + CxJsonValue* v = cxJsonCreateString(obj->allocator, str); + if (v == NULL) return NULL; + if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; } + return v; +} + +CxJsonValue* cxJsonObjPutCxString(CxJsonValue* obj, cxstring name, cxstring str) { + CxJsonValue* v = cxJsonCreateCxString(obj->allocator, str); + if (v == NULL) return NULL; + if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL; } + return v; +} + +CxJsonValue* cxJsonObjPutLiteral(CxJsonValue* obj, cxstring name, CxJsonLiteral lit) { + CxJsonValue* v = cxJsonCreateLiteral(obj->allocator, lit); + if (v == NULL) return NULL; + if (cxJsonObjPut(obj, name, v)) { cxJsonValueFree(v); return NULL;} + return v; +} + CxJsonValue *cxJsonArrGet(const CxJsonValue *value, size_t index) { if (index >= value->value.array.array_size) { return &cx_json_value_nothing;