]> granicus.if.org Git - json-c/commitdiff
add json_object_object_add_ex() API
authorRainer Gerhards <rgerhards@adiscon.com>
Wed, 23 Sep 2015 07:08:49 +0000 (09:08 +0200)
committerRainer Gerhards <rgerhards@adiscon.com>
Wed, 23 Sep 2015 07:43:00 +0000 (09:43 +0200)
This provides more control over some detail aspects, many
of which are performance related.

json_object.c
json_object.h
linkhash.c
linkhash.h

index e06c7acc411f251cecbecc396c449ababdbb0e45..55f74699533e2f8bb81ccc70d0c5b7c2df803c1d 100644 (file)
@@ -355,7 +355,8 @@ static int json_object_object_to_json_string(struct json_object* jso,
 
 static void json_object_lh_entry_free(struct lh_entry *ent)
 {
-       free(ent->k);
+       if (!ent->k_is_constant)
+               free(ent->k);
        json_object_put((struct json_object*)ent->v);
 }
 
@@ -396,6 +397,31 @@ struct lh_table* json_object_get_object(struct json_object *jso)
        }
 }
 
+void json_object_object_add_ex(struct json_object* jso,
+       const char *const key,
+       struct json_object *const val,
+       const unsigned opts)
+{
+       // We lookup the entry and replace the value, rather than just deleting
+       // and re-adding it, so the existing key remains valid.
+       json_object *existing_value = NULL;
+       struct lh_entry *existing_entry;
+       const unsigned long hash = lh_get_hash(jso->o.c_object, (void*)key);
+       existing_entry = (opts & JSON_C_OBJECT_ADD_KEY_IS_NEW) ? NULL : 
+                             lh_table_lookup_entry_w_hash(jso->o.c_object, (void*)key, hash);
+       if (!existing_entry)
+       {
+               void *const k = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT) ?
+                                       (void*)key : strdup(key);
+               lh_table_insert_w_hash(jso->o.c_object, k, val, hash, opts);
+               return;
+       }
+       existing_value = (void *)existing_entry->v;
+       if (existing_value)
+               json_object_put(existing_value);
+       existing_entry->v = val;
+}
+
 void json_object_object_add(struct json_object* jso, const char *key,
                            struct json_object *val)
 {
@@ -407,7 +433,7 @@ void json_object_object_add(struct json_object* jso, const char *key,
        existing_entry = lh_table_lookup_entry_w_hash(jso->o.c_object, (void*)key, hash);
        if (!existing_entry)
        {
-               lh_table_insert_w_hash(jso->o.c_object, strdup(key), val, hash);
+               lh_table_insert_w_hash(jso->o.c_object, strdup(key), val, hash, 0);
                return;
        }
        existing_value = (void *)existing_entry->v;
index 0dca0b1e3fe964e5f0a0330e873e74d4b0881012..d42c365db9b7ae1e6b451ac0f475f148c3444085 100644 (file)
@@ -55,6 +55,36 @@ extern "C" {
  */
 #define JSON_C_TO_STRING_NOZERO     (1<<2)
 
+/**
+ * A flag for the json_object_object_add_ex function which
+ * causes the value to be added without a check if it already exists.
+ * Note: it is the responsibilty of the caller to ensure that no
+ * key is added multiple times. If this is done, results are
+ * unpredictable. While this option is somewhat dangerous, it
+ * permits potentially large performance savings in code that
+ * knows for sure the key values are unique (e.g. because the
+ * code adds a well-known set of constant key values).
+ */
+#define JSON_C_OBJECT_ADD_KEY_IS_NEW (1<<1)
+/**
+ * A flag for the json_object_object_add_ex function which
+ * flags the key as being constant memory. This means that
+ * the key will NOT be copied via strdup(), resulting in a
+ * potentially huge performance win (malloc, strdup and
+ * free are usually performance hogs). It is acceptable to
+ * use this flag for keys in non-constant memory blocks if
+ * the caller ensure that the memory holding the key lives
+ * longer than the corresponding json object. However, this
+ * is somewhat dangerous and should only be done if really
+ * justified.
+ * The general use-case for this flag is cases where the
+ * key is given as a real constant value in the function
+ * call, e.g. as in
+ *   json_object_object_add_ex(obj, "ip", json,
+ *       JSON_C_OBJECT_KEY_IS_CONSTANT);
+ */
+#define JSON_C_OBJECT_KEY_IS_CONSTANT (1<<2)
+
 #undef FALSE
 #define FALSE ((json_bool)0)
 
@@ -275,6 +305,22 @@ extern int json_object_object_length(struct json_object* obj);
 extern void json_object_object_add(struct json_object* obj, const char *key,
                                   struct json_object *val);
 
+/** Add an object field to a json_object of type json_type_object
+ *
+ * The semantics are identical to json_object_object_add, except that an
+ * additional flag fields gives you more control over some detail aspects
+ * of processing. See the description of JSON_C_OBJECT_ADD_* flags for more
+ * details.
+ *
+ * @param obj the json_object instance
+ * @param key the object field name (a private copy will be duplicated)
+ * @param val a json_object or NULL member to associate with the given field
+ * @param opts process-modifying options. To specify multiple options, use 
+ *             arithmetic or (OPT1|OPT2)
+ */
+extern void json_object_object_add_ex(struct json_object* obj, const char *key,
+                                  struct json_object *val, const unsigned opts);
+
 /** Get the json_object associate with a given object field
  *
  * *No* reference counts will be changed.  There is no need to manually adjust
index b4763cfc5724a2444276cfc3da12fab239753298..f89859ee16c08b3f275645e70d67f5f11f21fd84 100644 (file)
@@ -490,7 +490,7 @@ void lh_table_free(struct lh_table *t)
 }
 
 
-int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const unsigned long h)
+int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const unsigned long h, const unsigned opts)
 {
        unsigned long n;
 
@@ -506,6 +506,7 @@ int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const uns
        }
 
        t->table[n].k = k;
+       t->table[n].k_is_constant = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT);
        t->table[n].v = v;
        t->count++;
 
@@ -523,7 +524,7 @@ int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const uns
 }
 int lh_table_insert(struct lh_table *t, void *k, const void *v)
 {
-       return lh_table_insert_w_hash(t, k, v, lh_get_hash(t, k));
+       return lh_table_insert_w_hash(t, k, v, lh_get_hash(t, k), 0);
 }
 
 
index 66f2d9785163499ce8500d7240064b5b88008e51..f967bf9ad517cfcd6f9f29f2d3b1b8feb2807dcb 100644 (file)
@@ -64,6 +64,7 @@ struct lh_entry {
         * The key.
         */
        void *k;
+       int k_is_constant;
        /**
         * The value.
         */
@@ -241,8 +242,9 @@ extern int lh_table_insert(struct lh_table *t, void *k, const void *v);
  * @param k a pointer to the key to insert.
  * @param v a pointer to the value to insert.
  * @param h hash value of the key to insert
+ * @param opts opts, a subset of JSON_OBJECT_ADD_* flags is supported
  */
-extern int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const unsigned long h);
+extern int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const unsigned long h, const unsigned opts);
 
 
 /**