shithub: libmujs

Download patch

ref: ac953db0f7acd01f838ae4263f2ae3a7e831dbc4
parent: b1c99267f03ad327bd0079d629fb26cd391d9331
author: Tor Andersson <tor@ccxvii.net>
date: Mon Jan 27 12:59:36 EST 2014

Add more array functions.

And some internal wrapper functions to get/set array index properties.

--- a/jsarray.c
+++ b/jsarray.c
@@ -2,6 +2,49 @@
 #include "jsvalue.h"
 #include "jsbuiltin.h"
 
+static unsigned int js_getlength(js_State *J, int idx)
+{
+	unsigned int len;
+	js_getproperty(J, idx, "length");
+	len = js_touint32(J, -1);
+	js_pop(J, 1);
+	return len;
+}
+
+static void js_setlength(js_State *J, int idx, unsigned int len)
+{
+	js_pushnumber(J, len);
+	js_setproperty(J, idx, "length");
+}
+
+static int js_hasindex(js_State *J, int idx, unsigned int i)
+{
+	char buf[32];
+	sprintf(buf, "%u", i);
+	return js_hasproperty(J, idx, buf);
+}
+
+static void js_getindex(js_State *J, int idx, unsigned int i)
+{
+	char buf[32];
+	sprintf(buf, "%u", i);
+	js_getproperty(J, idx, buf);
+}
+
+static void js_setindex(js_State *J, int idx, unsigned int i)
+{
+	char buf[32];
+	sprintf(buf, "%u", i);
+	js_setproperty(J, idx, buf);
+}
+
+static void js_delindex(js_State *J, int idx, unsigned int i)
+{
+	char buf[32];
+	sprintf(buf, "%u", i);
+	js_delproperty(J, idx, buf);
+}
+
 static int jsB_new_Array(js_State *J, int argc)
 {
 	int i;
@@ -14,16 +57,15 @@
 			js_setproperty(J, -2, "length");
 		} else {
 			js_copy(J, 1);
-			js_setproperty(J, -2, "0");
+			js_setindex(J, -2, 0);
 		}
 	} else {
-		char buf[32];
 		for (i = 1; i <= argc; ++i) {
-			sprintf(buf, "%u", i - 1);
 			js_copy(J, i);
-			js_setproperty(J, -2, buf);
+			js_setindex(J, -2, i - 1);
 		}
 	}
+
 	return 1;
 }
 
@@ -30,7 +72,6 @@
 static int Ap_concat(js_State *J, int argc)
 {
 	unsigned int n, len, i;
-	char buf[32];
 
 	js_newarray(J);
 	n = 0;
@@ -40,16 +81,12 @@
 		if (js_isarray(J, -1)) {
 			unsigned int k = 0;
 
-			js_getproperty(J, -1, "length");
-			len = js_touint32(J, -1);
-			js_pop(J, 1);
+			len = js_getlength(J, -1);
 
 			while (k < len) {
-				sprintf(buf, "%u", k);
-				if (js_hasproperty(J, -1, buf)) {
-					js_getproperty(J, -1, buf);
-					sprintf(buf, "%u", n);
-					js_setproperty(J, -3, buf);
+				if (js_hasindex(J, -1, k)) {
+					js_getindex(J, -1, k);
+					js_setindex(J, -3, n);
 				}
 				++k;
 				++n;
@@ -56,8 +93,7 @@
 			}
 			js_pop(J, 1);
 		} else {
-			sprintf(buf, "%u", n);
-			js_setproperty(J, -2, buf);
+			js_setindex(J, -2, n);
 			++n;
 		}
 	}
@@ -68,14 +104,12 @@
 static int Ap_join(js_State *J, int argc)
 {
 	char * volatile out = NULL;
-	char buf[32];
-	const char *r, *sep = ",";
-	unsigned int seplen, n;
-	unsigned int k, len;
+	const char *sep = ",";
+	const char *r;
+	unsigned int seplen = 1;
+	unsigned int k, n, len;
 
-	js_getproperty(J, 0, "length");
-	len = js_touint32(J, -1);
-	js_pop(J, 1);
+	len = js_getlength(J, 0);
 
 	if (argc == 1 && !js_isundefined(J, 1)) {
 		sep = js_tostring(J, 1);
@@ -94,8 +128,7 @@
 
 	n = 1;
 	for (k = 0; k < len; ++k) {
-		sprintf(buf, "%u", k);
-		js_getproperty(J, 0, buf);
+		js_getindex(J, 0, k);
 		if (js_isundefined(J, -1) || js_isnull(J, -1))
 			r = "";
 		else
@@ -116,33 +149,26 @@
 	}
 
 	js_pushstring(J, out);
-
 	js_endtry(J);
 	free(out);
 	return 1;
 }
 
-
 static int Ap_pop(js_State *J, int argc)
 {
 	unsigned int n;
-	char buf[32];
 
-	js_getproperty(J, 0, "length");
-	n = js_touint32(J, -1);
-	js_pop(J, 1);
+	n = js_getlength(J, 0);
 
 	if (n > 0) {
-		sprintf(buf, "%u", n - 1);
-		js_getproperty(J, 0, buf);
-		js_delproperty(J, 0, buf);
-		js_pushnumber(J, n - 1);
-		js_setproperty(J, 0, "length");
+		js_getindex(J, 0, n - 1);
+		js_delindex(J, 0, n - 1);
+		js_setlength(J, 0, n - 1);
 	} else {
-		js_pushnumber(J, 0);
-		js_setproperty(J, 0, "length");
+		js_setlength(J, 0, 0);
 		js_pushundefined(J);
 	}
+
 	return 1;
 }
 
@@ -150,33 +176,200 @@
 {
 	unsigned int n;
 	int i;
-	char buf[32];
 
-	js_getproperty(J, 0, "length");
-	n = js_touint32(J, -1);
-	js_pop(J, 1);
+	n = js_getlength(J, 0);
 
-	for (i = 1; i <= argc; ++i) {
-		sprintf(buf, "%u", n);
+	for (i = 1; i <= argc; ++i, ++n) {
 		js_copy(J, i);
-		js_setproperty(J, 0, buf);
-		++n;
+		js_setindex(J, 0, n);
 	}
 
-	js_pushnumber(J, n);
-	js_setproperty(J, 0, "length");
+	js_setlength(J, 0, n);
 
 	js_pushnumber(J, n);
 	return 1;
 }
 
-// reverse
-// shift
-// slice
+static int Ap_reverse(js_State *J, int argc)
+{
+	unsigned int len, middle, lower;
+
+	len = js_getlength(J, 0);
+	middle = len / 2;
+	lower = 0;
+
+	while (lower != middle) {
+		unsigned int upper = len - lower - 1;
+		int haslower = js_hasindex(J, 0, lower);
+		int hasupper = js_hasindex(J, 0, upper);
+		if (haslower && hasupper) {
+			js_getindex(J, 0, lower);
+			js_getindex(J, 0, upper);
+			js_setindex(J, 0, lower);
+			js_setindex(J, 0, upper);
+		} else if (hasupper) {
+			js_getindex(J, 0, upper);
+			js_setindex(J, 0, lower);
+			js_delindex(J, 0, upper);
+		} else if (haslower) {
+			js_getindex(J, 0, lower);
+			js_setindex(J, 0, upper);
+			js_delindex(J, 0, lower);
+		}
+		++lower;
+	}
+
+	js_copy(J, 0);
+	return 1;
+}
+
+static int Ap_shift(js_State *J, int argc)
+{
+	unsigned int k, len;
+
+	len = js_getlength(J, 0);
+
+	if (len == 0) {
+		js_setlength(J, 0, 0);
+		js_pushundefined(J);
+		return 1;
+	}
+
+	js_getindex(J, 0, 0);
+
+	for (k = 1; k < len; ++k) {
+		if (js_hasindex(J, 0, k)) {
+			js_getindex(J, 0, k);
+			js_setindex(J, 0, k - 1);
+		} else {
+			js_delindex(J, 0, k - 1);
+		}
+	}
+
+	js_delindex(J, 0, len - 1);
+	js_setlength(J, 0, len - 1);
+
+	return 1;
+}
+
+static int Ap_slice(js_State *J, int argc)
+{
+	unsigned int len;
+	int s, e, n;
+
+	js_newarray(J);
+
+	len = js_getlength(J, 0);
+	s = js_tointeger(J, 1);
+	e = argc > 1 ? js_tointeger(J, 2) : len;
+
+	if (s < 0) s = s + len;
+	if (e < 0) e = e + len;
+
+	s = s < 0 ? 0 : s > len ? len : s;
+	e = e < 0 ? 0 : e > len ? len : e;
+
+	for (n = 0; s < e; ++s, ++n) {
+		if (js_hasindex(J, 0, s)) {
+			js_getindex(J, 0, s);
+			js_setindex(J, -2, n);
+		}
+	}
+
+	return 1;
+}
+
 // sort
-// splice
-// unshift
 
+static int Ap_splice(js_State *J, int argc)
+{
+	unsigned int len;
+	int start, del, add, k;
+
+	js_newarray(J);
+
+	len = js_getlength(J, 0);
+
+	start = js_tointeger(J, 1);
+	if (start < 0) start = start + len;
+	start = start < 0 ? 0 : start > len ? len : start;
+
+	del = js_tointeger(J, 2);
+	del = del < 0 ? 0 : del > len - start ? len - start : del;
+
+	/* copy deleted items to return array */
+	for (k = 0; k < del; ++k) {
+		if (js_hasindex(J, 0, start + k)) {
+			js_getindex(J, 0, start + k);
+			js_setindex(J, -2, k);
+		}
+	}
+
+	/* shift the tail to resize the hole left by deleted items */
+	add = argc - 2;
+	if (add < del) {
+		for (k = start; k < len - del; ++k) {
+			if (js_hasindex(J, 0, k + del)) {
+				js_getindex(J, 0, k + del);
+				js_setindex(J, 0, k + add);
+			} else {
+				js_delindex(J, 0, k + del);
+			}
+		}
+		for (k = len; k > len - del + add; --k) {
+			js_delindex(J, 0, k - 1);
+		}
+	} else if (add > del) {
+		for (k = len - del; k > start; --k) {
+			if (js_hasindex(J, 0, k + del - 1)) {
+				js_getindex(J, 0, k + del - 1);
+				js_setindex(J, 0, k + add - 1);
+			} else {
+				js_delindex(J, 0, k + add - 1);
+			}
+		}
+	}
+
+	/* copy new items into the hole */
+	for (k = 0; k < add; ++k) {
+		js_copy(J, 3 + k);
+		js_setindex(J, 0, start + k);
+	}
+
+	js_setlength(J, 0, len - del + add);
+
+	return 1;
+}
+
+static int Ap_unshift(js_State *J, int argc)
+{
+	unsigned int k, len;
+	int i;
+
+	len = js_getlength(J, 0);
+
+	for (k = len; k > 0; --k) {
+		int from = k - 1;
+		int to = k + argc - 1;
+		if (js_hasindex(J, 0, from)) {
+			js_getindex(J, 0, from);
+			js_setindex(J, 0, to);
+		} else {
+			js_delindex(J, 0, to);
+		}
+	}
+
+	for (i = 1; i <= argc; ++i) {
+		js_copy(J, i);
+		js_setindex(J, 0, i - 1);
+	}
+
+	js_setlength(J, 0, len + argc);
+
+	js_pushnumber(J, len + argc);
+	return 1;
+}
+
 static int Ap_toString(js_State *J, int argc)
 {
 	js_pop(J, argc);
@@ -203,6 +396,11 @@
 		jsB_propf(J, "join", Ap_join, 1);
 		jsB_propf(J, "pop", Ap_pop, 0);
 		jsB_propf(J, "push", Ap_push, 1);
+		jsB_propf(J, "reverse", Ap_reverse, 0);
+		jsB_propf(J, "shift", Ap_shift, 0);
+		jsB_propf(J, "slice", Ap_slice, 0);
+		jsB_propf(J, "splice", Ap_splice, 0);
+		jsB_propf(J, "unshift", Ap_unshift, 0);
 	}
 	js_newcconstructor(J, jsB_new_Array, jsB_new_Array, 1);
 	{
--- a/jsstring.c
+++ b/jsstring.c
@@ -144,12 +144,10 @@
 {
 	const char *haystack = js_tostring(J, 0);
 	const char *needle = js_tostring(J, 1);
-	int pos = strlen(haystack);
+	int pos = argc > 1 ? js_tointeger(J, 2) : strlen(haystack);
 	int len = strlen(needle);
 	int k = 0, last = -1;
 	Rune rune;
-	if (!js_isundefined(J, 2))
-		pos = js_tointeger(J, 2);
 	while (*haystack && k <= pos) {
 		if (!strncmp(haystack, needle, len))
 			last = k;
@@ -186,7 +184,7 @@
 	const char *str = js_tostring(J, 0);
 	int len = utflen(str);
 	int s = js_tointeger(J, 1);
-	int e = !js_isundefined(J, 2) ? js_tointeger(J, 2) : len;
+	int e = argc > 1 ? js_tointeger(J, 2) : len;
 	char *out;
 
 	s = s < 0 ? s + len : s;
@@ -214,7 +212,7 @@
 	const char *str = js_tostring(J, 0);
 	int len = utflen(str);
 	int s = js_tointeger(J, 1);
-	int e = !js_isundefined(J, 2) ? js_tointeger(J, 2) : len;
+	int e = argc > 1 ? js_tointeger(J, 2) : len;
 	char *out;
 
 	s = s < 0 ? 0 : s > len ? len : s;