]> git.proxmox.com Git - ovs.git/commitdiff
json: Avoid extra memory allocation and string copy parsing object members.
authorBen Pfaff <blp@ovn.org>
Fri, 23 Mar 2018 22:46:58 +0000 (15:46 -0700)
committerBen Pfaff <blp@ovn.org>
Sat, 31 Mar 2018 19:22:58 +0000 (12:22 -0700)
Until now, every time the JSON parser added an object member, it made an
extra copy of the member name and then freed the original copy.  This is
wasteful, so this commit eliminates the extra copy.

Signed-off-by: Ben Pfaff <blp@ovn.org>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
include/openvswitch/json.h
include/openvswitch/shash.h
lib/json.c
lib/shash.c

index 61b9a02cfc197506cb3e0b0d7fe0003643c17d13..bcf6a27826aeeaf0f1d42979793b09cc0af691b5 100644 (file)
@@ -91,6 +91,7 @@ struct json *json_array_create_3(struct json *, struct json *, struct json *);
 
 struct json *json_object_create(void);
 void json_object_put(struct json *, const char *name, struct json *value);
+void json_object_put_nocopy(struct json *, char *name, struct json *value);
 void json_object_put_string(struct json *,
                             const char *name, const char *value);
 void json_object_put_format(struct json *,
index afc482364f2490a2cbb3db27d54ab4b4f3466ae4..c249e13e1f28af77703d1fe2bb3df1da7e01c0b9 100644 (file)
@@ -62,6 +62,7 @@ struct shash_node *shash_add_nocopy(struct shash *, char *, const void *);
 bool shash_add_once(struct shash *, const char *, const void *);
 void shash_add_assert(struct shash *, const char *, const void *);
 void *shash_replace(struct shash *, const char *, const void *data);
+void *shash_replace_nocopy(struct shash *, char *name, const void *data);
 void shash_delete(struct shash *, struct shash_node *);
 char *shash_steal(struct shash *, struct shash_node *);
 struct shash_node *shash_find(const struct shash *, const char *);
index 07ca87b2130fc0352027abe6e04df629937b86ca..603fd1df8b6af60f6d196c13db09b6a302ed4c15 100644 (file)
@@ -279,6 +279,12 @@ json_object_put(struct json *json, const char *name, struct json *value)
     json_destroy(shash_replace(json->u.object, name, value));
 }
 
+void
+json_object_put_nocopy(struct json *json, char *name, struct json *value)
+{
+    json_destroy(shash_replace_nocopy(json->u.object, name, value));
+}
+
 void
 json_object_put_string(struct json *json, const char *name, const char *value)
 {
@@ -1217,8 +1223,7 @@ json_parser_put_value(struct json_parser *p, struct json *value)
 {
     struct json_parser_node *node = json_parser_top(p);
     if (node->json->type == JSON_OBJECT) {
-        json_object_put(node->json, p->member_name, value);
-        free(p->member_name);
+        json_object_put_nocopy(node->json, p->member_name, value);
         p->member_name = NULL;
     } else if (node->json->type == JSON_ARRAY) {
         json_array_add(node->json, value);
index 318a30ffc0f057682cc2358d1c5b77b7d2f6efe1..a8433629ab84cf4be1c808a1e3fabc47c4b3091b 100644 (file)
@@ -166,6 +166,29 @@ shash_replace(struct shash *sh, const char *name, const void *data)
     }
 }
 
+/* Searches for 'name' in 'sh'.  If it does not already exist, adds it along
+ * with 'data' and returns NULL.  If it does already exist, replaces its data
+ * by 'data' and returns the data that it formerly contained.
+ *
+ * Takes ownership of 'name'. */
+void *
+shash_replace_nocopy(struct shash *sh, char *name, const void *data)
+{
+    size_t hash = hash_name(name);
+    struct shash_node *node;
+
+    node = shash_find__(sh, name, strlen(name), hash);
+    if (!node) {
+        shash_add_nocopy__(sh, name, data, hash);
+        return NULL;
+    } else {
+        free(name);
+        void *old_data = node->data;
+        node->data = CONST_CAST(void *, data);
+        return old_data;
+    }
+}
+
 /* Deletes 'node' from 'sh' and frees the node's name.  The caller is still
  * responsible for freeing the node's data, if necessary. */
 void