generify cxJsonObjGet() - fixes #525

Fri, 20 Dec 2024 21:09:20 +0100

author
Mike Becker <universe@uap-core.de>
date
Fri, 20 Dec 2024 21:09:20 +0100
changeset 1037
83620ba72cc1
parent 1036
6d29532a76c3
child 1038
8cab3d8e0af4

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;
         }
     }

mercurial