summaryrefslogtreecommitdiffhomepage
path: root/lib.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2023-05-28 20:52:10 +0200
committerJo-Philipp Wich <jo@mein.io>2023-05-30 10:11:34 +0200
commitd72eebeb168b8b350f3f9fb8cded8075464eef10 (patch)
tree84381541d89f97062744d75cfce839f278cbfeb5 /lib.c
parentd656d150905e8b24deb95707d675db60776c737f (diff)
lib: support object ordering in `uc_sort()`
Extend `uc_sort()` to utilize `ucv_object_sort()` in order to support reordering object keys. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c72
1 files changed, 63 insertions, 9 deletions
diff --git a/lib.c b/lib.c
index a0a1b9b..93ea022 100644
--- a/lib.c
+++ b/lib.c
@@ -404,11 +404,8 @@ uc_rindex(uc_vm_t *vm, size_t nargs)
}
static bool
-assert_mutable_array(uc_vm_t *vm, uc_value_t *val)
+assert_mutable(uc_vm_t *vm, uc_value_t *val)
{
- if (ucv_type(val) != UC_ARRAY)
- return false;
-
if (ucv_is_constant(val)) {
uc_vm_raise_exception(vm, EXCEPTION_TYPE,
"%s value is immutable",
@@ -420,6 +417,15 @@ assert_mutable_array(uc_vm_t *vm, uc_value_t *val)
return true;
}
+static bool
+assert_mutable_array(uc_vm_t *vm, uc_value_t *val)
+{
+ if (ucv_type(val) != UC_ARRAY)
+ return false;
+
+ return assert_mutable(vm, val);
+}
+
static uc_value_t *
uc_push(uc_vm_t *vm, size_t nargs)
{
@@ -894,7 +900,7 @@ default_cmp(uc_value_t *v1, uc_value_t *v2)
}
static int
-sort_fn(const void *k1, const void *k2)
+array_sort_fn(const void *k1, const void *k2)
{
uc_value_t *rv, *null = ucv_int64_new(0);
uc_value_t * const *v1 = k1;
@@ -928,21 +934,69 @@ sort_fn(const void *k1, const void *k2)
return res;
}
+static int
+object_sort_fn(const void *k1, const void *k2)
+{
+ uc_value_t *rv, *null = ucv_int64_new(0);
+ struct lh_entry * const *e1 = k1;
+ struct lh_entry * const *e2 = k2;
+ int res;
+
+ if (!sort_ctx.fn)
+ return strcmp((char *)lh_entry_k(*e1), (char *)lh_entry_k(*e2));
+
+ if (sort_ctx.ex)
+ return 0;
+
+ uc_vm_ctx_push(sort_ctx.vm);
+ uc_vm_stack_push(sort_ctx.vm, ucv_get(sort_ctx.fn));
+ uc_vm_stack_push(sort_ctx.vm, ucv_string_new((char *)lh_entry_k(*e1)));
+ uc_vm_stack_push(sort_ctx.vm, ucv_string_new((char *)lh_entry_k(*e2)));
+ uc_vm_stack_push(sort_ctx.vm, ucv_get((uc_value_t *)lh_entry_v(*e1)));
+ uc_vm_stack_push(sort_ctx.vm, ucv_get((uc_value_t *)lh_entry_v(*e2)));
+
+ if (uc_vm_call(sort_ctx.vm, true, 4)) {
+ sort_ctx.ex = true;
+
+ return 0;
+ }
+
+ rv = uc_vm_stack_pop(sort_ctx.vm);
+
+ ucv_compare(0, rv, null, &res);
+
+ ucv_put(null);
+ ucv_put(rv);
+
+ return res;
+}
+
static uc_value_t *
uc_sort(uc_vm_t *vm, size_t nargs)
{
- uc_value_t *arr = uc_fn_arg(0);
+ uc_value_t *val = uc_fn_arg(0);
uc_value_t *fn = uc_fn_arg(1);
- if (!assert_mutable_array(vm, arr))
+ if (!assert_mutable(vm, val))
return NULL;
sort_ctx.vm = vm;
sort_ctx.fn = fn;
- ucv_array_sort(arr, sort_fn);
+ switch (ucv_type(val)) {
+ case UC_ARRAY:
+ ucv_array_sort(val, array_sort_fn);
+ break;
+
+ case UC_OBJECT:
+ ucv_object_sort(val, object_sort_fn);
+ break;
+
+ default:
+ return NULL;
+ }
- return sort_ctx.ex ? NULL : ucv_get(arr);
+ return sort_ctx.ex ? NULL : ucv_get(val);
}
static uc_value_t *