1
0
mirror of https://github.com/stedolan/jq.git synced 2024-05-11 05:55:39 +00:00

Perl-style autovivification.

.foo.bar = 1 will cause objects to be created if they don't exist.
This commit is contained in:
Stephen Dolan
2012-09-03 16:50:38 +01:00
parent c9dbe1aff8
commit eea05ff924
3 changed files with 57 additions and 12 deletions

19
c/jv.c
View File

@ -125,10 +125,13 @@ static int jvp_array_length(jv_complex* a) {
}
static jv* jvp_array_read(jv_complex* a, int i) {
assert(i >= 0 && i < jvp_array_length(a));
jvp_array* array = jvp_array_ptr(a);
assert(i + a->i[0] < array->length);
return &array->elements[i + a->i[0]];
if (i >= 0 && i < jvp_array_length(a)) {
jvp_array* array = jvp_array_ptr(a);
assert(i + a->i[0] < array->length);
return &array->elements[i + a->i[0]];
} else {
return 0;
}
}
static jv* jvp_array_write(jv_complex* a, int i) {
@ -223,7 +226,13 @@ int jv_array_length(jv j) {
jv jv_array_get(jv j, int idx) {
assert(jv_get_kind(j) == JV_KIND_ARRAY);
jv val = jv_copy(*jvp_array_read(&j.val.complex, idx));
jv* slot = jvp_array_read(&j.val.complex, idx);
jv val;
if (slot) {
val = jv_copy(*slot);
} else {
val = jv_invalid();
}
jv_free(j);
return val;
}

32
c/jv.h
View File

@ -104,6 +104,14 @@ static jv jv_lookup(jv t, jv k) {
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) {
// FIXME: don't do lookup for noninteger index
v = jv_array_get(t, (int)jv_number_value(k));
if (!jv_is_valid(v)) {
v = jv_null();
}
} else if (jv_get_kind(t) == JV_KIND_NULL &&
(jv_get_kind(k) == JV_KIND_STRING || jv_get_kind(k) == JV_KIND_NUMBER)) {
jv_free(t);
jv_free(k);
v = jv_null();
} else {
assert(0&&"bad lookup");
}
@ -118,12 +126,26 @@ static jv jv_lookup(jv t, jv k) {
}
static jv jv_modify(jv t, jv k, jv v) {
if (jv_get_kind(t) == JV_KIND_OBJECT && jv_get_kind(k) == JV_KIND_STRING) {
t = jv_object_set(t, k, v);
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) {
t = jv_array_set(t, (int)jv_number_value(k), v);
if (jv_get_kind(k) == JV_KIND_STRING) {
if (jv_get_kind(t) == JV_KIND_NULL) {
t = jv_object();
}
if (jv_get_kind(t) == JV_KIND_OBJECT) {
t = jv_object_set(t, k, v);
} else {
assert(0 && "bad mod - not an object");
}
} else if (jv_get_kind(k) == JV_KIND_NUMBER) {
if (jv_get_kind(t) == JV_KIND_NULL) {
t = jv_array();
}
if (jv_get_kind(t) == JV_KIND_ARRAY) {
t = jv_array_set(t, (int)jv_number_value(k), v);
} else {
assert(0 && "bad mod - not an array");
}
} else {
assert(0 && "bad mod");
assert(0 && "bad mod - seriously, wtf");
}
return t;
}

View File

@ -133,12 +133,18 @@ null
# Builtin functions
#
# FIXME: floats vs. integer
1+1
null
2
1+1
"wtasdf"
2.0
1e+0+0.001e3
"I wonder what this will be?"
20e-1
.+4
15
19.0
@ -212,3 +218,11 @@ def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x
def inc(x): x |= .+1; inc(.[].a)
[{"a":1,"b":2},{"a":2,"b":4},{"a":7,"b":8}]
[{"a":2,"b":2},{"a":3,"b":4},{"a":8,"b":8}]
.[2][3] = 1
[4]
[4, null, [null, null, null, 1]]
.foo[2].bar = 1
{"foo":[11], "bar":42}
{"foo":[11,null,{"bar":1}], "bar":42}