]> granicus.if.org Git - jq/commitdiff
Perl-style autovivification.
authorStephen Dolan <mu@netsoc.tcd.ie>
Mon, 3 Sep 2012 15:50:38 +0000 (16:50 +0100)
committerStephen Dolan <mu@netsoc.tcd.ie>
Mon, 3 Sep 2012 15:50:38 +0000 (16:50 +0100)
.foo.bar = 1 will cause objects to be created if they don't exist.

c/jv.c
c/jv.h
c/testdata

diff --git a/c/jv.c b/c/jv.c
index 4484dc9fdce42850b92c49957970a467c66596ad..9a3d308facf231868f183c84e6981b858fb85728 100644 (file)
--- a/c/jv.c
+++ b/c/jv.c
@@ -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;
 }
diff --git a/c/jv.h b/c/jv.h
index b251329cb57133ab042b3265cf5ec975898fde4b..8d9ebadb3ca8ef231df196b7b93ef1f882953fc3 100644 (file)
--- a/c/jv.h
+++ b/c/jv.h
@@ -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;
 }
index c6388d67980a3aa2130a3dbc7dc093813d4aff9b..70071186f159de241cdef6ebfc00c1022d57e377 100644 (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}