diff --git a/src/jq_test.c b/src/jq_test.c index 94ffee69d9..a83640c4fa 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -492,96 +492,17 @@ static void jv_test() { } { - assert(jv_equal( - jv_paths( - jv_parse("{" - "\"key\":[" - "{\"this\":{\"some\":true}}," - "false," - "null," - "10," - "[true]" - "]" - "}") - ), - jv_parse("[" - "[\"key\"]," - "[\"key\", 0]," - "[\"key\", 0, \"this\"]," - "[\"key\", 0, \"this\", \"some\"]," - "[\"key\", 1]," - "[\"key\", 2]," - "[\"key\", 3]," - "[\"key\", 4]," - "[\"key\", 4, 0]" - "]") - )); + jv test_unshared = JV_OBJECT(jv_string("some"), JV_ARRAY(jv_string("other"), jv_true())); - } - - { - assert(jv_equal( - jv_addpath( - jv_parse("{" - "\"key\":{" - "\"some\":{" - "\"test\":\"value\"" - "}," - "\"other\":\"thing\"" - "}" - "}"), - JV_ARRAY(jv_string("key")), - jv_parse("{" - "\"some\":{" - "\"test\":\"other\"" - "}," - "\"added\":\"thing\"" - "}") - ), - jv_parse("{" - "\"key\":{" - "\"some\":{" - "\"test\":\"other\"" - "}," - "\"other\":\"thing\"," - "\"added\":\"thing\"" - "}" - "}") - ) - ); + assert(jv_is_unshared(test_unshared)); + jv_free(test_unshared); - } - - { jv initial = jv_parse("{\"test\":[{\"some\":\"value\"}, 1, true, false, null]}"); jv new = jv_unshare(jv_copy(initial)); assert(jv_equal(jv_copy(initial), jv_copy(new))); - assert(!jv_identical(jv_copy(initial), jv_copy(new))); - - jv paths = jv_paths(jv_copy(initial)); - - size_t paths_length = jv_array_length(jv_copy(paths)); - - for(size_t i = 0; i < paths_length; i++){ - jv path_i = jv_array_get(jv_copy(paths), i); - assert(!jv_identical( - jv_getpath( - jv_copy(initial), - jv_copy(path_i) - ), - jv_getpath( - jv_copy(new), - jv_copy(path_i) - ) - )); - - jv_free(path_i); - } - + assert(jv_is_unshared(new)); jv_free(initial); jv_free(new); - jv_free(paths); - } } diff --git a/src/jv.c b/src/jv.c index 770234df18..cc42ea226a 100644 --- a/src/jv.c +++ b/src/jv.c @@ -1865,11 +1865,13 @@ jv jv_object_iter_value(jv object, int iter) { jv jv_unshare(jv input){ switch(jv_get_kind(input)){ case JV_KIND_INVALID: - if(!jv_invalid_has_msg(jv_copy(input))){ - jv_free(input); - return jv_invalid(); + { + if(!jv_invalid_has_msg(jv_copy(input))){ + jv_free(input); + return jv_invalid(); + } + return jv_invalid_with_msg(jv_unshare(jv_invalid_get_msg(jv_copy(input)))); } - return jv_invalid_with_msg(jv_unshare(jv_invalid_get_msg(jv_copy(input)))); case JV_KIND_OBJECT: { jv keys = jv_keys(jv_copy(input)); @@ -1943,6 +1945,49 @@ jv jv_unshare(jv input){ } } +int jv_is_unshared(jv a){ + if(jv_get_refcnt(a) != 1){ + fprintf(stderr, "input refcnt != 1\n"); + return 1; + } + if(jv_get_kind(a) == JV_KIND_OBJECT){ + jv keys = jv_keys(jv_copy(a)); + size_t keys_length = jv_array_length(jv_copy(keys)); + for(size_t i = 0; i < keys_length; i++){ + jv key = jv_array_get(jv_copy(keys), i); + if(jv_get_refcnt(key) > 3){ + fprintf(stderr, "key in object does not have refcnt 1, %d\n", jv_get_refcnt(key)); + jv_free(key); + jv_free(keys); + return 0; + } + + jv value = jv_object_get(jv_copy(a), key); + jv_free(value); + if(!jv_is_unshared(value)){ + fprintf(stderr, "failed on object\n"); + jv_free(keys); + return 0; + } + } + + jv_free(keys); + + }else if(jv_get_kind(a) == JV_KIND_ARRAY){ + size_t a_length = jv_array_length(jv_copy(a)); + for(size_t i = 0; i < a_length; i++){ + jv value = jv_array_get(jv_copy(a), i); + jv_free(value); + if(!jv_is_unshared(value)){ + fprintf(stderr, "failed on array value\n"); + return 0; + } + } + } + + return 1; +} + jv jv_copy(jv j) { if (JVP_IS_ALLOCATED(j)) { jvp_refcnt_inc(j.u.ptr); diff --git a/src/jv.h b/src/jv.h index 487eba030d..d31f5b1ff8 100644 --- a/src/jv.h +++ b/src/jv.h @@ -53,6 +53,7 @@ static int jv_is_valid(jv x) { return jv_get_kind(x) != JV_KIND_INVALID; } //jv_unshare() creates a deep copy of the input aka the content of the output will be identical to the input, but no shared memory exists between them jv jv_unshare(jv); +int jv_is_unshared(jv); jv jv_copy(jv); void jv_free(jv); @@ -258,10 +259,8 @@ jv jv_get(jv, jv); jv jv_set(jv, jv, jv); jv jv_has(jv, jv); jv jv_setpath(jv, jv, jv); -jv jv_addpath(jv, jv, jv); jv jv_getpath(jv, jv); jv jv_delpaths(jv, jv); -jv jv_paths(jv); jv jv_keys(jv /*object or array*/); jv jv_keys_unsorted(jv /*object or array*/); int jv_cmp(jv, jv); diff --git a/src/jv_aux.c b/src/jv_aux.c index a1fa00dcc2..24ffb032c0 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -427,69 +427,7 @@ jv jv_setpath(jv root, jv path, jv value) { return jv_set(root, pathcurr, jv_setpath(subroot, pathrest, value)); } -jv jv_addpath(jv root, jv path, jv add){ - if(jv_get_kind(path) != JV_KIND_ARRAY || !jv_is_valid(add)){ - jv_free(root); - jv_free(path); - jv_free(add); - return jv_invalid(); - } - - if(jv_get_kind(root) != JV_KIND_OBJECT && jv_get_kind(root) != JV_KIND_ARRAY){ - jv_free(root); - - if(!jv_equal(jv_copy(path), jv_array())){ - jv_free(path); - jv_free(add); - return jv_invalid(); - } - - jv_free(path); - - return add; - } - - if(!jv_equal(jv_copy(path), jv_array())){ - return jv_setpath(root, path, jv_addpath(jv_getpath(jv_copy(root), jv_copy(path)), jv_array(), add)); - } - - jv root_paths = jv_paths(jv_copy(root)); - jv add_paths = jv_paths(jv_copy(add)); - - size_t add_paths_length = jv_array_length(jv_copy(add_paths)); - - for(size_t i = 0; i < add_paths_length; i++){ - jv add_path = jv_array_get(jv_copy(add_paths), i); - jv add_path_value = jv_getpath(jv_copy(add), jv_copy(add_path)); - - if(!jv_is_valid(add_path_value) || jv_get_kind(add_path_value) == JV_KIND_NULL){ - jv_free(root); - jv_free(path); - jv_free(add); - jv_free(root_paths); - jv_free(add_paths); - jv_free(add_path); - jv_free(add_path_value); - return jv_invalid(); - } - - if(jv_get_kind(add_path_value) == JV_KIND_OBJECT || jv_get_kind(add_path_value) == JV_KIND_ARRAY){ - jv_free(add_path); - jv_free(add_path_value); - continue; - } - - root = jv_setpath(root, add_path, add_path_value); - } - - jv_free(path); - jv_free(add); - - jv_free(root_paths); - jv_free(add_paths); - - return root; -} + jv jv_getpath(jv root, jv path) { if (jv_get_kind(path) != JV_KIND_ARRAY) { @@ -602,46 +540,6 @@ static int string_cmp(const void* pa, const void* pb){ return r; } -jv jv_paths(jv input){ - if(jv_get_kind(input) != JV_KIND_OBJECT && jv_get_kind(input) != JV_KIND_ARRAY){ - jv_free(input); - return jv_invalid(); - } - - jv keys = jv_keys(jv_copy(input)); - - size_t keys_length = jv_array_length(jv_copy(keys)); - - jv output = jv_array(); - - for(size_t i = 0; i < keys_length; i++){ - jv key = jv_array_get(jv_copy(keys), i); - jv insert_paths = jv_paths(jv_getpath(jv_copy(input), JV_ARRAY(jv_copy(key)))); - - output = jv_array_append(output, JV_ARRAY(jv_copy(key))); - - if(jv_get_kind(insert_paths) == JV_KIND_INVALID){ - jv_free(insert_paths); - jv_free(key); - - continue; - } - - size_t paths_length = jv_array_length(jv_copy(insert_paths)); - - for(size_t j = 0; j < paths_length; j++){ - output = jv_array_append(output, jv_array_concat(JV_ARRAY(jv_copy(key)), jv_array_get(jv_copy(insert_paths), j))); - } - - jv_free(key); - jv_free(insert_paths); - } - - jv_free(input); - jv_free(keys); - - return output; -} jv jv_keys_unsorted(jv x) { if (jv_get_kind(x) != JV_KIND_OBJECT)