--- a/ucx/cx/json.h Wed Dec 17 18:31:20 2025 +0100 +++ b/ucx/cx/json.h Thu Dec 18 17:50:15 2025 +0100 @@ -43,8 +43,6 @@ #include "array_list.h" #include "map.h" -#include <string.h> - #ifdef __cplusplus extern "C" { #endif @@ -185,10 +183,6 @@ typedef struct cx_json_value_s CxJsonValue; /** - * Type alias for the JSON array struct. - */ -typedef struct cx_json_array_s CxJsonArray; -/** * Type alias for the map representing a JSON object. * The map contains pointers of type @c CxJsonValue. */ @@ -211,16 +205,6 @@ typedef enum cx_json_literal CxJsonLiteral; /** - * JSON array structure. - */ -struct cx_json_array_s { - /** - * The array data. - */ - CX_ARRAY_DECLARE(CxJsonValue*, data); -}; - -/** * Structure for a JSON value. */ struct cx_json_value_s { @@ -243,7 +227,7 @@ /** * The array data if the type is #CX_JSON_ARRAY. */ - CxJsonArray array; + CX_ARRAY(CxJsonValue*, array); /** * The object data if the type is #CX_JSON_OBJECT. */ @@ -298,6 +282,7 @@ * The allocator used for produced JSON values. */ const CxAllocator *allocator; + /** * The input buffer. */ @@ -327,12 +312,12 @@ /** * State stack. */ - CX_ARRAY_DECLARE_SIZED(int, states, unsigned); + CX_ARRAY(int, states); /** * Value buffer stack. */ - CX_ARRAY_DECLARE_SIZED(CxJsonValue*, vbuf, unsigned); + CX_ARRAY(CxJsonValue*, vbuf); /** * Internally reserved memory for the state stack. @@ -477,28 +462,28 @@ /** * Produces a compact string representation of the specified JSON value. * + * @param allocator the allocator for the string * @param value the JSON value - * @param allocator the allocator for the string * @return the produced string * @see cxJsonWrite() * @see cxJsonWriterCompact() * @see cxJsonToPrettyString() */ -cx_attr_nonnull_arg(1) -CX_EXPORT cxmutstr cxJsonToString(CxJsonValue *value, const CxAllocator *allocator); +cx_attr_nonnull_arg(2) +CX_EXPORT cxmutstr cxJsonToString(const CxAllocator *allocator, CxJsonValue *value); /** * Produces a pretty string representation of the specified JSON value. * + * @param allocator the allocator for the string * @param value the JSON value - * @param allocator the allocator for the string * @return the produced string * @see cxJsonWrite() * @see cxJsonWriterPretty() * @see cxJsonToString() */ -cx_attr_nonnull_arg(1) -CX_EXPORT cxmutstr cxJsonToPrettyString(CxJsonValue *value, const CxAllocator *allocator); +cx_attr_nonnull_arg(2) +CX_EXPORT cxmutstr cxJsonToPrettyString(const CxAllocator *allocator, CxJsonValue *value); /** * Initializes the JSON interface. @@ -628,13 +613,16 @@ /** * Creates a new (empty) JSON array. * + * Optionally, this function already allocates memory with the given capacity. + * * @param allocator the allocator to use + * @param capacity optional capacity or zero if it's unknown how many elements the array will have * @return the new JSON array or @c NULL if allocation fails * @see cxJsonObjPutArr() * @see cxJsonArrAddValues() */ cx_attr_nodiscard -CX_EXPORT CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator); +CX_EXPORT CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator, size_t capacity); /** * Creates a new JSON number value. @@ -840,23 +828,25 @@ * * @param obj the target JSON object * @param name the name of the new value + * @param capacity optional initial capacity * @return the new value or @c NULL if allocation fails * @see cxJsonObjPut() * @see cxJsonCreateArr() */ cx_attr_nonnull -CX_EXPORT CxJsonValue* cx_json_obj_put_arr(CxJsonValue* obj, cxstring name); +CX_EXPORT CxJsonValue* cx_json_obj_put_arr(CxJsonValue* obj, cxstring name, size_t capacity); /** * Creates a new JSON array and adds it to an object. * * @param obj (@c CxJsonValue*) the target JSON object * @param name (any string) the name of the new value + * @param capacity (@c size_t) optional initial capacity * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails * @see cxJsonObjPut() * @see cxJsonCreateArr() */ -#define cxJsonObjPutArr(obj, name) cx_json_obj_put_arr(obj, cx_strcast(name)) +#define cxJsonObjPutArr(obj, name, capacity) cx_json_obj_put_arr(obj, cx_strcast(name), capacity) /** * Creates a new JSON number and adds it to an object. @@ -1238,7 +1228,7 @@ */ cx_attr_nonnull CX_INLINE size_t cxJsonArrSize(const CxJsonValue *value) { - return value->array.data_size; + return value->array.size; } /** @@ -1366,6 +1356,66 @@ */ #define cxJsonObjRemove(value, name) cx_json_obj_remove(value, cx_strcast(name)) +/** + * Performs a deep comparison of two JSON values. + * + * The order of object members is ignored during comparison. + * + * @param json the JSON value + * @param other the other JSON value that the JSON value is compared to + * @retval zero the values are equal (except for ordering of object members) + * @retval non-zero the values differ + */ +CX_EXPORT int cxJsonCompare(const CxJsonValue *json, const CxJsonValue *other); + + +/** + * Creates a deep copy of the specified JSON value. + * + * If you need a @c cx_clone_func compatible version, see cxJsonCloneFunc(). + * + * @note when you are cloning @c NULL, you will get a pointer to a statically + * allocated value which represents nothing. + * + * @param value the value to be cloned + * @param allocator the allocator for the new value + * @return the new value or @c NULL if any allocation was unsuccessful + * @see cxJsonCloneFunc() + */ +cx_attr_nodiscard +CX_EXPORT CxJsonValue* cxJsonClone(const CxJsonValue* value, + const CxAllocator* allocator); + + +/** + * A @c cx_clone_func compatible version of cxJsonClone(). + * + * Internal function - use cxJsonCloneFunc() to get a properly casted function pointer. + * + * @param target the target memory or @c NULL + * @param source the value to be cloned + * @param allocator the allocator for the new value + * @param data unused + * @return the new value or @c NULL if any allocation was unsuccessful + * @see cxJsonClone() + */ +cx_attr_nodiscard +CX_EXPORT CxJsonValue* cx_json_clone_func( + CxJsonValue* target, const CxJsonValue* source, + const CxAllocator* allocator, void *data); + +/** + * A @c cx_clone_func compatible version of cxJsonClone(). + * + * @param target (@c CxJsonValue*) the target memory or @c NULL + * @param source (@c CxJsonValue*) the value to be cloned + * @param allocator (@c CxAllocator*) the allocator for the new value + * @param data unused + * @return the new value or @c NULL if any allocation was unsuccessful + * @see cxJsonClone() + */ +#define cxJsonCloneFunc ((cx_clone_func) cx_json_clone_func) + #ifdef __cplusplus } #endif