From ab5236f243874178ac55207301a6d9a3ca0eeade Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 10 Feb 2014 15:01:52 +0100 Subject: [PATCH] UTF string index/pointer juggling. --- jsi.h | 3 +- jsrun.c | 16 ++++++++- jsstring.c | 104 +++++++++++++++++++++++++++-------------------------- 3 files changed, 70 insertions(+), 53 deletions(-) diff --git a/jsi.h b/jsi.h index e3dccc4..5f3a85d 100644 --- a/jsi.h +++ b/jsi.h @@ -41,7 +41,8 @@ void js_newscript(js_State *J, js_Function *function); js_Regexp *js_toregexp(js_State *J, int idx); int js_isarrayindex(js_State *J, const char *str, unsigned int *idx); int js_runeat(js_State *J, const char *s, int i); -void js_pushcharat(js_State *J, const char *s, int pos); +int js_utfptrtoidx(const char *s, const char *p); +const char *js_utfidxtoptr(const char *s, int i); void js_dup(js_State *J); void js_rot2(js_State *J); diff --git a/jsrun.c b/jsrun.c index 5e9fbb0..4a6473d 100644 --- a/jsrun.c +++ b/jsrun.c @@ -3,6 +3,8 @@ #include "jsvalue.h" #include "jsrun.h" +#include "utf.h" + static void jsR_run(js_State *J, js_Function *F); /* Push values on stack */ @@ -365,6 +367,18 @@ int js_isarrayindex(js_State *J, const char *str, unsigned int *idx) return !strcmp(buf, str); } +static void js_pushrune(js_State *J, Rune rune) +{ + char buf[UTFmax + 1]; + if (rune > 0) { + buf[runetochar(buf, &rune)] = 0; + js_pushstring(J, buf); + } else { + js_pushundefined(J); + } +} + + static int jsR_hasproperty(js_State *J, js_Object *obj, const char *name) { js_Property *ref; @@ -383,7 +397,7 @@ static int jsR_hasproperty(js_State *J, js_Object *obj, const char *name) return 1; } if (js_isarrayindex(J, name, &k)) { - js_pushcharat(J, obj->u.s.string, k); + js_pushrune(J, js_runeat(J, obj->u.s.string, k)); return 1; } } diff --git a/jsstring.c b/jsstring.c index f6bba25..1b64ac6 100644 --- a/jsstring.c +++ b/jsstring.c @@ -7,6 +7,50 @@ #define nelem(a) (sizeof (a) / sizeof (a)[0]) +int js_runeat(js_State *J, const char *s, int i) +{ + Rune rune = 0; + while (i-- >= 0) { + rune = *(unsigned char*)s; + if (rune < Runeself) { + if (rune == 0) + return 0; + ++s; + } else + s += chartorune(&rune, s); + } + return rune; +} + +const char *js_utfidxtoptr(const char *s, int i) +{ + Rune rune; + while (i-- > 0) { + rune = *(unsigned char*)s; + if (rune < Runeself) { + if (rune == 0) + return NULL; + ++s; + } else + s += chartorune(&rune, s); + } + return s; +} + +int js_utfptrtoidx(const char *s, const char *p) +{ + Rune rune; + int i = 0; + while (s < p) { + if (*(unsigned char *)s < Runeself) + ++s; + else + s += chartorune(&rune, s); + ++i; + } + return i; +} + static int jsB_new_String(js_State *J, int argc) { js_newstring(J, js_isdefined(J, 1) ? js_tostring(J, 1) : ""); @@ -35,48 +79,6 @@ static int Sp_valueOf(js_State *J, int argc) return 1; } -int js_runeat(js_State *J, const char *s, int i) -{ - Rune rune = 0; - while (i-- >= 0) { - rune = *(unsigned char*)s; - if (rune < Runeself) { - if (rune == 0) - return 0; - ++s; - } else - s += chartorune(&rune, s); - } - return rune; -} - -static inline const char *utfidx(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; -} - -void js_pushcharat(js_State *J, const char *s, int pos) -{ - char buf[UTFmax + 1]; - Rune rune = js_runeat(J, s, pos); - if (rune > 0) { - buf[runetochar(buf, &rune)] = 0; - js_pushstring(J, buf); - } else { - js_pushundefined(J); - } -} - static int Sp_charAt(js_State *J, int argc) { char buf[UTFmax + 1]; @@ -196,11 +198,11 @@ static int Sp_slice(js_State *J, int argc) e = e < 0 ? 0 : e > len ? len : e; if (s < e) { - ss = utfidx(str, s); - ee = utfidx(ss, e - s); + ss = js_utfidxtoptr(str, s); + ee = js_utfidxtoptr(ss, e - s); } else { - ss = utfidx(str, e); - ee = utfidx(ss, s - e); + ss = js_utfidxtoptr(str, e); + ee = js_utfidxtoptr(ss, s - e); } js_pushlstring(J, ss, ee - ss); @@ -219,11 +221,11 @@ static int Sp_substring(js_State *J, int argc) e = e < 0 ? 0 : e > len ? len : e; if (s < e) { - ss = utfidx(str, s); - ee = utfidx(ss, e - s); + ss = js_utfidxtoptr(str, s); + ee = js_utfidxtoptr(ss, e - s); } else { - ss = utfidx(str, e); - ee = utfidx(ss, s - e); + ss = js_utfidxtoptr(str, e); + ee = js_utfidxtoptr(ss, s - e); } js_pushlstring(J, ss, ee - ss); @@ -381,7 +383,7 @@ static int Sp_search(js_State *J, int argc) re = js_toregexp(J, -1); if (!regexec(re->prog, text, nelem(m), m, 0)) - js_pushnumber(J, m[0].rm_so); // TODO: convert to utf-8 index offset + js_pushnumber(J, js_utfptrtoidx(text, text + m[0].rm_so)); else js_pushnumber(J, -1);