--- a/ucx/json.c Tue Sep 09 16:01:30 2025 +0200 +++ b/ucx/json.c Tue Sep 09 20:56:47 2025 +0200 @@ -46,22 +46,17 @@ return cx_strcmp(cx_strcast(left->name), cx_strcast(right->name)); } -static CxJsonObjValue *json_find_objvalue(const CxJsonValue *obj, cxstring name) { +static size_t json_find_objvalue(const CxJsonValue *obj, cxstring name) { assert(obj->type == CX_JSON_OBJECT); CxJsonObjValue kv_dummy; kv_dummy.name = cx_mutstrn((char*) name.ptr, name.length); - size_t index = cx_array_binary_search( + return cx_array_binary_search( obj->value.object.values, obj->value.object.values_size, sizeof(CxJsonObjValue), &kv_dummy, json_cmp_objvalue ); - if (index == obj->value.object.values_size) { - return NULL; - } else { - return &obj->value.object.values[index]; - } } static int json_add_objvalue(CxJsonValue *objv, CxJsonObjValue member) { @@ -500,7 +495,7 @@ if (all_printable && escape) { size_t capa = str.length + 32; - char *space = malloc(capa); + char *space = cxMallocDefault(capa); if (space == NULL) return cx_mutstrn(NULL, 0); cxBufferInit(&buf, space, capa, NULL, CX_BUFFER_AUTO_EXTEND); cxBufferWrite(str.ptr, 1, i, &buf); @@ -631,10 +626,10 @@ void cxJsonDestroy(CxJson *json) { cxBufferDestroy(&json->buffer); if (json->states != json->states_internal) { - free(json->states); + cxFreeDefault(json->states); } if (json->vbuf != json->vbuf_internal) { - free(json->vbuf); + cxFreeDefault(json->vbuf); } cxJsonValueFree(json->parsed); json->parsed = NULL; @@ -984,67 +979,67 @@ if (values[i] == NULL) break; cxJsonValueFree(values[i]); } - free(values); + cxFreeDefault(values); } // LCOV_EXCL_STOP int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(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) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; } int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(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) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; } int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(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) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; } int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(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) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; } int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(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) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; } @@ -1126,6 +1121,20 @@ return value->value.array.array[index]; } +CxJsonValue *cxJsonArrRemove(CxJsonValue *value, size_t index) { + if (index >= value->value.array.array_size) { + return NULL; + } + CxJsonValue *ret = value->value.array.array[index]; + // TODO: replace with a low level cx_array_remove() + size_t count = value->value.array.array_size - index - 1; + if (count > 0) { + memmove(value->value.array.array + index, value->value.array.array + index + 1, count * sizeof(CxJsonValue*)); + } + value->value.array.array_size--; + return ret; +} + CxIterator cxJsonArrIter(const CxJsonValue *value) { return cxIteratorPtr( value->value.array.array, @@ -1142,11 +1151,25 @@ } CxJsonValue *cx_json_obj_get_cxstr(const CxJsonValue *value, cxstring name) { - CxJsonObjValue *member = json_find_objvalue(value, name); - if (member == NULL) { + size_t index = json_find_objvalue(value, name); + if (index >= value->value.object.values_size) { return &cx_json_value_nothing; } else { - return member->value; + return value->value.object.values[index].value; + } +} + +CxJsonValue *cx_json_obj_remove_cxstr(CxJsonValue *value, cxstring name) { + size_t index = json_find_objvalue(value, name); + if (index >= value->value.object.values_size) { + return NULL; + } else { + CxJsonObjValue kv = value->value.object.values[index]; + cx_strfree_a(value->allocator, &kv.name); + // TODO: replace with cx_array_remove() + value->value.object.values_size--; + memmove(value->value.object.values + index, value->value.object.values + index + 1, (value->value.object.values_size - index) * sizeof(CxJsonObjValue)); + return kv.value; } }