summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Dolan <mu@netsoc.tcd.ie>2013-05-06 13:46:16 +0100
committerStephen Dolan <mu@netsoc.tcd.ie>2013-05-06 13:46:54 +0100
commit48be23233ad63bf1bd218c259efedff3e52106c5 (patch)
treef79c3b52124b916fedb30f204732440dee8ef79c
parent88a6dc5343a66b2db3ad36f0fa9f24fc89282caa (diff)
Add the "has" function. Closes #74.
-rw-r--r--builtin.c1
-rw-r--r--docs/content/3.manual/manual.yml19
-rw-r--r--jv_aux.c28
-rw-r--r--jv_aux.h1
4 files changed, 49 insertions, 0 deletions
diff --git a/builtin.c b/builtin.c
index b9c60b83..39570188 100644
--- a/builtin.c
+++ b/builtin.c
@@ -480,6 +480,7 @@ static const struct cfunction function_list[] = {
{(cfunction_ptr)jv_setpath, "setpath", 3}, // FIXME typechecking
{(cfunction_ptr)jv_getpath, "getpath", 2},
{(cfunction_ptr)jv_delpaths, "delpaths", 2},
+ {(cfunction_ptr)jv_has, "has", 2},
{(cfunction_ptr)f_equal, "_equal", 3},
{(cfunction_ptr)f_notequal, "_notequal", 3},
{(cfunction_ptr)f_less, "_less", 3},
diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml
index 6f80b78b..7b490659 100644
--- a/docs/content/3.manual/manual.yml
+++ b/docs/content/3.manual/manual.yml
@@ -453,6 +453,25 @@ sections:
input: '[42,3,35]'
output: ['[0,1,2]']
+ - title: `has`
+ body: |
+
+ The builtin function `has` returns whether the input object
+ has the given key, or the input array has an element at the
+ given index.
+
+ `has($key)` has the same effect as checking whether `$key`
+ is a member of the array returned by `keys`, although `has`
+ will be faster.
+
+ examples:
+ - program: 'map(has("foo"))'
+ input: '[{"foo": 42}, {}]'
+ output: ['[true, false]']
+ - program: 'map(has(2))'
+ input: '[[0,1], ["a","b","c"]]'
+ output: ['[false, true]']
+
- title: `select`
body: |
diff --git a/jv_aux.c b/jv_aux.c
index 2c33491d..1f40cc4b 100644
--- a/jv_aux.c
+++ b/jv_aux.c
@@ -60,6 +60,34 @@ jv jv_set(jv t, jv k, jv v) {
return t;
}
+jv jv_has(jv t, jv k) {
+ assert(jv_is_valid(t));
+ assert(jv_is_valid(k));
+ jv ret;
+ if (jv_get_kind(t) == JV_KIND_NULL) {
+ jv_free(t);
+ jv_free(k);
+ ret = jv_false();
+ } else if (jv_get_kind(t) == JV_KIND_OBJECT &&
+ jv_get_kind(k) == JV_KIND_STRING) {
+ jv elem = jv_object_get(t, k);
+ ret = jv_bool(jv_is_valid(elem));
+ jv_free(elem);
+ } else if (jv_get_kind(t) == JV_KIND_ARRAY &&
+ jv_get_kind(k) == JV_KIND_NUMBER) {
+ jv elem = jv_array_get(t, (int)jv_number_value(k));
+ ret = jv_bool(jv_is_valid(elem));
+ jv_free(elem);
+ } else {
+ ret = jv_invalid_with_msg(jv_string_fmt("Cannot check whether %s has a %s key",
+ jv_kind_name(jv_get_kind(t)),
+ jv_kind_name(jv_get_kind(k))));
+ jv_free(t);
+ jv_free(k);
+ }
+ return ret;
+}
+
// assumes keys is a sorted array
jv jv_dels(jv t, jv keys) {
assert(jv_get_kind(keys) == JV_KIND_ARRAY);
diff --git a/jv_aux.h b/jv_aux.h
index 561f1083..5a47b70c 100644
--- a/jv_aux.h
+++ b/jv_aux.h
@@ -5,6 +5,7 @@
jv jv_get(jv t, jv k);
jv jv_set(jv t, jv k, jv v);
+jv jv_has(jv t, jv k);
jv jv_setpath(jv root, jv path, jv value);
jv jv_getpath(jv root, jv path);
jv jv_delpaths(jv root, jv paths);