summaryrefslogtreecommitdiff
path: root/json_object.c
diff options
context:
space:
mode:
authorAlexandru Ardelean <ardeleanalex@gmail.com>2017-06-16 10:05:32 +0300
committerAlexandru Ardelean <ardeleanalex@gmail.com>2017-11-27 16:17:48 +0200
commitbf80d5ad0ed3b34c54d6fce47edb16ed704f47bc (patch)
treeaf34da92caa2fce253845b18ca424190365ba119 /json_object.c
parent91662a5b69a2ca5102e286b77e76e39736db17a3 (diff)
downloadjson-c-bf80d5ad0ed3b34c54d6fce47edb16ed704f47bc.tar.gz
json_object: implement json_object_deep_copy()
Because doing `json_tokener_parse(json_object_get_string(src))` feels sloppy, dirty, and makes me want to cry at night sometimes. Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>
Diffstat (limited to 'json_object.c')
-rw-r--r--json_object.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/json_object.c b/json_object.c
index df20de1..3099c27 100644
--- a/json_object.c
+++ b/json_object.c
@@ -1313,3 +1313,106 @@ int json_object_equal(struct json_object* jso1, struct json_object* jso2)
return 0;
}
+static int json_object_copy_serializer_data(struct json_object *src, struct json_object *dst)
+{
+ /* FIXME: this is shared between copies ; maybe add a `_user_copy` cb here */
+ dst->_userdata = src->_userdata;
+ dst->_to_json_string = src->_to_json_string;
+ dst->_user_delete = src->_user_delete;
+ return 0;
+}
+
+static int json_object_deep_copy_recursive(struct json_object *src, struct json_object **dst)
+{
+ struct json_object *jso = NULL;
+ struct json_object_iter iter;
+ size_t i;
+
+ if (!src || !dst) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ switch (src->o_type) {
+ case json_type_boolean:
+ *dst = json_object_new_boolean(src->o.c_boolean);
+ break;
+
+ case json_type_double:
+ *dst = json_object_new_double(src->o.c_double);
+ break;
+
+ case json_type_int:
+ *dst = json_object_new_int64(src->o.c_int64);
+ break;
+
+ case json_type_string:
+ *dst = json_object_new_string(get_string_component(src));
+ break;
+
+ case json_type_object:
+ *dst = json_object_new_object();
+ if (!*dst) {
+ errno = ENOMEM;
+ return -1;
+ }
+ json_object_object_foreachC(src, iter) {
+ /* This handles the `json_type_null` case */
+ if (!iter.val)
+ jso = NULL;
+ else if (json_object_deep_copy_recursive(iter.val, &jso) < 0)
+ return -1;
+ if (json_object_object_add(*dst, iter.key, jso) < 0)
+ return -1;
+ }
+ break;
+
+ case json_type_array:
+ *dst = json_object_new_array();
+ if (!*dst) {
+ errno = ENOMEM;
+ return -1;
+ }
+ for (i = 0; i < json_object_array_length(src); i++) {
+ struct json_object *jso1 = json_object_array_get_idx(src, i);
+ /* This handles the `json_type_null` case */
+ if (!jso1)
+ jso = NULL;
+ else if (json_object_deep_copy_recursive(jso1, &jso) < 0)
+ return -1;
+ if (json_object_array_add(*dst, jso) < 0)
+ return -1;
+ }
+ break;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ };
+
+ /* errno should be set by the function that faulted */
+ if (!*dst)
+ return -1;
+
+ return json_object_copy_serializer_data(src, *dst);
+}
+
+int json_object_deep_copy(struct json_object *src, struct json_object **dst)
+{
+ int rc;
+
+ /* Check if arguments are sane ; *dst must not point to a non-NULL object */
+ if (!src || !dst || *dst) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ rc = json_object_deep_copy_recursive(src, dst);
+ if (rc < 0) {
+ json_object_put(*dst);
+ *dst = NULL;
+ }
+
+ return rc;
+}
+