shithub: libmujs

Download patch

ref: b1c99267f03ad327bd0079d629fb26cd391d9331
parent: 489365dcf31e78848255f7efab2661e02bd79d66
author: Tor Andersson <tor@ccxvii.net>
date: Mon Jan 27 08:08:24 EST 2014

Implement substring and slice.

--- a/jsstring.c
+++ b/jsstring.c
@@ -46,6 +46,21 @@
 	return rune;
 }
 
+static inline const char *utfindex(const char *s, int i)
+{
+	Rune rune = 0;
+	while (i-- > 0) {
+		rune = *(unsigned char*)s;
+		if (rune < Runeself) {
+			if (rune == 0)
+				return NULL;
+			++s;
+		} else
+			s += chartorune(&rune, s);
+	}
+	return s;
+}
+
 static int Sp_charAt(js_State *J, int argc)
 {
 	char buf[UTFmax + 1];
@@ -109,7 +124,7 @@
 {
 	const char *haystack = js_tostring(J, 0);
 	const char *needle = js_tostring(J, 1);
-	int pos = argc > 1 ? js_tointeger(J, 2) : 0;
+	int pos = js_tointeger(J, 2);
 	int len = strlen(needle);
 	int k = 0;
 	Rune rune;
@@ -133,7 +148,7 @@
 	int len = strlen(needle);
 	int k = 0, last = -1;
 	Rune rune;
-	if (argc > 1 && !js_isundefined(J, 2))
+	if (!js_isundefined(J, 2))
 		pos = js_tointeger(J, 2);
 	while (*haystack && k <= pos) {
 		if (!strncmp(haystack, needle, len))
@@ -152,6 +167,73 @@
 	return strcmp(a, b);
 }
 
+static char *substr(js_State *J, const char *src, int a, int b)
+{
+	int n = b - a;
+	const char *s = utfindex(src, a);
+	char *dst = malloc(UTFmax * n + 1), *d = dst;
+	while (n--) {
+		Rune rune;
+		s += chartorune(&rune, s);
+		d += runetochar(d, &rune);
+	}
+	*d = 0;
+	return dst;
+}
+
+static int Sp_slice(js_State *J, int argc)
+{
+	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;
+	char *out;
+
+	s = s < 0 ? s + len : s;
+	e = e < 0 ? e + len : e;
+
+	s = s < 0 ? 0 : s > len ? len : s;
+	e = e < 0 ? 0 : e > len ? len : e;
+
+	if (s < e)
+		out = substr(J, str, s, e);
+	else
+		out = substr(J, str, e, s);
+
+	if (js_try(J)) {
+		free(out);
+		js_throw(J);
+	}
+	js_pushstring(J, out);
+	js_endtry(J);
+	return 1;
+}
+
+static int Sp_substring(js_State *J, int argc)
+{
+	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;
+	char *out;
+
+	s = s < 0 ? 0 : s > len ? len : s;
+	e = e < 0 ? 0 : e > len ? len : e;
+
+	if (s < e)
+		out = substr(J, str, s, e);
+	else
+		out = substr(J, str, e, s);
+
+	if (js_try(J)) {
+		free(out);
+		js_throw(J);
+	}
+	js_pushstring(J, out);
+	js_endtry(J);
+	return 1;
+}
+
 static int Sp_toLowerCase(js_State *J, int argc)
 {
 	const char *src = js_tostring(J, 0);
@@ -235,16 +317,17 @@
 		jsB_propf(J, "indexOf", Sp_indexOf, 1);
 		jsB_propf(J, "lastIndexOf", Sp_lastIndexOf, 1);
 		jsB_propf(J, "localeCompare", Sp_localeCompare, 1);
-		//jsB_propf(J, "slice", Sp_slice, 2);
+		jsB_propf(J, "slice", Sp_slice, 2);
 		// match (uses regexp)
 		// replace (uses regexp)
 		// search (uses regexp)
 		// split (uses regexp)
-		//jsB_propf(J, "substring", Sp_substring, 2);
+		jsB_propf(J, "substring", Sp_substring, 2);
 		jsB_propf(J, "toLowerCase", Sp_toLowerCase, 0);
 		jsB_propf(J, "toLocaleLowerCase", Sp_toLowerCase, 0);
 		jsB_propf(J, "toUpperCase", Sp_toUpperCase, 0);
 		jsB_propf(J, "toLocaleUpperCase", Sp_toUpperCase, 0);
+		// trim (ES5)
 	}
 	js_newcconstructor(J, jsB_String, jsB_new_String, 1);
 	{