jv_aux.c (jq-1.5) | : | jv_aux.c (jq-1.6) | ||
---|---|---|---|---|
skipping to change at line 217 | skipping to change at line 217 | |||
ret = jv_invalid_with_msg(jv_string_fmt("Cannot check whether %s has a %s ke y", | ret = jv_invalid_with_msg(jv_string_fmt("Cannot check whether %s has a %s ke y", | |||
jv_kind_name(jv_get_kind(t)), | jv_kind_name(jv_get_kind(t)), | |||
jv_kind_name(jv_get_kind(k)))); | jv_kind_name(jv_get_kind(k)))); | |||
jv_free(t); | jv_free(t); | |||
jv_free(k); | jv_free(k); | |||
} | } | |||
return ret; | return ret; | |||
} | } | |||
// assumes keys is a sorted array | // assumes keys is a sorted array | |||
jv jv_dels(jv t, jv keys) { | static jv jv_dels(jv t, jv keys) { | |||
assert(jv_get_kind(keys) == JV_KIND_ARRAY); | assert(jv_get_kind(keys) == JV_KIND_ARRAY); | |||
assert(jv_is_valid(t)); | assert(jv_is_valid(t)); | |||
if (jv_get_kind(t) == JV_KIND_NULL || jv_array_length(jv_copy(keys)) == 0) { | if (jv_get_kind(t) == JV_KIND_NULL || jv_array_length(jv_copy(keys)) == 0) { | |||
// no change | // no change | |||
} else if (jv_get_kind(t) == JV_KIND_ARRAY) { | } else if (jv_get_kind(t) == JV_KIND_ARRAY) { | |||
// extract slices, they must be handled differently | // extract slices, they must be handled differently | |||
jv orig_keys = keys; | jv neg_keys = jv_array(); | |||
keys = jv_array(); | jv nonneg_keys = jv_array(); | |||
jv new_array = jv_array(); | jv new_array = jv_array(); | |||
jv starts = jv_array(), ends = jv_array(); | jv starts = jv_array(), ends = jv_array(); | |||
jv_array_foreach(orig_keys, i, key) { | jv_array_foreach(keys, i, key) { | |||
if (jv_get_kind(key) == JV_KIND_NUMBER) { | if (jv_get_kind(key) == JV_KIND_NUMBER) { | |||
keys = jv_array_append(keys, key); | if (jv_number_value(key) < 0) { | |||
neg_keys = jv_array_append(neg_keys, key); | ||||
} else { | ||||
nonneg_keys = jv_array_append(nonneg_keys, key); | ||||
} | ||||
} else if (jv_get_kind(key) == JV_KIND_OBJECT) { | } else if (jv_get_kind(key) == JV_KIND_OBJECT) { | |||
int start, end; | int start, end; | |||
if (parse_slice(jv_copy(t), key, &start, &end)) { | if (parse_slice(jv_copy(t), key, &start, &end)) { | |||
starts = jv_array_append(starts, jv_number(start)); | starts = jv_array_append(starts, jv_number(start)); | |||
ends = jv_array_append(ends, jv_number(end)); | ends = jv_array_append(ends, jv_number(end)); | |||
} else { | } else { | |||
jv_free(new_array); | jv_free(new_array); | |||
new_array = jv_invalid_with_msg(jv_string_fmt("Start and end indices o f an array slice must be numbers")); | new_array = jv_invalid_with_msg(jv_string_fmt("Start and end indices o f an array slice must be numbers")); | |||
goto arr_out; | goto arr_out; | |||
} | } | |||
} else { | } else { | |||
jv_free(new_array); | jv_free(new_array); | |||
new_array = jv_invalid_with_msg(jv_string_fmt("Cannot delete %s element of array", | new_array = jv_invalid_with_msg(jv_string_fmt("Cannot delete %s element of array", | |||
jv_kind_name(jv_get_kind(k ey)))); | jv_kind_name(jv_get_kind(k ey)))); | |||
jv_free(key); | jv_free(key); | |||
goto arr_out; | goto arr_out; | |||
} | } | |||
} | } | |||
int kidx = 0; | int neg_idx = 0; | |||
int nonneg_idx = 0; | ||||
int len = jv_array_length(jv_copy(t)); | ||||
jv_array_foreach(t, i, elem) { | jv_array_foreach(t, i, elem) { | |||
int del = 0; | int del = 0; | |||
while (kidx < jv_array_length(jv_copy(keys))) { | while (neg_idx < jv_array_length(jv_copy(neg_keys))) { | |||
int delidx = (int)jv_number_value(jv_array_get(jv_copy(keys), kidx)); | int delidx = len + (int)jv_number_value(jv_array_get(jv_copy(neg_keys), | |||
neg_idx)); | ||||
if (i == delidx) { | if (i == delidx) { | |||
del = 1; | del = 1; | |||
} | } | |||
if (i < delidx) { | if (i < delidx) { | |||
break; | break; | |||
} | } | |||
kidx++; | neg_idx++; | |||
} | ||||
while (nonneg_idx < jv_array_length(jv_copy(nonneg_keys))) { | ||||
int delidx = (int)jv_number_value(jv_array_get(jv_copy(nonneg_keys), non | ||||
neg_idx)); | ||||
if (i == delidx) { | ||||
del = 1; | ||||
} | ||||
if (i < delidx) { | ||||
break; | ||||
} | ||||
nonneg_idx++; | ||||
} | } | |||
for (int sidx=0; !del && sidx<jv_array_length(jv_copy(starts)); sidx++) { | for (int sidx=0; !del && sidx<jv_array_length(jv_copy(starts)); sidx++) { | |||
if ((int)jv_number_value(jv_array_get(jv_copy(starts), sidx)) <= i && | if ((int)jv_number_value(jv_array_get(jv_copy(starts), sidx)) <= i && | |||
i < (int)jv_number_value(jv_array_get(jv_copy(ends), sidx))) { | i < (int)jv_number_value(jv_array_get(jv_copy(ends), sidx))) { | |||
del = 1; | del = 1; | |||
} | } | |||
} | } | |||
if (!del) | if (!del) | |||
new_array = jv_array_append(new_array, elem); | new_array = jv_array_append(new_array, elem); | |||
else | else | |||
jv_free(elem); | jv_free(elem); | |||
} | } | |||
arr_out: | arr_out: | |||
jv_free(neg_keys); | ||||
jv_free(nonneg_keys); | ||||
jv_free(starts); | jv_free(starts); | |||
jv_free(ends); | jv_free(ends); | |||
jv_free(orig_keys); | ||||
jv_free(t); | jv_free(t); | |||
t = new_array; | t = new_array; | |||
} else if (jv_get_kind(t) == JV_KIND_OBJECT) { | } else if (jv_get_kind(t) == JV_KIND_OBJECT) { | |||
jv_array_foreach(keys, i, k) { | jv_array_foreach(keys, i, k) { | |||
if (jv_get_kind(k) != JV_KIND_STRING) { | if (jv_get_kind(k) != JV_KIND_STRING) { | |||
jv_free(t); | jv_free(t); | |||
t = jv_invalid_with_msg(jv_string_fmt("Cannot delete %s field of object" , | t = jv_invalid_with_msg(jv_string_fmt("Cannot delete %s field of object" , | |||
jv_kind_name(jv_get_kind(k)))); | jv_kind_name(jv_get_kind(k)))); | |||
jv_free(k); | jv_free(k); | |||
break; | break; | |||
skipping to change at line 393 | skipping to change at line 410 | |||
} | } | |||
jv_free(paths); | jv_free(paths); | |||
if (jv_is_valid(object)) | if (jv_is_valid(object)) | |||
object = jv_dels(object, delkeys); | object = jv_dels(object, delkeys); | |||
else | else | |||
jv_free(delkeys); | jv_free(delkeys); | |||
return object; | return object; | |||
} | } | |||
jv jv_delpaths(jv object, jv paths) { | jv jv_delpaths(jv object, jv paths) { | |||
if (jv_get_kind(paths) != JV_KIND_ARRAY) { | ||||
jv_free(object); | ||||
jv_free(paths); | ||||
return jv_invalid_with_msg(jv_string("Paths must be specified as an array")) | ||||
; | ||||
} | ||||
paths = jv_sort(paths, jv_copy(paths)); | paths = jv_sort(paths, jv_copy(paths)); | |||
jv_array_foreach(paths, i, elem) { | jv_array_foreach(paths, i, elem) { | |||
if (jv_get_kind(elem) != JV_KIND_ARRAY) { | if (jv_get_kind(elem) != JV_KIND_ARRAY) { | |||
jv_free(object); | jv_free(object); | |||
jv_free(paths); | jv_free(paths); | |||
jv err = jv_invalid_with_msg(jv_string_fmt("Path must be specified as arra y, not %s", | jv err = jv_invalid_with_msg(jv_string_fmt("Path must be specified as arra y, not %s", | |||
jv_kind_name(jv_get_kind(elem)) )); | jv_kind_name(jv_get_kind(elem)) )); | |||
jv_free(elem); | jv_free(elem); | |||
return err; | return err; | |||
} | } | |||
skipping to change at line 445 | skipping to change at line 467 | |||
answer = jv_array_append(answer, key); | answer = jv_array_append(answer, key); | |||
jv_free(value); | jv_free(value); | |||
} | } | |||
jv_free(x); | jv_free(x); | |||
return answer; | return answer; | |||
} | } | |||
jv jv_keys(jv x) { | jv jv_keys(jv x) { | |||
if (jv_get_kind(x) == JV_KIND_OBJECT) { | if (jv_get_kind(x) == JV_KIND_OBJECT) { | |||
int nkeys = jv_object_length(jv_copy(x)); | int nkeys = jv_object_length(jv_copy(x)); | |||
jv* keys = jv_mem_alloc(sizeof(jv) * nkeys); | jv* keys = jv_mem_calloc(sizeof(jv), nkeys); | |||
int kidx = 0; | int kidx = 0; | |||
jv_object_foreach(x, key, value) { | jv_object_foreach(x, key, value) { | |||
keys[kidx++] = key; | keys[kidx++] = key; | |||
jv_free(value); | jv_free(value); | |||
} | } | |||
qsort(keys, nkeys, sizeof(jv), string_cmp); | qsort(keys, nkeys, sizeof(jv), string_cmp); | |||
jv answer = jv_array_sized(nkeys); | jv answer = jv_array_sized(nkeys); | |||
for (int i = 0; i<nkeys; i++) { | for (int i = 0; i<nkeys; i++) { | |||
answer = jv_array_append(answer, keys[i]); | answer = jv_array_append(answer, keys[i]); | |||
} | } | |||
skipping to change at line 550 | skipping to change at line 572 | |||
} | } | |||
jv_free(a); | jv_free(a); | |||
jv_free(b); | jv_free(b); | |||
return r; | return r; | |||
} | } | |||
struct sort_entry { | struct sort_entry { | |||
jv object; | jv object; | |||
jv key; | jv key; | |||
int index; | ||||
}; | }; | |||
static int sort_cmp(const void* pa, const void* pb) { | static int sort_cmp(const void* pa, const void* pb) { | |||
const struct sort_entry* a = pa; | const struct sort_entry* a = pa; | |||
const struct sort_entry* b = pb; | const struct sort_entry* b = pb; | |||
int r = jv_cmp(jv_copy(a->key), jv_copy(b->key)); | int r = jv_cmp(jv_copy(a->key), jv_copy(b->key)); | |||
// comparing by address if r == 0 makes the sort stable | // comparing by index if r == 0 makes the sort stable | |||
return r ? r : (int)(a - b); | return r ? r : (a->index - b->index); | |||
} | } | |||
static struct sort_entry* sort_items(jv objects, jv keys) { | static struct sort_entry* sort_items(jv objects, jv keys) { | |||
assert(jv_get_kind(objects) == JV_KIND_ARRAY); | assert(jv_get_kind(objects) == JV_KIND_ARRAY); | |||
assert(jv_get_kind(keys) == JV_KIND_ARRAY); | assert(jv_get_kind(keys) == JV_KIND_ARRAY); | |||
assert(jv_array_length(jv_copy(objects)) == jv_array_length(jv_copy(keys))); | assert(jv_array_length(jv_copy(objects)) == jv_array_length(jv_copy(keys))); | |||
int n = jv_array_length(jv_copy(objects)); | int n = jv_array_length(jv_copy(objects)); | |||
struct sort_entry* entries = jv_mem_alloc(sizeof(struct sort_entry) * n); | struct sort_entry* entries = jv_mem_calloc(sizeof(struct sort_entry), n); | |||
for (int i=0; i<n; i++) { | for (int i=0; i<n; i++) { | |||
entries[i].object = jv_array_get(jv_copy(objects), i); | entries[i].object = jv_array_get(jv_copy(objects), i); | |||
entries[i].key = jv_array_get(jv_copy(keys), i); | entries[i].key = jv_array_get(jv_copy(keys), i); | |||
entries[i].index = i; | ||||
} | } | |||
jv_free(objects); | jv_free(objects); | |||
jv_free(keys); | jv_free(keys); | |||
qsort(entries, n, sizeof(struct sort_entry), sort_cmp); | qsort(entries, n, sizeof(struct sort_entry), sort_cmp); | |||
return entries; | return entries; | |||
} | } | |||
jv jv_sort(jv objects, jv keys) { | jv jv_sort(jv objects, jv keys) { | |||
assert(jv_get_kind(objects) == JV_KIND_ARRAY); | assert(jv_get_kind(objects) == JV_KIND_ARRAY); | |||
assert(jv_get_kind(keys) == JV_KIND_ARRAY); | assert(jv_get_kind(keys) == JV_KIND_ARRAY); | |||
End of changes. 15 change blocks. | ||||
14 lines changed or deleted | 41 lines changed or added |