Skip to content

Commit

Permalink
A more intuitive compare function for ucv_object_sort_r(). Instead of…
Browse files Browse the repository at this point in the history
… having to deal with alien struct lh_entry pointers,

the compare function gets to pairs of (const char *key, const uc_value_t *value).
  • Loading branch information
IdWV committed Nov 2, 2024
1 parent 5f64ba3 commit 0f9d44f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 22 deletions.
2 changes: 1 addition & 1 deletion include/ucode/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);

Expand Down
12 changes: 6 additions & 6 deletions lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
54 changes: 39 additions & 15 deletions types.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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];
Expand All @@ -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)
{
Expand Down

0 comments on commit 0f9d44f

Please sign in to comment.