--- a/ucx/cx/json.h Sat Oct 04 14:54:25 2025 +0200 +++ b/ucx/cx/json.h Sun Oct 19 21:20:08 2025 +0200 @@ -90,11 +90,11 @@ */ CX_JSON_TOKEN_STRING, /** - * A number token that can be represented as integer. + * A number token that can be represented as an integer. */ CX_JSON_TOKEN_INTEGER, /** - * A number token that cannot be represented as integer. + * A number token that cannot be represented as an integer. */ CX_JSON_TOKEN_NUMBER, /** @@ -196,11 +196,11 @@ */ typedef struct cx_mutstr_s CxJsonString; /** - * Type alias for a number that can be represented as 64-bit signed integer. + * Type alias for a number that can be represented as a 64-bit signed integer. */ typedef int64_t CxJsonInteger; /** - * Type alias for number that is not an integer. + * Type alias for a number that is not an integer. */ typedef double CxJsonNumber; /** @@ -272,27 +272,27 @@ */ union { /** - * The array data if type is #CX_JSON_ARRAY. + * The array data if the type is #CX_JSON_ARRAY. */ CxJsonArray array; /** - * The object data if type is #CX_JSON_OBJECT. + * The object data if the type is #CX_JSON_OBJECT. */ CxJsonObject object; /** - * The string data if type is #CX_JSON_STRING. + * The string data if the type is #CX_JSON_STRING. */ CxJsonString string; /** - * The integer if type is #CX_JSON_INTEGER. + * The integer if the type is #CX_JSON_INTEGER. */ CxJsonInteger integer; /** - * The number if type is #CX_JSON_NUMBER. + * The number if the type is #CX_JSON_NUMBER. */ CxJsonNumber number; /** - * The literal type if type is #CX_JSON_LITERAL. + * The literal type if the type is #CX_JSON_LITERAL. */ CxJsonLiteral literal; } value; @@ -377,7 +377,7 @@ }; /** - * Status codes for the json interface. + * Status codes for the JSON interface. */ enum cx_json_status { /** @@ -391,7 +391,7 @@ /** * The input ends unexpectedly. * - * Refill the buffer with cxJsonFill() to complete the json data. + * Refill the buffer with cxJsonFill() to complete the JSON data. */ CX_JSON_INCOMPLETE_DATA, /** @@ -400,7 +400,7 @@ * You can use this enumerator to check for all "good" status results * by checking if the status is less than @c CX_JSON_OK. * - * A "good" status means, that you can refill data and continue parsing. + * A "good" status means that you can refill data and continue parsing. */ CX_JSON_OK, /** @@ -412,7 +412,7 @@ */ CX_JSON_BUFFER_ALLOC_FAILED, /** - * Allocating memory for a json value failed. + * Allocating memory for a JSON value failed. */ CX_JSON_VALUE_ALLOC_FAILED, /** @@ -426,7 +426,7 @@ }; /** - * Typedef for the json status enum. + * Typedef for the JSON status enum. */ typedef enum cx_json_status CxJsonStatus; @@ -445,7 +445,7 @@ /** * The maximum number of fractional digits in a number value. * The default value is 6 and values larger than 15 are reduced to 15. - * Note, that the actual number of digits may be lower, depending on the concrete number. + * Note that the actual number of digits may be lower, depending on the concrete number. */ uint8_t frac_max_digits; /** @@ -465,7 +465,7 @@ }; /** - * Typedef for the json writer. + * Typedef for the JSON writer. */ typedef struct cx_json_writer_s CxJsonWriter; @@ -496,9 +496,8 @@ * that the data is only partially written when an error occurs with no * way to indicate how much data was written. * To avoid this problem, you can use a CxBuffer as @p target which is - * unlikely to fail a write operation and either use the buffer's flush - * feature to relay the data or use the data in the buffer manually to - * write it to the actual target. + * unlikely to fail a write operation. You can, for example, use the buffer's flush + * feature to relay the data. * * @param target the buffer or stream where to write to * @param value the value that shall be written @@ -517,9 +516,9 @@ ); /** - * Initializes the json interface. + * Initializes the JSON interface. * - * @param json the json interface + * @param json the JSON interface * @param allocator the allocator that shall be used for the produced values * @see cxJsonDestroy() */ @@ -528,9 +527,9 @@ void cxJsonInit(CxJson *json, const CxAllocator *allocator); /** - * Destroys the json interface. + * Destroys the JSON interface. * - * @param json the json interface + * @param json the JSON interface * @see cxJsonInit() */ cx_attr_nonnull @@ -538,12 +537,12 @@ void cxJsonDestroy(CxJson *json); /** - * Destroys and re-initializes the json interface. + * Destroys and re-initializes the JSON interface. * - * You might want to use this, to reset the parser after + * You might want to use this to reset the parser after * encountering a syntax error. * - * @param json the json interface + * @param json the JSON interface */ cx_attr_nonnull static inline void cxJsonReset(CxJson *json) { @@ -563,7 +562,7 @@ * the additional data is appended - inevitably leading to * an allocation of a new buffer and copying the previous contents. * - * @param json the json interface + * @param json the JSON interface * @param buf the source buffer * @param len the length of the source buffer * @retval zero success @@ -575,36 +574,20 @@ cx_attr_export int cxJsonFilln(CxJson *json, const char *buf, size_t len); -#ifdef __cplusplus -} // extern "C" +/** + * Internal function, do not use. + * + * @param json the JSON interface + * @param str the string + * @retval zero success + * @retval non-zero internal allocation error + */ cx_attr_nonnull -static inline int cxJsonFill( - CxJson *json, - cxstring str -) { +static inline int cx_json_fill(CxJson *json, cxstring str) { return cxJsonFilln(json, str.ptr, str.length); } -cx_attr_nonnull -static inline int cxJsonFill( - CxJson *json, - cxmutstr str -) { - return cxJsonFilln(json, str.ptr, str.length); -} - -cx_attr_nonnull -cx_attr_cstr_arg(2) -static inline int cxJsonFill( - CxJson *json, - const char *str -) { - return cxJsonFilln(json, str, strlen(str)); -} - -extern "C" { -#else // __cplusplus /** * Fills the input buffer. * @@ -616,53 +599,13 @@ * the additional data is appended - inevitably leading to * an allocation of a new buffer and copying the previous contents. * - * @param json the json interface + * @param json the JSON interface * @param str the source string * @retval zero success * @retval non-zero internal allocation error * @see cxJsonFilln() */ -#define cxJsonFill(json, str) _Generic((str), \ - cxstring: cx_json_fill_cxstr, \ - cxmutstr: cx_json_fill_mutstr, \ - char*: cx_json_fill_str, \ - const char*: cx_json_fill_str) \ - (json, str) - -/** - * @copydoc cxJsonFill() - */ -cx_attr_nonnull -static inline int cx_json_fill_cxstr( - CxJson *json, - cxstring str -) { - return cxJsonFilln(json, str.ptr, str.length); -} - -/** - * @copydoc cxJsonFill() - */ -cx_attr_nonnull -static inline int cx_json_fill_mutstr( - CxJson *json, - cxmutstr str -) { - return cxJsonFilln(json, str.ptr, str.length); -} - -/** - * @copydoc cxJsonFill() - */ -cx_attr_nonnull -cx_attr_cstr_arg(2) -static inline int cx_json_fill_str( - CxJson *json, - const char *str -) { - return cxJsonFilln(json, str, strlen(str)); -} -#endif +#define cxJsonFill(json, str) cx_json_fill(json, cx_strcast(str)) /** * Creates a new (empty) JSON object. @@ -973,8 +916,8 @@ * Recursively deallocates the memory of a JSON value. * * @remark The type of each deallocated value will be changed - * to #CX_JSON_NOTHING and values of such type will be skipped - * by the de-allocation. That means, this function protects + * to #CX_JSON_NOTHING, and values of such a type will be skipped + * by the deallocation. That means this function protects * you from double-frees when you are accidentally freeing * a nested value and then the parent value (or vice versa). * @@ -993,7 +936,7 @@ * add the missing data with another invocation of cxJsonFill() * and then repeat the call to cxJsonNext(). * - * @param json the json interface + * @param json the JSON interface * @param value a pointer where the next value shall be stored * @retval CX_JSON_NO_ERROR successfully retrieve the @p value * @retval CX_JSON_NO_DATA there is no (more) data in the buffer to read from @@ -1049,7 +992,7 @@ /** * Checks if the specified value is a JSON number. * - * This function will return true for both floating point and + * This function will return true for both floating-point and * integer numbers. * * @param value a pointer to the value @@ -1109,7 +1052,7 @@ /** * Checks if the specified value is @c true. * - * @remark Be advised, that this is not the same as + * @remark Be advised that this is different from * testing @c !cxJsonIsFalse(v). * * @param value a pointer to the value @@ -1126,7 +1069,7 @@ /** * Checks if the specified value is @c false. * - * @remark Be advised, that this is not the same as + * @remark Be advised that this is different from * testing @c !cxJsonIsTrue(v). * * @param value a pointer to the value @@ -1197,7 +1140,7 @@ } /** - * Obtains a double-precision floating point value from the given JSON value. + * Obtains a double-precision floating-point value from the given JSON value. * * If the @p value is not a JSON number, the behavior is undefined. * @@ -1284,6 +1227,23 @@ CxJsonValue *cxJsonArrGet(const CxJsonValue *value, size_t index); /** + * Removes an element from a JSON array. + * + * If the @p value is not a JSON array, the behavior is undefined. + * + * This function, in contrast to cxJsonArrayGet(), returns @c NULL + * when the index is out of bounds. + * + * @param value the JSON value + * @param index the index in the array + * @return the removed value from the specified index or @c NULL when the index was out of bounds + * @see cxJsonIsArray() + */ +cx_attr_nonnull +cx_attr_export +CxJsonValue *cxJsonArrRemove(CxJsonValue *value, size_t index); + +/** * Returns an iterator over the JSON array elements. * * The iterator yields values of type @c CxJsonValue* . @@ -1317,30 +1277,16 @@ CxIterator cxJsonObjIter(const CxJsonValue *value); /** - * @copydoc cxJsonObjGet() + * Internal function, do not use. + * @param value the JSON object + * @param name the key to look up + * @return the value corresponding to the key */ cx_attr_nonnull cx_attr_returns_nonnull cx_attr_export -CxJsonValue *cx_json_obj_get_cxstr(const CxJsonValue *value, cxstring name); - -#ifdef __cplusplus -} // extern "C" - -static inline CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxstring name) { - return cx_json_obj_get_cxstr(value, name); -} +CxJsonValue *cx_json_obj_get(const CxJsonValue *value, cxstring name); -static inline CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxmutstr name) { - return cx_json_obj_get_cxstr(value, cx_strcast(name)); -} - -static inline CxJsonValue *cxJsonObjGet(const CxJsonValue *value, const char *name) { - return cx_json_obj_get_cxstr(value, cx_str(name)); -} - -extern "C" { -#else /** * Returns a value corresponding to a key in a JSON object. * @@ -1355,32 +1301,32 @@ * @return the value corresponding to the key * @see cxJsonIsObject() */ -#define cxJsonObjGet(value, name) _Generic((name), \ - cxstring: cx_json_obj_get_cxstr, \ - cxmutstr: cx_json_obj_get_mutstr, \ - char*: cx_json_obj_get_str, \ - const char*: cx_json_obj_get_str) \ - (value, name) +#define cxJsonObjGet(value, name) cx_json_obj_get(value, cx_strcast(name)) /** - * @copydoc cxJsonObjGet() + * Internal function, do not use. + * @param value the JSON object + * @param name the key to look up + * @return the value corresponding to the key or @c NULL when the key is not part of the object */ cx_attr_nonnull -cx_attr_returns_nonnull -static inline CxJsonValue *cx_json_obj_get_mutstr(const CxJsonValue *value, cxmutstr name) { - return cx_json_obj_get_cxstr(value, cx_strcast(name)); -} +cx_attr_export +CxJsonValue *cx_json_obj_remove(CxJsonValue *value, cxstring name); /** - * @copydoc cxJsonObjGet() + * Removes and returns a value corresponding to a key in a JSON object. + * + * If the @p value is not a JSON object, the behavior is undefined. + * + * This function, in contrast to cxJsonObjGet() returns @c NULL when the + * object does not contain @p name. + * + * @param value the JSON object + * @param name the key to look up + * @return the value corresponding to the key or @c NULL when the key is not part of the object + * @see cxJsonIsObject() */ -cx_attr_nonnull -cx_attr_returns_nonnull -cx_attr_cstr_arg(2) -static inline CxJsonValue *cx_json_obj_get_str(const CxJsonValue *value, const char *name) { - return cx_json_obj_get_cxstr(value, cx_str(name)); -} -#endif +#define cxJsonObjRemove(value, name) cx_json_obj_remove(value, cx_strcast(name)) #ifdef __cplusplus }