From b749e23cb4ff42e06d9e1e75196745be4ca40a59 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 4 Feb 2014 15:04:45 +0100 Subject: [PATCH] String.split(). --- jsregexp.c | 2 + jsstring.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/jsregexp.c b/jsregexp.c index e42b891..7205a23 100644 --- a/jsregexp.c +++ b/jsregexp.c @@ -83,8 +83,10 @@ static int jsB_new_RegExp(js_State *J, int argc) js_pop(J, 1); } else if (js_isundefined(J, 1)) { pattern = ""; + flags = 0; } else { pattern = js_tostring(J, 1); + flags = 0; } if (argc > 1) { diff --git a/jsstring.c b/jsstring.c index 0cd08ab..b3d4c1b 100644 --- a/jsstring.c +++ b/jsstring.c @@ -513,6 +513,119 @@ static int Sp_replace(js_State *J, int argc) return Sp_replace_string(J, argc); } +static int Sp_split_regexp(js_State *J, int argc) +{ + const char *str = js_tostring(J, 0); + unsigned int limit = !js_isundefined(J, 2) ? js_touint32(J, 2) : 1 << 30; + regmatch_t m[10]; + regex_t *prog; + int flags; + unsigned int len, k, e; + unsigned int p, a, b, c; + + prog = js_toregexp(J, 1, &flags); + + js_newarray(J); + len = 0; + + e = strlen(str); + + /* splitting the empty string */ + if (e == 0) { + if (regexec(prog, str, nelem(m), m, 0)) { + if (len == limit) return 1; + js_pushliteral(J, ""); + js_setindex(J, -2, 0); + } + return 1; + } + + p = a = 0; + while (a < e) { + if (regexec(prog, str + a, nelem(m), m, a > 0 ? REG_NOTBOL : 0)) + break; /* no match */ + + b = a + m[0].rm_so; + c = a + m[0].rm_eo; + + /* empty string at end of last match */ + if (b == p) { + ++a; + continue; + } + + if (len == limit) return 1; + js_pushlstring(J, str + p, b - p); + js_setindex(J, -2, len++); + + for (k = 1; k < nelem(m) && m[k].rm_so >= 0; ++k) { + if (len == limit) return 1; + js_pushlstring(J, str + a + m[k].rm_so, m[k].rm_eo - m[k].rm_so); + js_setindex(J, -2, len++); + } + + a = p = c; + } + + if (len == limit) return 1; + js_pushstring(J, str + p); + js_setindex(J, -2, len); + + return 1; +} + +static int Sp_split_string(js_State *J, int argc) +{ + const char *str = js_tostring(J, 0); + const char *sep = js_tostring(J, 1); + unsigned int limit = !js_isundefined(J, 2) ? js_touint32(J, 2) : 1 << 30; + unsigned int i, n; + + js_newarray(J); + + n = strlen(sep); + + /* empty string */ + if (n == 0) { + Rune rune; + for (i = 0; *str && i < limit; ++i) { + n = chartorune(&rune, str); + js_pushlstring(J, str, n); + js_setindex(J, -2, i); + str += n; + } + return 1; + } + + for (i = 0; str && i < limit; ++i) { + const char *s = strstr(str, sep); + if (s) { + js_pushlstring(J, str, s-str); + js_setindex(J, -2, i); + str = s + n; + } else { + js_pushstring(J, str); + js_setindex(J, -2, i); + str = NULL; + } + } + + return 1; +} + +static int Sp_split(js_State *J, int argc) +{ + if (js_isundefined(J, 1)) { + js_newarray(J); + js_copy(J, 0); + js_setindex(J, -2, 0); + return 1; + } + if (js_isregexp(J, 1)) + return Sp_split_regexp(J, argc); + return Sp_split_string(J, argc); +} + void jsB_initstring(js_State *J) { J->String_prototype->u.string = ""; @@ -531,7 +644,7 @@ void jsB_initstring(js_State *J) jsB_propf(J, "replace", Sp_replace, 2); jsB_propf(J, "search", Sp_search, 1); jsB_propf(J, "slice", Sp_slice, 2); - // split (uses regexp) + jsB_propf(J, "split", Sp_split, 2); jsB_propf(J, "substring", Sp_substring, 2); jsB_propf(J, "toLowerCase", Sp_toLowerCase, 0); jsB_propf(J, "toLocaleLowerCase", Sp_toLowerCase, 0);