summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/json.c9
-rw-r--r--lib/shash.c23
2 files changed, 30 insertions, 2 deletions
diff --git a/lib/json.c b/lib/json.c
index 07ca87b21..603fd1df8 100644
--- a/lib/json.c
+++ b/lib/json.c
@@ -280,6 +280,12 @@ json_object_put(struct json *json, const char *name, struct json *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)
{
json_object_put(json, name, json_string_create(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);
diff --git a/lib/shash.c b/lib/shash.c
index 318a30ffc..a8433629a 100644
--- a/lib/shash.c
+++ b/lib/shash.c
@@ -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