summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/ucode/types.h2
-rw-r--r--include/ucode/util.h28
-rw-r--r--types.c69
3 files changed, 96 insertions, 3 deletions
diff --git a/include/ucode/types.h b/include/ucode/types.h
index bf8b9f2..9cd7cfc 100644
--- a/include/ucode/types.h
+++ b/include/ucode/types.h
@@ -388,6 +388,7 @@ uc_value_t *ucv_array_push(uc_value_t *, uc_value_t *);
uc_value_t *ucv_array_shift(uc_value_t *);
uc_value_t *ucv_array_unshift(uc_value_t *, uc_value_t *);
void ucv_array_sort(uc_value_t *, int (*)(const void *, const void *));
+void ucv_array_sort_r(uc_value_t *, int (*)(uc_value_t *, uc_value_t *, void *), void *);
bool ucv_array_delete(uc_value_t *, size_t, size_t);
bool ucv_array_set(uc_value_t *, size_t, uc_value_t *);
size_t ucv_array_length(uc_value_t *);
@@ -396,6 +397,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 char *, uc_value_t *, const char *, uc_value_t *, void *), void *);
bool ucv_object_delete(uc_value_t *, const char *);
size_t ucv_object_length(uc_value_t *);
diff --git a/include/ucode/util.h b/include/ucode/util.h
index cc92e33..1360d28 100644
--- a/include/ucode/util.h
+++ b/include/ucode/util.h
@@ -267,4 +267,32 @@ uc_vector_extend_(char **base, size_t itemsize, size_t count, size_t add)
iter != NULL && iter >= (vec)->entries; \
iter--)
+#ifdef __APPLE__
+
+# define uc_vector_sort_cb(fn_, optype_, udtype_, ...) \
+ int fn_(void *ud, const void *k1, const void *k2) { \
+ optype_ v1 = *(optype_ *)k1; \
+ optype_ v2 = *(optype_ *)k2; \
+ udtype_ ctx = (udtype_)ud; \
+ __VA_ARGS__ \
+ }
+
+# define uc_vector_sort(v_, cmp_, ud_) \
+ qsort_r((v_)->entries, (v_)->count, sizeof((v_)->entries[0]), ud_, cmp_)
+
+#else
+
+# define uc_vector_sort_cb(fn_, optype_, udtype_, ...) \
+ int fn_(const void *k1, const void *k2, void *ud) { \
+ optype_ v1 = *(optype_ *)k1; \
+ optype_ v2 = *(optype_ *)k2; \
+ udtype_ ctx = (udtype_)ud; \
+ __VA_ARGS__ \
+ }
+
+# define uc_vector_sort(v_, cmp_, ud_) \
+ qsort_r((v_)->entries, (v_)->count, sizeof((v_)->entries[0]), cmp_, ud_)
+
+#endif
+
#endif /* UCODE_UTIL_H */
diff --git a/types.c b/types.c
index 26f588e..8c30614 100644
--- a/types.c
+++ b/types.c
@@ -785,6 +785,28 @@ ucv_array_unshift(uc_value_t *uv, uc_value_t *item)
return item;
}
+typedef struct {
+ int (*cmp)(uc_value_t *, uc_value_t *, void *);
+ void *ud;
+} array_sort_ctx_t;
+
+static uc_vector_sort_cb(ucv_array_sort_r_cb, uc_value_t *, array_sort_ctx_t *, {
+ return ctx->cmp(v1, v2, ctx->ud);
+});
+
+void
+ucv_array_sort_r(uc_value_t *uv,
+ int (*cmp)(uc_value_t *, uc_value_t *, void *), void *ud)
+{
+ array_sort_ctx_t ctx = { .cmp = cmp, .ud = ud };
+ uc_array_t *array = (uc_array_t *)uv;
+
+ if (ucv_type(uv) != UC_ARRAY || array->count <= 1)
+ return;
+
+ uc_vector_sort(array, ucv_array_sort_r_cb, &ctx);
+}
+
void
ucv_array_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
{
@@ -985,8 +1007,29 @@ ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val)
return true;
}
-void
-ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
+
+typedef struct {
+ int (*cmp)(const void *, const void *);
+ int (*cmpr)(const char *, uc_value_t *, const char *, uc_value_t *, void *);
+ void *ud;
+} object_sort_ctx_t;
+
+static uc_vector_sort_cb(ucv_object_sort_cb, const void *, object_sort_ctx_t *, {
+ (void)v1;
+ (void)v2;
+
+ return ctx->cmp(k1, k2);
+});
+
+static uc_vector_sort_cb(ucv_object_sort_r_cb, const struct lh_entry *, object_sort_ctx_t *, {
+ return ctx->cmpr(
+ v1 ? lh_entry_k(v1) : NULL, v1 ? lh_entry_v(v1) : NULL,
+ v2 ? lh_entry_k(v2) : NULL, v2 ? lh_entry_v(v2) : NULL,
+ ctx->ud);
+});
+
+static void
+ucv_object_sort_common(uc_value_t *uv, object_sort_ctx_t *ctx)
{
uc_object_t *object = (uc_object_t *)uv;
struct lh_table *t;
@@ -1007,7 +1050,8 @@ ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
if (!keys.entries)
return;
- qsort(keys.entries, keys.count, sizeof(keys.entries[0]), cmp);
+ uc_vector_sort(&keys,
+ ctx->cmpr ? ucv_object_sort_r_cb : ucv_object_sort_cb, ctx);
for (i = 0; i < keys.count; i++) {
e = keys.entries[i];
@@ -1027,6 +1071,25 @@ ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
uc_vector_clear(&keys);
}
+void
+ucv_object_sort_r(uc_value_t *uv,
+ int (*cmp)(const char *, uc_value_t *,
+ const char *, uc_value_t *, void *),
+ void *ud)
+{
+ object_sort_ctx_t ctx = { .cmp = NULL, .cmpr = cmp, .ud = ud };
+
+ ucv_object_sort_common(uv, &ctx);
+}
+
+void
+ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
+{
+ object_sort_ctx_t ctx = { .cmp = cmp, .cmpr = NULL, .ud = NULL };
+
+ ucv_object_sort_common(uv, &ctx);
+}
+
bool
ucv_object_delete(uc_value_t *uv, const char *key)
{