Make .[] capable of iteration over objects as well as arrays.
Also change an assert to a proper error message if it's given something silly like a number.
This commit is contained in:
1 parent
d9d6f43407
commit
f6c6ba95ad
1 file changed
+36
-10
+36
-10
@@ -326,25 +326,51 @@ jv jq_next() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case EACH:
|
case EACH:
|
||||||
stack_push(stackval_root(jv_number(0)));
|
stack_push(stackval_root(jv_number(-1)));
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case ON_BACKTRACK(EACH): {
|
case ON_BACKTRACK(EACH): {
|
||||||
int idx = jv_number_value(stack_pop().value);
|
int idx = jv_number_value(stack_pop().value);
|
||||||
stackval array = stack_pop();
|
stackval container = stack_pop();
|
||||||
if (idx >= jv_array_length(jv_copy(array.value))) {
|
|
||||||
jv_free(array.value);
|
int is_array, keep_going;
|
||||||
|
jv key, value;
|
||||||
|
if (jv_get_kind(container.value) == JV_KIND_ARRAY) {
|
||||||
|
is_array = 1;
|
||||||
|
if (opcode == EACH) idx = 0;
|
||||||
|
else idx = idx + 1;
|
||||||
|
keep_going = idx < jv_array_length(jv_copy(container.value));
|
||||||
|
if (keep_going) {
|
||||||
|
key = jv_number(idx);
|
||||||
|
value = jv_array_get(jv_copy(container.value), idx);
|
||||||
|
}
|
||||||
|
} else if (jv_get_kind(container.value) == JV_KIND_OBJECT) {
|
||||||
|
is_array = 0;
|
||||||
|
if (opcode == EACH) idx = jv_object_iter(container.value);
|
||||||
|
else idx = jv_object_iter_next(container.value, idx);
|
||||||
|
keep_going = jv_object_iter_valid(container.value, idx);
|
||||||
|
if (keep_going) {
|
||||||
|
key = jv_object_iter_key(container.value, idx);
|
||||||
|
value = jv_object_iter_value(container.value, idx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(opcode == EACH);
|
||||||
|
print_error(jv_invalid_with_msg(jv_string_fmt("Cannot iterate over %s",
|
||||||
|
jv_kind_name(jv_get_kind(container.value)))));
|
||||||
|
keep_going = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keep_going) {
|
||||||
|
jv_free(container.value);
|
||||||
goto do_backtrack;
|
goto do_backtrack;
|
||||||
} else {
|
} else {
|
||||||
stack_save();
|
stack_save();
|
||||||
stackval array2 = array;
|
stack_push(container);
|
||||||
array2.value = jv_copy(array2.value);
|
stack_push(stackval_root(jv_number(idx)));
|
||||||
stack_push(array2);
|
|
||||||
stack_push(stackval_root(jv_number(idx+1)));
|
|
||||||
frame_push_backtrack(&frame_stk, pc - 1);
|
frame_push_backtrack(&frame_stk, pc - 1);
|
||||||
stack_switch();
|
stack_switch();
|
||||||
|
|
||||||
stackval sv = {jv_array_get(array.value, idx),
|
stackval sv = {value,
|
||||||
path_push(array, jv_number(idx))};
|
path_push(container, key)};
|
||||||
stack_push(sv);
|
stack_push(sv);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in new issue
Block a user