From 90492ec1a8b98f120e793a91821a83075259b25a Mon Sep 17 00:00:00 2001 From: maximilian Date: Sun, 18 Feb 2024 23:20:54 +0100 Subject: [PATCH 01/20] implement borrowing --- src/jv.c | 34 +++++++++++++++++----------------- src/jv.h | 14 +++++++++++--- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/jv.c b/src/jv.c index e23d8ec124..d67b5220e6 100644 --- a/src/jv.c +++ b/src/jv.c @@ -114,10 +114,10 @@ const char* jv_kind_name(jv_kind k) { return ""; } -const jv JV_NULL = {JVP_FLAGS_NULL, 0, 0, 0, {0}}; -const jv JV_INVALID = {JVP_FLAGS_INVALID, 0, 0, 0, {0}}; -const jv JV_FALSE = {JVP_FLAGS_FALSE, 0, 0, 0, {0}}; -const jv JV_TRUE = {JVP_FLAGS_TRUE, 0, 0, 0, {0}}; +const jv JV_NULL = {JVP_FLAGS_NULL, 0, 0, 0, 0, {0}}; +const jv JV_INVALID = {JVP_FLAGS_INVALID, 0, 0, 0, 0, {0}}; +const jv JV_FALSE = {JVP_FLAGS_FALSE, 0, 0, 0, 0, {0}}; +const jv JV_TRUE = {JVP_FLAGS_TRUE, 0, 0, 0, 0, {0}}; jv jv_true() { return JV_TRUE; @@ -151,7 +151,7 @@ jv jv_invalid_with_msg(jv err) { i->refcnt = JV_REFCNT_INIT; i->errmsg = err; - jv x = {JVP_FLAGS_INVALID_MSG, 0, 0, 0, {&i->refcnt}}; + jv x = {JVP_FLAGS_INVALID_MSG, 0, 0, 0, 0, {&i->refcnt}}; return x; } @@ -590,7 +590,7 @@ static jv jvp_literal_number_new(const char * literal) { return JV_INVALID; } - jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, JV_NUMBER_SIZE_INIT, {&n->refcnt}}; + jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, 0, JV_NUMBER_SIZE_INIT, {&n->refcnt}}; return r; } @@ -674,7 +674,7 @@ jv jv_number(double x) { #else JV_KIND_NUMBER, #endif - 0, 0, 0, {.number = x} + 0, 0, 0, 0, {.number = x} }; return j; } @@ -806,7 +806,7 @@ static jvp_array* jvp_array_alloc(unsigned size) { } static jv jvp_array_new(unsigned size) { - jv r = {JVP_FLAGS_ARRAY, 0, 0, 0, {&jvp_array_alloc(size)->refcnt}}; + jv r = {JVP_FLAGS_ARRAY, 0, 0, 0, 0, {&jvp_array_alloc(size)->refcnt}}; return r; } @@ -869,7 +869,7 @@ static jv* jvp_array_write(jv* a, int i) { } new_array->length = new_length; jvp_array_free(*a); - jv new_jv = {JVP_FLAGS_ARRAY, 0, 0, new_length, {&new_array->refcnt}}; + jv new_jv = {JVP_FLAGS_ARRAY, 0, 0, 0, new_length, {&new_array->refcnt}}; *a = new_jv; return &new_array->elements[i]; } @@ -1091,7 +1091,7 @@ static jv jvp_string_copy_replace_bad(const char* data, uint32_t length) { length = out - s->data; s->data[length] = 0; s->length_hashed = length << 1; - jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, 0, {&s->refcnt}}; return r; } @@ -1102,7 +1102,7 @@ static jv jvp_string_new(const char* data, uint32_t length) { if (data != NULL) memcpy(s->data, data, length); s->data[length] = 0; - jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, 0, {&s->refcnt}}; return r; } @@ -1110,7 +1110,7 @@ static jv jvp_string_empty_new(uint32_t length) { jvp_string* s = jvp_string_alloc(length); s->length_hashed = 0; memset(s->data, 0, length); - jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, 0, {&s->refcnt}}; return r; } @@ -1153,7 +1153,7 @@ static jv jvp_string_append(jv string, const char* data, uint32_t len) { memcpy(news->data + currlen, data, len); news->data[currlen + len] = 0; jvp_string_free(string); - jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&news->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, 0, {&news->refcnt}}; return r; } } @@ -1521,7 +1521,7 @@ static jv jvp_object_new(int size) { for (int i=0; irefcnt}}; + jv r = {JVP_FLAGS_OBJECT, 0, 0, 0, size, {&obj->refcnt}}; return r; } @@ -1862,14 +1862,14 @@ jv jv_object_iter_value(jv object, int iter) { /* * Memory management */ -jv jv_copy(jv j) { - if (JVP_IS_ALLOCATED(j)) { +jv jv__copy(jv j) { + if (JVP_IS_ALLOCATED(j) && !j.borrowed) { jvp_refcnt_inc(j.u.ptr); } return j; } -void jv_free(jv j) { +void jv__free(jv j) { switch(JVP_KIND(j)) { case JV_KIND_ARRAY: jvp_array_free(j); diff --git a/src/jv.h b/src/jv.h index 083509ec26..29b10b4c80 100644 --- a/src/jv.h +++ b/src/jv.h @@ -33,7 +33,8 @@ struct jv_refcnt; Really. Do not play with them. */ typedef struct { unsigned char kind_flags; - unsigned char pad_; + unsigned char pad_:7; + unsigned char borrowed:1; unsigned short offset; /* array offsets */ int size; union { @@ -51,8 +52,13 @@ jv_kind jv_get_kind(jv); const char* jv_kind_name(jv_kind); static int jv_is_valid(jv x) { return jv_get_kind(x) != JV_KIND_INVALID; } -jv jv_copy(jv); -void jv_free(jv); +void jv__free(jv); +jv jv__copy(jv); + +static inline jv jv_copy(jv a){if(a.borrowed) return a; return jv__copy(a);} +static inline void jv_free(jv a){if(!a.borrowed) jv__free(a);} + +static inline jv jv_borrow(jv a){a.borrowed = 1; return a;} int jv_get_refcnt(jv); @@ -70,6 +76,8 @@ jv jv_true(void); jv jv_false(void); jv jv_bool(int); +static inline jv jv_is_borrowed(jv a){if(a.borrowed) return jv_true(); return jv_false();} + jv jv_number(double); jv jv_number_with_literal(const char*); double jv_number_value(jv); From b8463a66e2af1749dc991e0e27feabfac06ddb38 Mon Sep 17 00:00:00 2001 From: maximilian Date: Tue, 20 Feb 2024 21:30:56 +0100 Subject: [PATCH 02/20] add jv_unborrow --- src/jv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jv.h b/src/jv.h index 29b10b4c80..26fed56513 100644 --- a/src/jv.h +++ b/src/jv.h @@ -59,6 +59,7 @@ static inline jv jv_copy(jv a){if(a.borrowed) return a; return jv__copy(a);} static inline void jv_free(jv a){if(!a.borrowed) jv__free(a);} static inline jv jv_borrow(jv a){a.borrowed = 1; return a;} +static inline jv jv_unborrow(jv a){a.borrowed = 0; return jv_copy(a);} int jv_get_refcnt(jv); From e6e90a31f302b9f7d64a3c4729ee65c0015b4cf4 Mon Sep 17 00:00:00 2001 From: maximilian Date: Tue, 20 Feb 2024 21:51:27 +0100 Subject: [PATCH 03/20] replace jv_copy with jv_unborrow in relevant functions in jv.c --- src/jv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/jv.c b/src/jv.c index d67b5220e6..e04ae6b0c5 100644 --- a/src/jv.c +++ b/src/jv.c @@ -164,7 +164,7 @@ jv jv_invalid_get_msg(jv inv) { jv x; if (JVP_HAS_FLAGS(inv, JVP_FLAGS_INVALID_MSG)) { - x = jv_copy(((jvp_invalid*)inv.u.ptr)->errmsg); + x = jv_unborrow(((jvp_invalid*)inv.u.ptr)->errmsg); } else { x = jv_null(); @@ -862,7 +862,7 @@ static jv* jvp_array_write(jv* a, int i) { int j; for (j = 0; j < jvp_array_length(*a); j++) { new_array->elements[j] = - jv_copy(array->elements[j + jvp_array_offset(*a)]); + jv_unborrow(array->elements[j + jvp_array_offset(*a)]); } for (; j < new_length; j++) { new_array->elements[j] = JV_NULL; @@ -974,7 +974,7 @@ jv jv_array_get(jv j, int idx) { jv* slot = jvp_array_read(j, idx); jv val; if (slot) { - val = jv_copy(*slot); + val = jv_unborrow(*slot); } else { val = jv_invalid(); } @@ -1636,8 +1636,8 @@ static jv jvp_object_unshare(jv object) { struct object_slot* new_slot = jvp_object_get_slot(new_object, i); *new_slot = *old_slot; if (jv_get_kind(old_slot->string) != JV_KIND_NULL) { - new_slot->string = jv_copy(old_slot->string); - new_slot->value = jv_copy(old_slot->value); + new_slot->string = jv_unborrow(old_slot->string); + new_slot->value = jv_unborrow(old_slot->value); } } From 9015331334b0de3f989aad8a5319682ef10cc1aa Mon Sep 17 00:00:00 2001 From: maximilian Date: Mon, 26 Feb 2024 11:44:47 +0100 Subject: [PATCH 04/20] adds testing --- src/jq_test.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/jv.h | 2 +- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/jq_test.c b/src/jq_test.c index 39456861a5..7c4d692c87 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -490,4 +490,66 @@ static void jv_test() { //jv_dump(jv_copy(o2), 0); printf("\n"); jv_free(o2); } + + /// Borrowing + { + jv d = jv_string("b"); + jv a = JV_ARRAY(jv_string("a"), jv_borrow(d)); + + jv i = jv_invalid_with_msg(jv_borrow(d)); + jv m = jv_invalid_get_msg(i); + assert(!jv_is_borrowed(m)); + jv_free(m); + + jv c = jv_array_get(jv_borrow(a), 1); + assert(!jv_is_borrowed(c)); + + jv c2 = jv_getpath(jv_borrow(a), JV_ARRAY(jv_number(1))); + assert(!jv_is_borrowed(c2)); + assert(jv_cmp(jv_borrow(c), jv_borrow(c2)) == 0); + jv_free(c); + jv_free(d); + jv_free(c2); + + jv b = jv_borrow(a); + assert(jv_is_borrowed(b)); + jv_free(b); + jv_free(b); + + assert(jv_equal(jv_copy(a), b)); + + //subject of potential debate + jv e = jv_array_concat(b, JV_ARRAY(jv_number(5))); + assert(!jv_is_borrowed(e)); + jv_free(e); + + jv_array_length(b); + jv k = jv_keys(b); + assert(!jv_is_borrowed(k)); + jv_free(k); + + //currently broken stuff + jv f = jv_array_append(b, jv_number(5)); + assert(!jv_is_borrowed(f)); + jv_free(f); + + jv g = jv_array_append(jv_array(), b); + assert(!jv_is_borrowed(g)); + g = jv_setpath(g, JV_ARRAY(jv_number(0)), jv_string("test")); + assert(!jv_is_borrowed(g)); + jv_free(g); + g = jv_setpath(b, JV_ARRAY(jv_number(1)), jv_string("some")); + assert(!jv_is_borrowed(g)); + jv_free(g); + + + b = jv_unborrow(b); + + jv_free(a); + + assert(jv_get_refcnt(a) == 1); + + jv_free(b); + + } } diff --git a/src/jv.h b/src/jv.h index 26fed56513..f578f428ec 100644 --- a/src/jv.h +++ b/src/jv.h @@ -77,7 +77,7 @@ jv jv_true(void); jv jv_false(void); jv jv_bool(int); -static inline jv jv_is_borrowed(jv a){if(a.borrowed) return jv_true(); return jv_false();} +static inline int jv_is_borrowed(jv a){return a.borrowed;} jv jv_number(double); jv jv_number_with_literal(const char*); From 1b8ec4043df69c5d73c943f9f2b294da08b5fa1d Mon Sep 17 00:00:00 2001 From: maximilian Date: Mon, 26 Feb 2024 11:51:28 +0100 Subject: [PATCH 05/20] fixes borowed outputs --- src/jv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jv.c b/src/jv.c index e04ae6b0c5..590a9880a6 100644 --- a/src/jv.c +++ b/src/jv.c @@ -996,6 +996,7 @@ jv jv_array_set(jv j, int idx, jv val) { jv* slot = jvp_array_write(&j, idx); jv_free(*slot); *slot = val; + if(jv_is_borrowed(j)) return jv_unborrow(j); return j; } @@ -1013,6 +1014,7 @@ jv jv_array_concat(jv a, jv b) { a = jv_array_append(a, elem); } jv_free(b); + if(jv_is_borrowed(a)) return jv_unborrow(a); return a; } From d82f5d475e0331f87cf392da783e6093c8612cf8 Mon Sep 17 00:00:00 2001 From: maximilian Date: Mon, 26 Feb 2024 16:11:41 +0100 Subject: [PATCH 06/20] fixes jv_get and jv_set (setpath still broken) --- src/jq_test.c | 24 +++++++++++++++++------- src/jv_aux.c | 4 ++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/jq_test.c b/src/jq_test.c index 7c4d692c87..1065cd3d74 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -528,20 +528,31 @@ static void jv_test() { assert(!jv_is_borrowed(k)); jv_free(k); - //currently broken stuff jv f = jv_array_append(b, jv_number(5)); assert(!jv_is_borrowed(f)); jv_free(f); jv g = jv_array_append(jv_array(), b); assert(!jv_is_borrowed(g)); - g = jv_setpath(g, JV_ARRAY(jv_number(0)), jv_string("test")); - assert(!jv_is_borrowed(g)); - jv_free(g); - g = jv_setpath(b, JV_ARRAY(jv_number(1)), jv_string("some")); - assert(!jv_is_borrowed(g)); jv_free(g); + jv a1 = jv_parse("{\"key\":\"value\"}"); + jv p = jv_set(jv_borrow(a1), jv_string("key"), jv_string("other")); + assert(!jv_is_borrowed(p)); + jv_free(p); + + jv q = jv_get(jv_borrow(a1), jv_string("key")); + assert(!jv_is_borrowed(q)); + jv_free(q); + + jv_free(a1); + + + + jv h = jv_setpath(b, JV_ARRAY(jv_number(1)), jv_string("some")); + assert(!jv_is_borrowed(h)); + jv_free(h); + b = jv_unborrow(b); @@ -550,6 +561,5 @@ static void jv_test() { assert(jv_get_refcnt(a) == 1); jv_free(b); - } } diff --git a/src/jv_aux.c b/src/jv_aux.c index 6004799c6a..4258347e6f 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -151,6 +151,8 @@ jv jv_get(jv t, jv k) { jv_free(t); jv_free(k); } + + if(jv_is_borrowed(v)) return jv_unborrow(v); return v; } @@ -158,6 +160,7 @@ jv jv_set(jv t, jv k, jv v) { if (!jv_is_valid(v)) { jv_free(t); jv_free(k); + if(jv_is_borrowed(v)) return jv_unborrow(v); return v; } int isnull = jv_get_kind(t) == JV_KIND_NULL; @@ -233,6 +236,7 @@ jv jv_set(jv t, jv k, jv v) { jv_free(v); t = err; } + if(jv_is_borrowed(t)) return jv_unborrow(t); return t; } From 93553783a75dcd424698ea41c2ae8f214c1e4b2d Mon Sep 17 00:00:00 2001 From: maximilian Date: Mon, 26 Feb 2024 17:25:39 +0100 Subject: [PATCH 07/20] fixes issues with borrowing. Important note: jv_borrow is unsafe in that your borrowed reference can outlive the owned value! No real mitigation possible --- src/jq_test.c | 7 ++++--- src/jv.c | 2 ++ src/jv_aux.c | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/jq_test.c b/src/jq_test.c index 1065cd3d74..c61a32511b 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -508,7 +508,6 @@ static void jv_test() { assert(!jv_is_borrowed(c2)); assert(jv_cmp(jv_borrow(c), jv_borrow(c2)) == 0); jv_free(c); - jv_free(d); jv_free(c2); jv b = jv_borrow(a); @@ -518,7 +517,6 @@ static void jv_test() { assert(jv_equal(jv_copy(a), b)); - //subject of potential debate jv e = jv_array_concat(b, JV_ARRAY(jv_number(5))); assert(!jv_is_borrowed(e)); jv_free(e); @@ -547,7 +545,9 @@ static void jv_test() { jv_free(a1); - + jv res = jv_array_get(b, 1); + assert(!jv_is_borrowed(res)); + jv_free(res); jv h = jv_setpath(b, JV_ARRAY(jv_number(1)), jv_string("some")); assert(!jv_is_borrowed(h)); @@ -561,5 +561,6 @@ static void jv_test() { assert(jv_get_refcnt(a) == 1); jv_free(b); + jv_free(d); } } diff --git a/src/jv.c b/src/jv.c index 590a9880a6..342ce5c628 100644 --- a/src/jv.c +++ b/src/jv.c @@ -1775,6 +1775,7 @@ jv jv_object_set(jv object, jv key, jv value) { jv* slot = jvp_object_write(&object, key); jv_free(*slot); *slot = value; + if(jv_is_borrowed(object)) return jv_unborrow(object); return object; } @@ -1783,6 +1784,7 @@ jv jv_object_delete(jv object, jv key) { assert(JVP_HAS_KIND(key, JV_KIND_STRING)); jvp_object_delete(&object, key); jv_free(key); + if(jv_is_borrowed(object)) return jv_unborrow(object); return object; } diff --git a/src/jv_aux.c b/src/jv_aux.c index 4258347e6f..add7f20183 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -389,11 +389,13 @@ jv jv_setpath(jv root, jv path, jv value) { if (!jv_is_valid(root)){ jv_free(value); jv_free(path); + if(jv_is_borrowed(root)) return jv_unborrow(root); return root; } if (jv_array_length(jv_copy(path)) == 0) { jv_free(path); jv_free(root); + if(jv_is_borrowed(value)) return jv_unborrow(value); return value; } jv pathcurr = jv_array_get(jv_copy(path), 0); From a7fa7087255844e8f4437b155a254ac5fa414947 Mon Sep 17 00:00:00 2001 From: maximilian Date: Tue, 27 Feb 2024 10:33:10 +0100 Subject: [PATCH 08/20] unborrows borrowed values before adding them to an array / object --- src/jq_test.c | 2 +- src/jv.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/jq_test.c b/src/jq_test.c index c61a32511b..8c8a140fd2 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -495,6 +495,7 @@ static void jv_test() { { jv d = jv_string("b"); jv a = JV_ARRAY(jv_string("a"), jv_borrow(d)); + jv_free(d); jv i = jv_invalid_with_msg(jv_borrow(d)); jv m = jv_invalid_get_msg(i); @@ -561,6 +562,5 @@ static void jv_test() { assert(jv_get_refcnt(a) == 1); jv_free(b); - jv_free(d); } } diff --git a/src/jv.c b/src/jv.c index 342ce5c628..a4ce6ac026 100644 --- a/src/jv.c +++ b/src/jv.c @@ -995,7 +995,11 @@ jv jv_array_set(jv j, int idx, jv val) { // copy/free of val,j coalesced jv* slot = jvp_array_write(&j, idx); jv_free(*slot); - *slot = val; + if(jv_is_borrowed(val)){ + *slot = jv_unborrow(val); + }else{ + *slot = val; + } if(jv_is_borrowed(j)) return jv_unborrow(j); return j; } @@ -1774,7 +1778,11 @@ jv jv_object_set(jv object, jv key, jv value) { // copy/free of object, key, value coalesced jv* slot = jvp_object_write(&object, key); jv_free(*slot); - *slot = value; + if(jv_is_borrowed(value)){ + *slot = jv_unborrow(value); + }else{ + *slot = value; + } if(jv_is_borrowed(object)) return jv_unborrow(object); return object; } From 72ef180495cae40c096cb34825edb871c94053c6 Mon Sep 17 00:00:00 2001 From: maximilian Date: Tue, 27 Feb 2024 10:43:34 +0100 Subject: [PATCH 09/20] fixes excessive copies --- src/jv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/jv.c b/src/jv.c index a4ce6ac026..7830afda41 100644 --- a/src/jv.c +++ b/src/jv.c @@ -1717,8 +1717,7 @@ static int jvp_object_equal(jv o1, jv o2) { if (jv_get_kind(slot->string) == JV_KIND_NULL) continue; jv* slot2 = jvp_object_read(o2, slot->string); if (!slot2) return 0; - // FIXME: do less refcounting here - if (!jv_equal(jv_copy(slot->value), jv_copy(*slot2))) return 0; + if (!jv_equal(jv_borrow(slot->value), jv_borrow(*slot2))) return 0; len1++; } return len1 == len2; From b80e4f0a025c8620e4c3bd3369b25efa08cbcf6b Mon Sep 17 00:00:00 2001 From: maximilian Date: Tue, 27 Feb 2024 12:39:53 +0100 Subject: [PATCH 10/20] adds jv_return --- src/jv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jv.h b/src/jv.h index f578f428ec..c0635936ca 100644 --- a/src/jv.h +++ b/src/jv.h @@ -60,6 +60,7 @@ static inline void jv_free(jv a){if(!a.borrowed) jv__free(a);} static inline jv jv_borrow(jv a){a.borrowed = 1; return a;} static inline jv jv_unborrow(jv a){a.borrowed = 0; return jv_copy(a);} +static inline jv jv_return(jv a){if(a.borrowed) return jv_unborrow(a); return a;} int jv_get_refcnt(jv); From 52c07c7eb9323a3056433517dcb0be738637d6f5 Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Wed, 28 Feb 2024 09:29:15 +0100 Subject: [PATCH 11/20] removes conditional unborrowing on read, fixes jv_object_delete() --- src/jq_test.c | 6 ++++++ src/jv.c | 23 ++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/jq_test.c b/src/jq_test.c index 8c8a140fd2..14e0b1e49c 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -562,5 +562,11 @@ static void jv_test() { assert(jv_get_refcnt(a) == 1); jv_free(b); + + jv o = JV_OBJECT(jv_string("some"), jv_string("value")); + jv od = jv_object_delete(jv_borrow(o), jv_string("some")); + jv ov = jv_getpath(o, JV_ARRAY(jv_string("some"))); + assert(jv_equal(ov, jv_string("value"))); + jv_free(od); } } diff --git a/src/jv.c b/src/jv.c index 7830afda41..2dc8eeda3f 100644 --- a/src/jv.c +++ b/src/jv.c @@ -149,7 +149,12 @@ typedef struct { jv jv_invalid_with_msg(jv err) { jvp_invalid* i = jv_mem_alloc(sizeof(jvp_invalid)); i->refcnt = JV_REFCNT_INIT; - i->errmsg = err; + + if(jv_is_borrowed(err)){ + i->errmsg = jv_unborrow(err); + }else{ + i->errmsg = err; + } jv x = {JVP_FLAGS_INVALID_MSG, 0, 0, 0, 0, {&i->refcnt}}; return x; @@ -164,7 +169,7 @@ jv jv_invalid_get_msg(jv inv) { jv x; if (JVP_HAS_FLAGS(inv, JVP_FLAGS_INVALID_MSG)) { - x = jv_unborrow(((jvp_invalid*)inv.u.ptr)->errmsg); + x = jv_copy(((jvp_invalid*)inv.u.ptr)->errmsg); } else { x = jv_null(); @@ -974,7 +979,7 @@ jv jv_array_get(jv j, int idx) { jv* slot = jvp_array_read(j, idx); jv val; if (slot) { - val = jv_unborrow(*slot); + val = jv_copy(*slot); } else { val = jv_invalid(); } @@ -1018,7 +1023,6 @@ jv jv_array_concat(jv a, jv b) { a = jv_array_append(a, elem); } jv_free(b); - if(jv_is_borrowed(a)) return jv_unborrow(a); return a; } @@ -1642,8 +1646,8 @@ static jv jvp_object_unshare(jv object) { struct object_slot* new_slot = jvp_object_get_slot(new_object, i); *new_slot = *old_slot; if (jv_get_kind(old_slot->string) != JV_KIND_NULL) { - new_slot->string = jv_unborrow(old_slot->string); - new_slot->value = jv_unborrow(old_slot->value); + new_slot->string = jv_copy(old_slot->string); + new_slot->value = jv_copy(old_slot->value); } } @@ -1786,12 +1790,13 @@ jv jv_object_set(jv object, jv key, jv value) { return object; } -jv jv_object_delete(jv object, jv key) { - assert(JVP_HAS_KIND(object, JV_KIND_OBJECT)); +jv jv_object_delete(jv input, jv key) { + assert(JVP_HAS_KIND(input, JV_KIND_OBJECT)); assert(JVP_HAS_KIND(key, JV_KIND_STRING)); + jv object = jv_unborrow(input); + jv_free(input); jvp_object_delete(&object, key); jv_free(key); - if(jv_is_borrowed(object)) return jv_unborrow(object); return object; } From e0a23735bc6e59175335397c66df39b56344b66e Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Wed, 28 Feb 2024 09:43:04 +0100 Subject: [PATCH 12/20] adds check for jv_array_slice --- src/jq_test.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/jq_test.c b/src/jq_test.c index 14e0b1e49c..1d333f21b0 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -563,10 +563,15 @@ static void jv_test() { jv_free(b); - jv o = JV_OBJECT(jv_string("some"), jv_string("value")); - jv od = jv_object_delete(jv_borrow(o), jv_string("some")); - jv ov = jv_getpath(o, JV_ARRAY(jv_string("some"))); - assert(jv_equal(ov, jv_string("value"))); - jv_free(od); + jv object = JV_OBJECT(jv_string("some"), jv_string("value")); + jv object_deleted = jv_object_delete(jv_borrow(o), jv_string("some")); + jv object_value = jv_getpath(object, JV_ARRAY(jv_string("some"))); + assert(jv_equal(object_value, jv_string("value"))); + jv_free(object_deleted); + + jv array = JV_ARRAY(jv_string("some"), jv_string("value")); + jv new_array = jv_array_slice(jv_borrow(array), 0, 1); + assert(jv_equal(array, JV_ARRAY(jv_string("some"), jv_string("value")))); + jv_free(new_array); } } From b73308171203beac35e000adfd19120244fa4189 Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Wed, 28 Feb 2024 10:15:41 +0100 Subject: [PATCH 13/20] fixes jv_object_set --- src/jq_test.c | 12 ++++++++++-- src/jv.c | 8 +++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/jq_test.c b/src/jq_test.c index 1d333f21b0..1503661efb 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -564,7 +564,7 @@ static void jv_test() { jv_free(b); jv object = JV_OBJECT(jv_string("some"), jv_string("value")); - jv object_deleted = jv_object_delete(jv_borrow(o), jv_string("some")); + jv object_deleted = jv_object_delete(jv_borrow(object), jv_string("some")); jv object_value = jv_getpath(object, JV_ARRAY(jv_string("some"))); assert(jv_equal(object_value, jv_string("value"))); jv_free(object_deleted); @@ -573,5 +573,13 @@ static void jv_test() { jv new_array = jv_array_slice(jv_borrow(array), 0, 1); assert(jv_equal(array, JV_ARRAY(jv_string("some"), jv_string("value")))); jv_free(new_array); - } + + + jv test = jv_string("value"); + object = JV_OBJECT(jv_string("some"), jv_borrow(test)); + jv_free(test); + jv object_set = jv_object_set(jv_borrow(object), jv_string("some"), jv_string("other")); + assert(jv_equal(object, JV_OBJECT(jv_string("some"), jv_string("value")))); + jv_free(object_set); +} } diff --git a/src/jv.c b/src/jv.c index 2dc8eeda3f..1b9aaeba36 100644 --- a/src/jv.c +++ b/src/jv.c @@ -1775,9 +1775,12 @@ int jv_object_has(jv object, jv key) { return res; } -jv jv_object_set(jv object, jv key, jv value) { - assert(JVP_HAS_KIND(object, JV_KIND_OBJECT)); +jv jv_object_set(jv input, jv key, jv value) { + assert(JVP_HAS_KIND(input, JV_KIND_OBJECT)); assert(JVP_HAS_KIND(key, JV_KIND_STRING)); + + jv object = jv_unborrow(input); + jv_free(input); // copy/free of object, key, value coalesced jv* slot = jvp_object_write(&object, key); jv_free(*slot); @@ -1786,7 +1789,6 @@ jv jv_object_set(jv object, jv key, jv value) { }else{ *slot = value; } - if(jv_is_borrowed(object)) return jv_unborrow(object); return object; } From c17308e19ac2aff0068b65d9eeffc984f94749a4 Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Wed, 28 Feb 2024 10:20:47 +0100 Subject: [PATCH 14/20] removes potential unborrow in jv_get --- src/jv_aux.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/jv_aux.c b/src/jv_aux.c index add7f20183..70983cc0b9 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -236,7 +236,6 @@ jv jv_set(jv t, jv k, jv v) { jv_free(v); t = err; } - if(jv_is_borrowed(t)) return jv_unborrow(t); return t; } From 715b4b4e81e9edbbdfe1a12b5b5eb1d63f63abee Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Wed, 28 Feb 2024 10:43:38 +0100 Subject: [PATCH 15/20] fixes jv_string_append_*() and jv_object_set() --- src/jq_test.c | 5 +++++ src/jv.c | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/jq_test.c b/src/jq_test.c index 1503661efb..0229254575 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -581,5 +581,10 @@ static void jv_test() { jv object_set = jv_object_set(jv_borrow(object), jv_string("some"), jv_string("other")); assert(jv_equal(object, JV_OBJECT(jv_string("some"), jv_string("value")))); jv_free(object_set); + + jv string = jv_string("value"); + jv other = jv_string_append_buf(jv_borrow(string), "test", 4); + assert(jv_equal(string, jv_string("value"))); + assert(jv_equal(other, jv_string("valuetest"))); } } diff --git a/src/jv.c b/src/jv.c index 1b9aaeba36..9b268eace9 100644 --- a/src/jv.c +++ b/src/jv.c @@ -1437,7 +1437,9 @@ jv jv_string_concat(jv a, jv b) { return a; } -jv jv_string_append_buf(jv a, const char* buf, int len) { +jv jv_string_append_buf(jv input, const char* buf, int len) { + jv a = jv_return(input); + if (jvp_utf8_is_valid(buf, buf+len)) { a = jvp_string_append(a, buf, len); } else { @@ -1447,7 +1449,9 @@ jv jv_string_append_buf(jv a, const char* buf, int len) { return a; } -jv jv_string_append_codepoint(jv a, uint32_t c) { +jv jv_string_append_codepoint(jv input, uint32_t c) { + jv a = jv_return(input); + char buf[5]; int len = jvp_utf8_encode(c, buf); a = jvp_string_append(a, buf, len); From 791b76d0bd09c6d3887941c9a6ac534f7b218e59 Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Thu, 29 Feb 2024 09:29:55 +0100 Subject: [PATCH 16/20] makes jq functions borrow-save --- src/execute.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/execute.c b/src/execute.c index 9ef8368329..806d0090dd 100644 --- a/src/execute.c +++ b/src/execute.c @@ -166,7 +166,7 @@ void stack_push(jq_state *jq, jv val) { assert(jv_is_valid(val)); jq->stk_top = stack_push_block(&jq->stk, jq->stk_top, sizeof(jv)); jv* sval = stack_block(&jq->stk, jq->stk_top); - *sval = val; + *sval = jv_return(val); } jv stack_pop(jq_state *jq) { @@ -1274,7 +1274,7 @@ jv jq_get_lib_dirs(jq_state *jq) { void jq_set_attrs(jq_state *jq, jv attrs) { assert(jv_get_kind(attrs) == JV_KIND_OBJECT); jv_free(jq->attrs); - jq->attrs = attrs; + jq->attrs = jv_return(attrs); } void jq_set_attr(jq_state *jq, jv attr, jv val) { @@ -1324,8 +1324,8 @@ jq_halt(jq_state *jq, jv exit_code, jv error_message) { assert(!jq->halted); jq->halted = 1; - jq->exit_code = exit_code; - jq->error_message = error_message; + jq->exit_code = jv_return(exit_code); + jq->error_message = jv_return(error_message); } int From bec08580441547d7e7744cc74b9fbdb42c18b33f Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Thu, 29 Feb 2024 09:49:14 +0100 Subject: [PATCH 17/20] fixed borrow-checking for jv_array_set --- src/jq_test.c | 6 ++++++ src/jv.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/jq_test.c b/src/jq_test.c index 0229254575..858b99d11a 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -586,5 +586,11 @@ static void jv_test() { jv other = jv_string_append_buf(jv_borrow(string), "test", 4); assert(jv_equal(string, jv_string("value"))); assert(jv_equal(other, jv_string("valuetest"))); + + array = JV_ARRAY(jv_string("test")); + jv array_out = jv_array_set(jv_borrow(array), 0, jv_string("value")); + assert(jv_equal(array, JV_ARRAY(jv_string("test")))); + assert(!jv_is_borrowed(array_out)); + jv_free(array_out); } } diff --git a/src/jv.c b/src/jv.c index 9b268eace9..59d93f6dc6 100644 --- a/src/jv.c +++ b/src/jv.c @@ -867,7 +867,7 @@ static jv* jvp_array_write(jv* a, int i) { int j; for (j = 0; j < jvp_array_length(*a); j++) { new_array->elements[j] = - jv_unborrow(array->elements[j + jvp_array_offset(*a)]); + jv_copy(array->elements[j + jvp_array_offset(*a)]); } for (; j < new_length; j++) { new_array->elements[j] = JV_NULL; @@ -990,6 +990,8 @@ jv jv_array_get(jv j, int idx) { jv jv_array_set(jv j, int idx, jv val) { assert(JVP_HAS_KIND(j, JV_KIND_ARRAY)); + j = jv_return(j); + if (idx < 0) idx = jvp_array_length(j) + idx; if (idx < 0) { From 6500319de66d19fbc8704ffd8435846ba2bc2d23 Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Mon, 4 Mar 2024 12:20:42 +0100 Subject: [PATCH 18/20] fixes jv_object_set --- src/jv.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/jv.c b/src/jv.c index 59d93f6dc6..b707eaff8f 100644 --- a/src/jv.c +++ b/src/jv.c @@ -1433,6 +1433,8 @@ jv jv_string_slice(jv j, int start, int end) { } jv jv_string_concat(jv a, jv b) { + a = jv_return(a); + b = jv_return(b); a = jvp_string_append(a, jv_string_value(b), jvp_string_length(jvp_string_ptr(b))); jv_free(b); @@ -1785,17 +1787,12 @@ jv jv_object_set(jv input, jv key, jv value) { assert(JVP_HAS_KIND(input, JV_KIND_OBJECT)); assert(JVP_HAS_KIND(key, JV_KIND_STRING)); - jv object = jv_unborrow(input); - jv_free(input); + input = jv_return(input); // copy/free of object, key, value coalesced - jv* slot = jvp_object_write(&object, key); + jv* slot = jvp_object_write(&input, jv_return(key)); jv_free(*slot); - if(jv_is_borrowed(value)){ - *slot = jv_unborrow(value); - }else{ - *slot = value; - } - return object; + *slot = jv_return(value); + return input; } jv jv_object_delete(jv input, jv key) { From 0115bb4b19b92a22ab80e976a71427ccb3c6e2c7 Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Mon, 4 Mar 2024 12:32:39 +0100 Subject: [PATCH 19/20] refactor test --- src/jq_test.c | 152 +++++++++++++++++--------------------------------- 1 file changed, 52 insertions(+), 100 deletions(-) diff --git a/src/jq_test.c b/src/jq_test.c index 858b99d11a..b422d6fcf6 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -493,104 +493,56 @@ static void jv_test() { /// Borrowing { - jv d = jv_string("b"); - jv a = JV_ARRAY(jv_string("a"), jv_borrow(d)); - jv_free(d); - - jv i = jv_invalid_with_msg(jv_borrow(d)); - jv m = jv_invalid_get_msg(i); - assert(!jv_is_borrowed(m)); - jv_free(m); - - jv c = jv_array_get(jv_borrow(a), 1); - assert(!jv_is_borrowed(c)); - - jv c2 = jv_getpath(jv_borrow(a), JV_ARRAY(jv_number(1))); - assert(!jv_is_borrowed(c2)); - assert(jv_cmp(jv_borrow(c), jv_borrow(c2)) == 0); - jv_free(c); - jv_free(c2); - - jv b = jv_borrow(a); - assert(jv_is_borrowed(b)); - jv_free(b); - jv_free(b); - - assert(jv_equal(jv_copy(a), b)); - - jv e = jv_array_concat(b, JV_ARRAY(jv_number(5))); - assert(!jv_is_borrowed(e)); - jv_free(e); - - jv_array_length(b); - jv k = jv_keys(b); - assert(!jv_is_borrowed(k)); - jv_free(k); - - jv f = jv_array_append(b, jv_number(5)); - assert(!jv_is_borrowed(f)); - jv_free(f); - - jv g = jv_array_append(jv_array(), b); - assert(!jv_is_borrowed(g)); - jv_free(g); - - jv a1 = jv_parse("{\"key\":\"value\"}"); - jv p = jv_set(jv_borrow(a1), jv_string("key"), jv_string("other")); - assert(!jv_is_borrowed(p)); - jv_free(p); - - jv q = jv_get(jv_borrow(a1), jv_string("key")); - assert(!jv_is_borrowed(q)); - jv_free(q); - - jv_free(a1); - - jv res = jv_array_get(b, 1); - assert(!jv_is_borrowed(res)); - jv_free(res); - - jv h = jv_setpath(b, JV_ARRAY(jv_number(1)), jv_string("some")); - assert(!jv_is_borrowed(h)); - jv_free(h); - - - b = jv_unborrow(b); - - jv_free(a); - - assert(jv_get_refcnt(a) == 1); - - jv_free(b); - - jv object = JV_OBJECT(jv_string("some"), jv_string("value")); - jv object_deleted = jv_object_delete(jv_borrow(object), jv_string("some")); - jv object_value = jv_getpath(object, JV_ARRAY(jv_string("some"))); - assert(jv_equal(object_value, jv_string("value"))); - jv_free(object_deleted); - - jv array = JV_ARRAY(jv_string("some"), jv_string("value")); - jv new_array = jv_array_slice(jv_borrow(array), 0, 1); - assert(jv_equal(array, JV_ARRAY(jv_string("some"), jv_string("value")))); - jv_free(new_array); - - - jv test = jv_string("value"); - object = JV_OBJECT(jv_string("some"), jv_borrow(test)); - jv_free(test); - jv object_set = jv_object_set(jv_borrow(object), jv_string("some"), jv_string("other")); - assert(jv_equal(object, JV_OBJECT(jv_string("some"), jv_string("value")))); - jv_free(object_set); - - jv string = jv_string("value"); - jv other = jv_string_append_buf(jv_borrow(string), "test", 4); - assert(jv_equal(string, jv_string("value"))); - assert(jv_equal(other, jv_string("valuetest"))); - - array = JV_ARRAY(jv_string("test")); - jv array_out = jv_array_set(jv_borrow(array), 0, jv_string("value")); - assert(jv_equal(array, JV_ARRAY(jv_string("test")))); - assert(!jv_is_borrowed(array_out)); - jv_free(array_out); -} + jv input = jv_string("some"); + jv_copy(jv_borrow(input)); + jv_free(jv_borrow(input)); + jv_free(jv_unborrow(jv_borrow(input))); + jv_free(jv_unborrow(input)); + jv_free(input); + + jv key = jv_string("key"); + jv val = jv_string("value"); + jv object = JV_OBJECT(jv_borrow(key), jv_borrow(val)); + jv_free(key); + jv_free(val); + jv modified = jv_object_set(jv_borrow(object), jv_string("key"), jv_string("other")); + assert(!jv_is_borrowed(modified)); + jv original_value = jv_getpath(object, JV_ARRAY(jv_string("key"))); + assert(jv_equal(original_value, jv_string("value"))); + jv modified_value = jv_getpath(modified, JV_ARRAY(jv_string("key"))); + assert(!jv_is_borrowed(modified_value)); + assert(jv_equal(modified_value, jv_string("other"))); + + jv array_value = jv_string("value"); + jv array = JV_ARRAY(jv_borrow(array_value)); + jv_free(array_value); + jv modified_array = jv_array_set(jv_borrow(array), 0, jv_string("other")); + assert(!jv_is_borrowed(modified_array)); + jv original_array_value = jv_array_get(array, 0); + assert(jv_equal(original_array_value, jv_string("value"))); + jv modified_array_value = jv_array_get(modified_array, 0); + assert(!jv_is_borrowed(modified_array_value)); + assert(jv_equal(modified_array_value, jv_string("other"))); + + jv invalid_msg = jv_string("message"); + jv invalid = jv_invalid_with_msg(jv_borrow(invalid_msg)); + jv_free(invalid_msg); + jv obtained_msg = jv_invalid_get_msg(invalid); + assert(!jv_is_borrowed(obtained_msg)); + assert(jv_equal(obtained_msg, jv_string("message"))); + + jv input_string = jv_string("test"); + jv modified_string = jv_string_append_buf(jv_borrow(input_string), "ing", 3); + assert(!jv_is_borrowed(input_string)); + assert(jv_equal(modified_string, jv_string("testing"))); + jv_free(input_string); + + jv string_a = jv_string("some"); + jv string_b = jv_string("thing"); + jv concat_string = jv_string_concat(jv_borrow(string_a), jv_borrow(string_b)); + jv_free(string_a); + jv_free(string_b); + assert(!jv_is_borrowed(concat_string)); + assert(jv_equal(concat_string, jv_string("something"))); + } } From b6c551e6d56981449d9a7ee9d6631085f8549ae6 Mon Sep 17 00:00:00 2001 From: MaxBrandtner Date: Mon, 4 Mar 2024 13:14:00 +0100 Subject: [PATCH 20/20] use jv_return instead of unborrowing conditionally --- src/jv.c | 38 +++++++++++--------------------------- src/jv_aux.c | 18 +++++++----------- 2 files changed, 18 insertions(+), 38 deletions(-) diff --git a/src/jv.c b/src/jv.c index b707eaff8f..90c2416c73 100644 --- a/src/jv.c +++ b/src/jv.c @@ -150,11 +150,7 @@ jv jv_invalid_with_msg(jv err) { jvp_invalid* i = jv_mem_alloc(sizeof(jvp_invalid)); i->refcnt = JV_REFCNT_INIT; - if(jv_is_borrowed(err)){ - i->errmsg = jv_unborrow(err); - }else{ - i->errmsg = err; - } + i->errmsg = jv_return(err); jv x = {JVP_FLAGS_INVALID_MSG, 0, 0, 0, 0, {&i->refcnt}}; return x; @@ -1002,13 +998,8 @@ jv jv_array_set(jv j, int idx, jv val) { // copy/free of val,j coalesced jv* slot = jvp_array_write(&j, idx); jv_free(*slot); - if(jv_is_borrowed(val)){ - *slot = jv_unborrow(val); - }else{ - *slot = val; - } - if(jv_is_borrowed(j)) return jv_unborrow(j); - return j; + *slot = jv_return(val); + return jv_return(j); } jv jv_array_append(jv j, jv val) { @@ -1433,19 +1424,15 @@ jv jv_string_slice(jv j, int start, int end) { } jv jv_string_concat(jv a, jv b) { - a = jv_return(a); - b = jv_return(b); - a = jvp_string_append(a, jv_string_value(b), + a = jvp_string_append(jv_return(a), jv_string_value(b), jvp_string_length(jvp_string_ptr(b))); jv_free(b); return a; } -jv jv_string_append_buf(jv input, const char* buf, int len) { - jv a = jv_return(input); - +jv jv_string_append_buf(jv a, const char* buf, int len) { if (jvp_utf8_is_valid(buf, buf+len)) { - a = jvp_string_append(a, buf, len); + a = jvp_string_append(jv_return(a), buf, len); } else { jv b = jvp_string_copy_replace_bad(buf, len); a = jv_string_concat(a, b); @@ -1453,12 +1440,10 @@ jv jv_string_append_buf(jv input, const char* buf, int len) { return a; } -jv jv_string_append_codepoint(jv input, uint32_t c) { - jv a = jv_return(input); - +jv jv_string_append_codepoint(jv a, uint32_t c) { char buf[5]; int len = jvp_utf8_encode(c, buf); - a = jvp_string_append(a, buf, len); + a = jvp_string_append(jv_return(a), buf, len); return a; } @@ -1798,11 +1783,10 @@ jv jv_object_set(jv input, jv key, jv value) { jv jv_object_delete(jv input, jv key) { assert(JVP_HAS_KIND(input, JV_KIND_OBJECT)); assert(JVP_HAS_KIND(key, JV_KIND_STRING)); - jv object = jv_unborrow(input); - jv_free(input); - jvp_object_delete(&object, key); + input = jv_return(input); + jvp_object_delete(&input, key); jv_free(key); - return object; + return input; } int jv_object_length(jv object) { diff --git a/src/jv_aux.c b/src/jv_aux.c index 70983cc0b9..b5572067d8 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -152,7 +152,6 @@ jv jv_get(jv t, jv k) { jv_free(k); } - if(jv_is_borrowed(v)) return jv_unborrow(v); return v; } @@ -160,8 +159,7 @@ jv jv_set(jv t, jv k, jv v) { if (!jv_is_valid(v)) { jv_free(t); jv_free(k); - if(jv_is_borrowed(v)) return jv_unborrow(v); - return v; + return jv_return(v); } int isnull = jv_get_kind(t) == JV_KIND_NULL; if (jv_get_kind(k) == JV_KIND_STRING && @@ -388,14 +386,12 @@ jv jv_setpath(jv root, jv path, jv value) { if (!jv_is_valid(root)){ jv_free(value); jv_free(path); - if(jv_is_borrowed(root)) return jv_unborrow(root); - return root; + return jv_return(root); } if (jv_array_length(jv_copy(path)) == 0) { jv_free(path); jv_free(root); - if(jv_is_borrowed(value)) return jv_unborrow(value); - return value; + return jv_return(value); } jv pathcurr = jv_array_get(jv_copy(path), 0); jv pathrest = jv_array_slice(path, 1, jv_array_length(jv_copy(path))); @@ -440,11 +436,11 @@ jv jv_getpath(jv root, jv path) { } if (!jv_is_valid(root)) { jv_free(path); - return root; + return jv_return(root); } if (jv_array_length(jv_copy(path)) == 0) { jv_free(path); - return root; + return jv_return(root); } jv pathcurr = jv_array_get(jv_copy(path), 0); jv pathrest = jv_array_slice(path, 1, jv_array_length(jv_copy(path))); @@ -496,7 +492,7 @@ static jv delpaths_sorted(jv object, jv paths, int start) { object = jv_dels(object, delkeys); else jv_free(delkeys); - return object; + return jv_return(object); } jv jv_delpaths(jv object, jv paths) { @@ -520,7 +516,7 @@ jv jv_delpaths(jv object, jv paths) { if (jv_array_length(jv_copy(paths)) == 0) { // nothing is being deleted jv_free(paths); - return object; + return jv_return(object); } if (jv_array_length(jv_array_get(jv_copy(paths), 0)) == 0) { // everything is being deleted