From: Stephen Dolan Date: Mon, 3 Sep 2012 15:16:14 +0000 (+0100) Subject: JV_KIND_INVALID values to represent failed lookups, etc + various tests. X-Git-Tag: jq-1.1~83 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a8c3648ca5ebcb9c824f3df86a4c2fbe57c09d6d;p=jq JV_KIND_INVALID values to represent failed lookups, etc + various tests. --- diff --git a/c/execute.c b/c/execute.c index 0c31e07..d98872b 100644 --- a/c/execute.c +++ b/c/execute.c @@ -321,8 +321,7 @@ jv jq_next() { do_backtrack: case BACKTRACK: { if (!stack_restore()) { - // FIXME: invalid jv value - return jv_null(); + return jv_invalid(); } pc = *frame_current_retaddr(&frame_stk); frame_pop(&frame_stk); @@ -443,7 +442,7 @@ void run_program(struct bytecode* bc) { fgets(buf, sizeof(buf), stdin); jq_init(bc, jv_parse(buf)); jv result; - while (jv_get_kind(result = jq_next()) != JV_KIND_NULL) { + while (jv_is_valid(result = jq_next())) { jv_dump(result); printf("\n"); } diff --git a/c/jv.c b/c/jv.c index 198bfed..4484dc9 100644 --- a/c/jv.c +++ b/c/jv.c @@ -37,10 +37,15 @@ jv_kind jv_get_kind(jv x) { return x.kind; } +static const jv JV_INVALID = {JV_KIND_INVALID, {0}}; static const jv JV_NULL = {JV_KIND_NULL, {0}}; static const jv JV_FALSE = {JV_KIND_FALSE, {0}}; static const jv JV_TRUE = {JV_KIND_TRUE, {0}}; +jv jv_invalid() { + return JV_INVALID; +} + jv jv_true() { return JV_TRUE; } @@ -671,7 +676,13 @@ jv jv_object() { jv jv_object_get(jv object, jv key) { assert(jv_get_kind(object) == JV_KIND_OBJECT); assert(jv_get_kind(key) == JV_KIND_STRING); - jv val = jv_copy(*jvp_object_read(&object.val.complex, jvp_string_ptr(&key.val.complex))); + jv* slot = jvp_object_read(&object.val.complex, jvp_string_ptr(&key.val.complex)); + jv val; + if (slot) { + val = jv_copy(*slot); + } else { + val = jv_invalid(); + } jv_free(object); jv_free(key); return val; diff --git a/c/jv.h b/c/jv.h index 754f031..b251329 100644 --- a/c/jv.h +++ b/c/jv.h @@ -8,6 +8,7 @@ typedef enum { + JV_KIND_INVALID, JV_KIND_NULL, JV_KIND_FALSE, JV_KIND_TRUE, @@ -40,12 +41,14 @@ typedef struct { */ jv_kind jv_get_kind(jv); +static int jv_is_valid(jv x) { return jv_get_kind(x) != JV_KIND_INVALID; } jv jv_copy(jv); void jv_free(jv); int jv_equal(jv, jv); +jv jv_invalid(); jv jv_null(); jv jv_true(); jv jv_false(); @@ -95,6 +98,9 @@ static jv jv_lookup(jv t, jv k) { jv v; if (jv_get_kind(t) == JV_KIND_OBJECT && jv_get_kind(k) == JV_KIND_STRING) { v = jv_object_get(t, k); + if (!jv_is_valid(v)) { + v = jv_null(); + } } 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)); diff --git a/c/main.c b/c/main.c index 5cdc7d6..5879d03 100644 --- a/c/main.c +++ b/c/main.c @@ -46,7 +46,7 @@ void run_tests() { if (skipline(buf)) break; jv expected = jv_parse(buf); jv actual = jq_next(); - if (!1) { + if (!jv_is_valid(actual)) { printf("Insufficient results\n"); pass = 0; break; @@ -59,14 +59,14 @@ void run_tests() { pass = 0; } } - if (pass && 0) { /* + if (pass) { jv extra = jq_next(); - if (extra) { + if (jv_is_valid(extra)) { printf("Superfluous result: "); - json_dumpf(extra, stdout, JSON_ENCODE_ANY); + jv_dump(extra); printf("\n"); pass = 0; - }*/ + } } jq_teardown(); bytecode_free(bc); diff --git a/c/testdata b/c/testdata index 2cdaaa5..c6388d6 100644 --- a/c/testdata +++ b/c/testdata @@ -59,11 +59,9 @@ null {"foo": {"bar": 42}, "bar": "badvalue"} 42 - -# FIXME strings -# .["foo"].bar -# {"foo": {"bar": 42}, "bar": "badvalue"} -# 42 +.["foo"].bar +{"foo": {"bar": 42}, "bar": "badvalue"} +42 # @@ -172,6 +170,12 @@ true [1] true +null,1,null +"hello" +null +1 +null + [1,2,3] [5,6] [1,2,3] @@ -193,3 +197,18 @@ def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x [[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | g; f[0] | [f][0][1] | f] "woo, testing!" [[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]] + +# +# Assignment +# +.message = "goodbye" +{"message": "hello"} +{"message": "goodbye"} + +.foo = .bar +{"bar":42} +{"foo":42, "bar":42} + +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}]