From 0f9d44fd33591794afc23ce0cb36a9088bad88b3 Mon Sep 17 00:00:00 2001 From: Isaac de Wolff Date: Sat, 2 Nov 2024 09:49:06 +0100 Subject: [PATCH] A more intuitive compare function for ucv_object_sort_r(). Instead of having to deal with alien struct lh_entry pointers, the compare function gets to pairs of (const char *key, const uc_value_t *value). --- include/ucode/types.h | 2 +- lib.c | 12 +++++----- types.c | 54 +++++++++++++++++++++++++++++++------------ 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/include/ucode/types.h b/include/ucode/types.h index 2cb4bda..892d294 100644 --- a/include/ucode/types.h +++ b/include/ucode/types.h @@ -401,7 +401,7 @@ uc_value_t *ucv_object_new(uc_vm_t *); uc_value_t *ucv_object_get(uc_value_t *, const char *, bool *); bool ucv_object_add(uc_value_t *, const char *, uc_value_t *); void ucv_object_sort(uc_value_t *, int (*)(const void *, const void *)); -void ucv_object_sort_r(uc_value_t *, int (*)(const struct lh_entry *, const struct lh_entry *,void *), void *); +void ucv_object_sort_r(uc_value_t *, int (*)(const char *key1, const uc_value_t *value1, const char *key2, const uc_value_t *value2,void *), void *); bool ucv_object_delete(uc_value_t *, const char *); size_t ucv_object_length(uc_value_t *); diff --git a/lib.c b/lib.c index 97d57f8..37a8859 100644 --- a/lib.c +++ b/lib.c @@ -1475,24 +1475,24 @@ array_sort_fn(const uc_value_t *cv1, const uc_value_t *cv2, void *user ) } static int -object_sort_fn(const struct lh_entry *e1, const struct lh_entry *e2, void *user ) +object_sort_fn(const char *key1, const uc_value_t *value1, const char *key2, const uc_value_t *value2, void *user ) { uc_value_t *rv, *null = ucv_int64_new(0); int res; sort_ctx_t *ctx = user; if (!ctx->fn) - return strcmp((char *)lh_entry_k(e1), (char *)lh_entry_k(e2)); + return strcmp( key1, key2 ); if (ctx->ex) return 0; uc_vm_ctx_push(ctx->vm); uc_vm_stack_push(ctx->vm, ucv_get(ctx->fn)); - uc_vm_stack_push(ctx->vm, ucv_string_new((char *)lh_entry_k(e1))); - uc_vm_stack_push(ctx->vm, ucv_string_new((char *)lh_entry_k(e2))); - uc_vm_stack_push(ctx->vm, ucv_get((uc_value_t *)lh_entry_v(e1))); - uc_vm_stack_push(ctx->vm, ucv_get((uc_value_t *)lh_entry_v(e2))); + uc_vm_stack_push(ctx->vm, ucv_string_new(key1)); + uc_vm_stack_push(ctx->vm, ucv_string_new(key2)); + uc_vm_stack_push(ctx->vm, ucv_get((uc_value_t *)value1)); + uc_vm_stack_push(ctx->vm, ucv_get((uc_value_t *)value2)); if (uc_vm_call(ctx->vm, true, 4)) { ctx->ex = true; diff --git a/types.c b/types.c index e6032af..441ca61 100644 --- a/types.c +++ b/types.c @@ -1005,9 +1005,29 @@ ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val) return true; } -void -ucv_object_sort_r(uc_value_t *uv, - int (*cmp)( const struct lh_entry *, const struct lh_entry *, void *), void *ctx ) +static int +pointer_dissecting_sort_fn( const void *p1, const void *p2, void *user ) +{ + struct lh_entry *const *pe1 = p1; + struct lh_entry *const *pe2 = p2; + const struct lh_entry *e1 = pe1 ? *pe1 : 0; + const struct lh_entry *e2 = pe2 ? *pe2 : 0; + + void **inbetween = user; + int (*cmp)(const char *, const uc_value_t *, const char *, const uc_value_t *,void *) = inbetween[ 0 ]; + return (*cmp)( + e1 ? (const char *)lh_entry_k(e1) : 0, + e1 ? (const uc_value_t *)lh_entry_v(e1) : 0, + e2 ? (const char *)lh_entry_k(e2) : 0, + e2 ? (const uc_value_t *)lh_entry_v(e2) : 0, + inbetween[ 1 ] ); +} + +static void +ucv_object_sort_r2(uc_value_t *uv, + int (*cmp1)(const char *, const uc_value_t *, const char *, const uc_value_t *,void *), + void *ctx, + int (*cmp2)(const void *, const void *) ) { uc_object_t *object = (uc_object_t *)uv; struct lh_table *t; @@ -1028,10 +1048,16 @@ ucv_object_sort_r(uc_value_t *uv, if (!keys.entries) return; - void *inbetween[2] = { cmp, ctx }; - - qsort_r(keys.entries, keys.count, sizeof(keys.entries[0]), - pointer_removing_sort_fn, inbetween ); + if( cmp1 ) + { + void *inbetween[2] = { cmp1, ctx }; + qsort_r(keys.entries, keys.count, sizeof(keys.entries[0]), + pointer_dissecting_sort_fn, inbetween ); + } + else if( cmp2 ) + { + qsort(keys.entries, keys.count, sizeof(keys.entries[0]),cmp2); + } for (i = 0; i < keys.count; i++) { e = keys.entries[i]; @@ -1051,23 +1077,21 @@ ucv_object_sort_r(uc_value_t *uv, uc_vector_clear(&keys); } -static int -pointer_adding_sort_fn( const struct lh_entry *e1, const struct lh_entry *e2, void *user ) + +void +ucv_object_sort_r(uc_value_t *uv, + int (*cmp)(const char *, const uc_value_t *, const char *, const uc_value_t *,void *), void *ctx ) { - const void *p1 = e1; - const void *p2 = e2; - int (*cmp)( const void *, const void * ) = user; - return cmp( &p1, &p2 ); + ucv_object_sort_r2( uv, cmp, ctx, 0 ); } void ucv_object_sort(uc_value_t *uv, int (*cmp)( const void *, const void * ) ) { - return ucv_object_sort_r( uv, pointer_adding_sort_fn, cmp ); + return ucv_object_sort_r2( uv, 0, 0, cmp ); } - bool ucv_object_delete(uc_value_t *uv, const char *key) {