ref: caabe08cb11e8c879173b599030d897a7e852373
parent: b0e3f5e80d3a5868c45c665a6f1ff84b07d49ed2
author: Tor Andersson <tor.andersson@artifex.com>
date: Tue May 15 07:48:11 EDT 2018
Use qsort to sort arrays.
--- a/jsarray.c
+++ b/jsarray.c
@@ -248,77 +248,72 @@
js_setindex(J, -2, n);
}
-static int compare(js_State *J, int x, int y, int *hasx, int *hasy, int hasfn)
+struct sortslot {
+ js_Value v;
+ js_State *J;
+};
+
+static int sortcmp(const void *avoid, const void *bvoid)
{
+ const struct sortslot *aslot = avoid, *bslot = bvoid;
+ const js_Value *a = &aslot->v, *b = &bslot->v;
+ js_State *J = aslot->J;
const char *sx, *sy;
int c;
- *hasx = js_hasindex(J, 0, x);
- *hasy = js_hasindex(J, 0, y);
+ int unx = (a->type == JS_TUNDEFINED);
+ int uny = (b->type == JS_TUNDEFINED);
+ if (unx) return !uny;
+ if (uny) return -1;
- if (*hasx && *hasy) {
- int unx = js_isundefined(J, -2);
- int uny = js_isundefined(J, -1);
- if (unx && uny) return 0;
- if (unx) return 1;
- if (uny) return -1;
-
- if (hasfn) {
- js_copy(J, 1); /* copy function */
- js_pushundefined(J); /* set this object */
- js_copy(J, -4); /* copy x */
- js_copy(J, -4); /* copy y */
- js_call(J, 2);
- c = js_tonumber(J, -1);
- js_pop(J, 1);
- return c;
- }
-
- /* Ap_sort expects the original values to remain on the stack,
- * but because js_tostring may mutate the stack slot, make a copy first. */
- js_copy(J, -2);
- js_copy(J, -2);
+ if (js_iscallable(J, 1)) {
+ js_copy(J, 1); /* copy function */
+ js_pushundefined(J);
+ js_pushvalue(J, *a);
+ js_pushvalue(J, *b);
+ js_call(J, 2);
+ c = js_tonumber(J, -1);
+ js_pop(J, 1);
+ } else {
+ js_pushvalue(J, *a);
+ js_pushvalue(J, *b);
sx = js_tostring(J, -2);
sy = js_tostring(J, -1);
c = strcmp(sx, sy);
js_pop(J, 2);
- return c;
}
-
- if (*hasx) return -1;
- if (*hasy) return 1;
- return 0;
+ return c;
}
static void Ap_sort(js_State *J)
{
- int len, i, k;
- int hasx, hasy, hasfn;
+ struct sortslot *array = NULL;
+ int i, len;
len = js_getlength(J, 0);
- hasfn = js_iscallable(J, 1);
- hasx = hasy = 0;
+ array = js_malloc(J, len * sizeof *array);
+ if (js_try(J)) {
+ js_free(J, array);
+ js_throw(J);
+ }
- for (i = 1; i < len; ++i) {
- k = i;
- while (k > 0 && compare(J, k - 1, k, &hasx, &hasy, hasfn) > 0) {
- if (hasx && hasy) {
- js_setindex(J, 0, k - 1);
- js_setindex(J, 0, k);
- } else if (hasx) {
- js_delindex(J, 0, k - 1);
- js_setindex(J, 0, k);
- } else if (hasy) {
- js_setindex(J, 0, k - 1);
- js_delindex(J, 0, k);
- }
- hasx = hasy = 0;
- --k;
- }
- if (hasx + hasy > 0)
- js_pop(J, hasx + hasy);
+ for (i = 0; i < len; ++i) {
+ js_getindex(J, 0, i);
+ array[i].v = *js_tovalue(J, -1);
+ array[i].J = J;
+ js_pop(J, 1);
}
+
+ qsort(array, len, sizeof *array, sortcmp);
+
+ for (i = 0; i < len; ++i) {
+ js_pushvalue(J, array[i].v);
+ js_setindex(J, 0, i);
+ }
+
+ js_endtry(J);
+ js_free(J, array);
js_copy(J, 0);
}