--- a/src/json.c Mon Nov 24 22:39:18 2025 +0100 +++ b/src/json.c Tue Nov 25 20:35:27 2025 +0100 @@ -94,7 +94,7 @@ size_t newcap = obj->values_capacity; if (newcap > oldcap) { if (cxReallocateArray(al, &obj->indices, newcap, sizeof(size_t))) { - return 1; + return 1; // LCOV_EXCL_LINE } } @@ -437,7 +437,7 @@ } else if (c == 'u') { char utf8buf[4]; unsigned utf8len = unescape_unicode_string( - cx_strn(str.ptr + i - 1, str.length + 1 - i), + cx_strn(str.ptr + i - 1, str.length - i), utf8buf ); if(utf8len > 0) { @@ -456,7 +456,7 @@ } else { // TODO: discuss the behavior for unrecognized escape sequences // most parsers throw an error here - we just ignore it - result.ptr[result.length++] = '\\'; + result.ptr[result.length++] = '\\'; // LCOV_EXCL_LINE } result.ptr[result.length++] = c; @@ -640,6 +640,7 @@ if (cxBufferEof(&json->buffer)) { // reinitialize the buffer cxBufferDestroy(&json->buffer); + if (buf == NULL) buf = ""; // buffer must not be initialized with NULL cxBufferInit(&json->buffer, (char*) buf, size, NULL, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_COPY_ON_WRITE); json->buffer.size = size; @@ -734,7 +735,8 @@ } } else { if (cx_strtod(token.content, &vbuf->value.number)) { - return_rec(CX_JSON_FORMAT_ERROR_NUMBER); + // TODO: at the moment this is unreachable, because the tokenizer is already stricter than cx_strtod() + return_rec(CX_JSON_FORMAT_ERROR_NUMBER); // LCOV_EXCL_LINE } } return_rec(CX_JSON_NO_ERROR); @@ -815,19 +817,19 @@ } else { // should be unreachable assert(false); - return_rec(-1); + return_rec(-1); // LCOV_EXCL_LINE } } CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value) { - // check if buffer has been filled + // initialize output value + *value = &cx_json_value_nothing; + + // check if the buffer has been filled if (json->buffer.space == NULL) { return CX_JSON_NULL_DATA; } - // initialize output value - *value = &cx_json_value_nothing; - // parse data CxJsonStatus result; do { @@ -943,11 +945,7 @@ return v; } -CxJsonValue* cxJsonCreateString(const CxAllocator* allocator, const char* str) { - return cxJsonCreateCxString(allocator, cx_str(str)); -} - -CxJsonValue* cxJsonCreateCxString(const CxAllocator* allocator, cxstring str) { +CxJsonValue* cx_json_create_string(const CxAllocator* allocator, cxstring str) { if (allocator == NULL) allocator = cxDefaultAllocator; CxJsonValue* v = cxMalloc(allocator, sizeof(CxJsonValue)); if (v == NULL) return NULL; @@ -1020,7 +1018,7 @@ 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]); + 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); @@ -1050,61 +1048,56 @@ ); } -int cxJsonObjPut(CxJsonValue* obj, cxstring name, CxJsonValue* child) { +int cx_json_obj_put(CxJsonValue* obj, cxstring name, CxJsonValue* child) { cxmutstr k = cx_strdup_a(obj->allocator, name); if (k.ptr == NULL) return -1; CxJsonObjValue kv = {k, child}; if (json_add_objvalue(obj, kv)) { + // LCOV_EXCL_START cx_strfree_a(obj->allocator, &k); return 1; + // LCOV_EXCL_STOP } else { return 0; } } -CxJsonValue* cxJsonObjPutObj(CxJsonValue* obj, cxstring name) { +CxJsonValue* cx_json_obj_put_obj(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* cx_json_obj_put_arr(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* cx_json_obj_put_number(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* cx_json_obj_put_integer(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* cx_json_obj_put_string(CxJsonValue* obj, cxstring name, cxstring 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* cx_json_obj_put_literal(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;} @@ -1286,9 +1279,6 @@ ? look_idx : value->value.object.indices[look_idx]; CxJsonObjValue *member = &value->value.object.values[elem_idx]; - if (settings->sort_members) { - depth++;depth--; - } // possible indentation if (settings->pretty) { @@ -1350,7 +1340,9 @@ if (cx_json_write_rec( target, element, wfunc, settings, depth) - ) return 1; + ) { + return 1; // LCOV_EXCL_LINE + } if (iter.index < iter.elem_count - 1) { const char *arr_value_sep = ", ";