summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Dolan <mu@netsoc.tcd.ie>2012-10-20 00:26:37 +0100
committerStephen Dolan <mu@netsoc.tcd.ie>2012-10-20 00:26:37 +0100
commit32e1b114df3067b000b26d11030fd265d2fee17a (patch)
tree562c9cccd053bb7e717afc2e43d544fdb1bfe18c
parentafec2544f1793d11c47356c32ef74ce8c4035263 (diff)
Add a 'keys' function. Fixes #4.
-rw-r--r--builtin.c34
-rw-r--r--testdata4
2 files changed, 38 insertions, 0 deletions
diff --git a/builtin.c b/builtin.c
index c6ff785d..c3d6af19 100644
--- a/builtin.c
+++ b/builtin.c
@@ -202,6 +202,39 @@ static void f_tostring(jv input[], jv output[]) {
}
}
+static int string_cmp(const void* pa, const void* pb){
+ const jv* a = pa;
+ const jv* b = pb;
+ int lena = jv_string_length(jv_copy(*a));
+ int lenb = jv_string_length(jv_copy(*b));
+ int minlen = lena < lenb ? lena : lenb;
+ int r = memcmp(jv_string_value(*a), jv_string_value(*b), minlen);
+ if (r == 0) r = lena - lenb;
+ return r;
+}
+
+static void f_keys(jv input[], jv output[]) {
+ if (jv_get_kind(input[0]) == JV_KIND_OBJECT) {
+ int nkeys = jv_object_length(jv_copy(input[0]));
+ jv* keys = malloc(sizeof(jv) * nkeys);
+ int kidx = 0;
+ jv_object_foreach(i, input[0]) {
+ keys[kidx++] = jv_object_iter_key(input[0], i);
+ }
+ qsort(keys, nkeys, sizeof(jv), string_cmp);
+ output[0] = jv_array_sized(nkeys);
+ for (int i = 0; i<nkeys; i++) {
+ output[0] = jv_array_append(output[0], keys[i]);
+ }
+ free(keys);
+ jv_free(input[0]);
+ } else {
+ output[0] = jv_invalid_with_msg(jv_string_fmt("'keys' only supports object, not %s",
+ jv_kind_name(jv_get_kind(input[0]))));
+ jv_free(input[0]);
+ }
+}
+
static void f_type(jv input[], jv output[]) {
output[0] = jv_string(jv_kind_name(jv_get_kind(input[0])));
jv_free(input[0]);
@@ -243,6 +276,7 @@ static struct cfunction function_list[] = {
{f_divide, "_divide", CALL_BUILTIN_3_1},
{f_tonumber, "tonumber", CALL_BUILTIN_1_1},
{f_tostring, "tostring", CALL_BUILTIN_1_1},
+ {f_keys, "keys", CALL_BUILTIN_1_1},
{f_equal, "_equal", CALL_BUILTIN_3_1},
{f_less, "_less", CALL_BUILTIN_3_1},
{f_greater, "_greater", CALL_BUILTIN_3_1},
diff --git a/testdata b/testdata
index ea0b1cc6..6f04a1d5 100644
--- a/testdata
+++ b/testdata
@@ -223,6 +223,10 @@ null
[[], {}, [1,2], {"a":42}, "asdf"]
[0, 0, 2, 1, 4]
+map(keys)
+[{}, {"abcd":1,"abc":2,"abcde":3}, {"x":1, "z": 3, "y":2}]
+[[], ["abc","abcd","abcde"], ["x","y","z"]]
+
[1,2,empty,3,empty,4]
null
[1,2,3,4]