Fri, 20 Dec 2024 21:09:20 +0100
generify cxJsonObjGet() - fixes #525
src/cx/json.h | file | annotate | diff | comparison | revisions | |
src/json.c | file | annotate | diff | comparison | revisions |
--- a/src/cx/json.h Fri Dec 20 16:56:20 2024 +0100 +++ b/src/cx/json.h Fri Dec 20 21:09:20 2024 +0100 @@ -236,9 +236,9 @@ */ struct cx_json_obj_value_s { /** - * The key a.k.a. name of the value. + * The key (or name in JSON terminology) of the value. */ - char *name; + cxmutstr name; /** * The value. */ @@ -468,16 +468,6 @@ #ifdef __cplusplus } // extern "C" -/** - * Adds more data to the input buffer. - * - * The data will be copied. - * - * @param json the json interface - * @param str the string to add to the buffer - * @return zero on success, non-zero on internal allocation error - * @see cxJsonFilln() - */ cx_attr_nonnull static inline int cxJsonFill( CxJson *json, @@ -486,16 +476,6 @@ return cxJsonFilln(json, str.ptr, str.length); } -/** - * Adds more data to the input buffer. - * - * The data will be copied. - * - * @param json the json interface - * @param str the string to add to the buffer - * @return zero on success, non-zero on internal allocation error - * @see cxJsonFilln() - */ cx_attr_nonnull static inline int cxJsonFill( CxJson *json, @@ -504,16 +484,6 @@ return cxJsonFilln(json, str.ptr, str.length); } -/** - * Adds more data to the input buffer. - * - * The data will be copied. - * - * @param json the json interface - * @param str the string to add to the buffer - * @return zero on success, non-zero on internal allocation error - * @see cxJsonFilln() - */ cx_attr_nonnull cx_attr_cstr_arg(2) static inline int cxJsonFill( @@ -543,14 +513,7 @@ (json, str) /** - * Adds more data to the input buffer. - * - * Internal function - please use the #cxJsonFill() macro. - * - * @param json the json interface - * @param str the string to add to the buffer - * @return zero on success, non-zero on internal allocation error - * @see cxJsonFill() + * @copydoc cxJsonFill() */ cx_attr_nonnull static inline int cx_json_fill_cxstr( @@ -561,14 +524,7 @@ } /** - * Adds more data to the input buffer. - * - * Internal function - please use the #cxJsonFill() macro. - * - * @param json the json interface - * @param str the string to add to the buffer - * @return zero on success, non-zero on internal allocation error - * @see cxJsonFill() + * @copydoc cxJsonFill() */ cx_attr_nonnull static inline int cx_json_fill_mutstr( @@ -579,14 +535,7 @@ } /** - * Adds more data to the input buffer. - * - * Internal function - please use the #cxJsonFill() macro. - * - * @param json the json interface - * @param str the string to add to the buffer - * @return zero on success, non-zero on internal allocation error - * @see cxJsonFill() + * @copydoc cxJsonFill() */ cx_attr_nonnull cx_attr_cstr_arg(2) @@ -901,6 +850,30 @@ CxIterator cxJsonArrIter(const CxJsonValue *value); /** + * @copydoc cxJsonObjGet() + */ +cx_attr_nonnull +cx_attr_returns_nonnull +CxJsonValue *cx_json_obj_get_cxstr(const CxJsonValue *value, cxstring name); + +#ifdef __cplusplus +} // extern "C" + +CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxstring name) { + return cx_json_obj_get_cxstr(value, name); +} + +CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxmutstr name) { + return cx_json_obj_get_cxstr(value, cx_strcast(name)); +} + +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. * * If the \p value is not a JSON object, the behavior is undefined. @@ -914,10 +887,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) + +/** + * @copydoc cxJsonObjGet() + */ +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)); +} + +/** + * @copydoc cxJsonObjGet() + */ cx_attr_nonnull cx_attr_returns_nonnull cx_attr_cstr_arg(2) -CxJsonValue *cxJsonObjGet(const CxJsonValue *value, const char* name); +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 #ifdef __cplusplus }
--- a/src/json.c Fri Dec 20 16:56:20 2024 +0100 +++ b/src/json.c Fri Dec 20 21:09:20 2024 +0100 @@ -375,16 +375,6 @@ return v; } -static int json_obj_add_entry(const CxJson *json, char *name) { - CxJsonObjValue kv = {name, NULL}; - assert(json->vbuf_size > 0); - CxJsonValue *parent = json->vbuf[json->vbuf_size - 1]; - assert(parent != NULL); - assert(parent->type == CX_JSON_OBJECT); - CxArrayReallocator value_realloc = cx_array_reallocator(json->allocator, NULL); - return cx_array_simple_add_a(&value_realloc, parent->value.object.values, kv); -} - #define JP_STATE_VALUE_BEGIN 0 #define JP_STATE_VALUE_END 10 #define JP_STATE_VALUE_BEGIN_OBJ 1 @@ -568,7 +558,15 @@ if (name.ptr == NULL) { return_rec(CX_JSON_VALUE_ALLOC_FAILED); } - json_obj_add_entry(json, name.ptr); + CxJsonObjValue kv = {name, NULL}; + assert(json->vbuf_size > 0); + CxJsonValue *parent = json->vbuf[json->vbuf_size - 1]; + assert(parent != NULL); + assert(parent->type == CX_JSON_OBJECT); + CxArrayReallocator value_realloc = cx_array_reallocator(json->allocator, NULL); + if (cx_array_simple_add_a(&value_realloc, parent->value.object.values, kv)) { + return_rec(CX_JSON_VALUE_ALLOC_FAILED); + } // next state json_add_state(json, JP_STATE_OBJ_COLON); @@ -643,7 +641,7 @@ CxJsonObject obj = value->value.object; for (size_t i = 0; i < obj.values_size; i++) { cxJsonValueFree(obj.values[i].value); - cxFree(value->allocator, obj.values[i].name); + cx_strfree_a(value->allocator, &obj.values[i].name); } cxFree(value->allocator, obj.values); break; @@ -707,11 +705,11 @@ return iter; } -CxJsonValue *cxJsonObjGet(const CxJsonValue *value, const char *name) { +CxJsonValue *cx_json_obj_get_cxstr(const CxJsonValue *value, cxstring name) { const CxJsonObject *obj = &(value->value.object); // TODO: think about sorting the object so that we can use binary search here for (size_t i = 0; i < obj->values_size; i++) { - if (0 == strcmp(name, obj->values[i].name)) { + if (0 == cx_strcmp(name, cx_strcast(obj->values[i].name))) { return obj->values[i].value; } }