--- a/src/json.c Thu Nov 28 19:37:00 2024 +0100 +++ b/src/json.c Thu Nov 28 20:53:56 2024 +0100 @@ -266,12 +266,12 @@ return ret; } -static cxmutstr unescape_string(const char *str, size_t len) { +static cxmutstr unescape_string(const CxAllocator *a, const char *str, size_t len) { // TODO: support more escape sequences // we know that the unescaped string will be shorter by at least 2 chars cxmutstr result; result.length = 0; - result.ptr = malloc(len - 1); + result.ptr = cxMalloc(a, len - 1); if (result.ptr == NULL) { // TODO: check if this actually leads to correct error handling return result; @@ -437,7 +437,7 @@ } case CX_JSON_TOKEN_STRING: { p->reader_type = CX_JSON_READER_STRING; - cxmutstr str = unescape_string(token.content, token.length); + cxmutstr str = unescape_string(p->allocator, token.content, token.length); if (str.ptr) { p->value_str = str.ptr; p->value_str_len = str.length; @@ -487,7 +487,7 @@ if (token.tokentype != CX_JSON_TOKEN_STRING) return -1; if (p->value_name) free(p->value_name); - cxmutstr valname = unescape_string(token.content, token.length); + cxmutstr valname = unescape_string(p->allocator, token.content, token.length); p->value_name = valname.ptr; p->value_name_len = valname.length; @@ -549,7 +549,8 @@ if (!parent) { return -1; // shouldn't happen but who knows } - + + CxArrayReallocator reallocator = cx_array_reallocator(p->allocator, NULL); if (parent->type == CX_JSON_OBJECT) { if (!p->value_name || p->value_name_len == 0) { return -1; @@ -561,9 +562,21 @@ newvalue.name = valuename; newvalue.value = v; - return cx_array_simple_add(parent->value.object.values, newvalue); + return cx_array_add( + &parent->value.object.values, + &parent->value.object.values_size, + &parent->value.object.values_capacity, + sizeof(CxJsonObjValue), + &newvalue, + &reallocator); } else if (parent->type == CX_JSON_ARRAY) { - return cx_array_simple_add(parent->value.array.array, v); + return cx_array_add( + &parent->value.array.array, + &parent->value.array.array_size, + &parent->value.array.array_capacity, + sizeof(CxJsonValue*), + &v, + &reallocator); } else { return -1; // should also never happen } @@ -581,8 +594,13 @@ return 0; } -void cxJsonInit(CxJson *json) { +void cxJsonInit(const CxAllocator *allocator, CxJson *json) { + if (allocator == NULL) { + allocator = cxDefaultAllocator; + } + memset(json, 0, sizeof(CxJson)); + json->allocator = allocator; json->states = json->states_internal; json->states_alloc = cx_nmemb(json->states_internal); // TODO: find better way to configure the initial allocation size for arrays and objects @@ -618,8 +636,9 @@ while (p->readvalue_nelm > 0 || !p->read_value) { if (p->value_ready) { // value available without another read - CxJsonValue *v = calloc(1, sizeof(CxJsonValue)); + CxJsonValue *v = cxCalloc(p->allocator, 1, sizeof(CxJsonValue)); if (!v) return -1; + v->allocator = p->allocator; if (p->readvalue_nelm > 0) { if (add_to_parent(p, p->readvalue_stack[p->readvalue_nelm - 1], v)) { @@ -704,15 +723,14 @@ void cxJsonValueFree(CxJsonValue *value) { if (value == NULL || value == &cx_json_value_nothing) return; - // TODO: discuss if we should keep freeing the stuff recursively switch (value->type) { case CX_JSON_OBJECT: { CxJsonObject obj = value->value.object; for (size_t i = 0; i < obj.values_size; i++) { cxJsonValueFree(obj.values[i].value); - free(obj.values[i].name); + cxFree(value->allocator, obj.values[i].name); } - free(obj.values); + cxFree(value->allocator, obj.values); break; } case CX_JSON_ARRAY: { @@ -720,18 +738,18 @@ for (size_t i = 0; i < array.array_size; i++) { cxJsonValueFree(array.array[i]); } - free(array.array); + cxFree(value->allocator, array.array); break; } case CX_JSON_STRING: { - free(value->value.string.ptr); + cxFree(value->allocator, value->value.string.ptr); break; } default: { break; } } - free(value); + cxFree(value->allocator, value); } CxJsonValue *cxJsonArrGet(CxJsonValue *value, size_t index) {