From 9e743d517a047566996181549f05383948c0d0c0 Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Fri, 30 Nov 2012 20:27:16 +0000 Subject: [PATCH] Sort function and more general comparison operators. --- builtin.c | 66 ++++++------------- jv_aux.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ jv_aux.h | 6 ++ testdata | 4 ++ 4 files changed, 219 insertions(+), 47 deletions(-) diff --git a/builtin.c b/builtin.c index 756b069d..eea85ed6 100644 --- a/builtin.c +++ b/builtin.c @@ -3,6 +3,7 @@ #include "compile.h" #include "parser.h" #include "locfile.h" +#include "jv_aux.h" enum { CMP_OP_LESS, @@ -127,22 +128,11 @@ static void f_notequal(jv input[], jv output[]) { static void order_cmp(jv input[], jv output[], int op) { jv_free(input[0]); - jv a = input[2]; - jv b = input[1]; - if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { - double da = jv_number_value(a); - double db = jv_number_value(b); - output[0] = jv_bool((op == CMP_OP_LESS && da < db) || - (op == CMP_OP_LESSEQ && da <= db) || - (op == CMP_OP_GREATEREQ && da >= db) || - (op == CMP_OP_GREATER && da > db)); - } else { - output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to compare order of %s wrt %s", - jv_kind_name(jv_get_kind(a)), - jv_kind_name(jv_get_kind(b)))); - jv_free(a); - jv_free(b); - } + int r = jv_cmp(input[2], input[1]); + output[0] = jv_bool((op == CMP_OP_LESS && r < 0) || + (op == CMP_OP_LESSEQ && r <= 0) || + (op == CMP_OP_GREATEREQ && r >= 0) || + (op == CMP_OP_GREATER && r > 0)); } static void f_less(jv input[], jv output[]) { @@ -222,38 +212,9 @@ 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 +#include jv jv_lookup(jv t, jv k) { jv v; @@ -60,3 +62,191 @@ jv jv_insert(jv root, jv value, jv* path, int pathlen) { return jv_modify(root, jv_copy(*path), jv_insert(jv_lookup(jv_copy(root), jv_copy(*path)), value, path+1, pathlen-1)); } + + +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; +} + +jv jv_keys(jv x) { + if (jv_get_kind(x) == JV_KIND_OBJECT) { + int nkeys = jv_object_length(jv_copy(x)); + jv* keys = malloc(sizeof(jv) * nkeys); + int kidx = 0; + jv_object_foreach(i, x) { + keys[kidx++] = jv_object_iter_key(x, i); + } + qsort(keys, nkeys, sizeof(jv), string_cmp); + jv answer = jv_array_sized(nkeys); + for (int i = 0; i= jv_array_length(jv_copy(a)); + int b_done = i >= jv_array_length(jv_copy(b)); + if (a_done || b_done) { + r = b_done - a_done; //suddenly, logic + break; + } + jv xa = jv_array_get(jv_copy(a), i); + jv xb = jv_array_get(jv_copy(b), i); + r = jv_cmp(xa, xb); + i++; + } + break; + } + + case JV_KIND_OBJECT: { + jv keys_a = jv_keys(jv_copy(a)); + jv keys_b = jv_keys(jv_copy(b)); + r = jv_cmp(jv_copy(keys_a), keys_b); + if (r == 0) { + for (int i=0; ikey), jv_copy(b->key)); + // comparing by address if r == 0 makes the sort stable + return r ? r : (int)(a - b); +} + +static struct sort_entry* sort_items(jv objects, jv keys) { + assert(jv_get_kind(objects) == JV_KIND_ARRAY); + assert(jv_get_kind(keys) == JV_KIND_ARRAY); + assert(jv_array_length(jv_copy(objects)) == jv_array_length(jv_copy(keys))); + int n = jv_array_length(jv_copy(objects)); + struct sort_entry* entries = malloc(sizeof(struct sort_entry) * n); + for (int i=0; i