summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorruki <[email protected]>2026-01-21 00:32:48 +0800
committerruki <[email protected]>2026-01-21 00:32:48 +0800
commit443fc30ae713b14623ac20bd5f1e8fdb12740783 (patch)
tree3ec726af7f2c4452726bd825fa240341ad01fb0a /core/src
parent91843ffb82564d29ce9a9e386f2c9292620a5ba9 (diff)
improve lastof
Diffstat (limited to 'core/src')
-rw-r--r--core/src/xmake/string/lastof.c42
-rw-r--r--core/src/xmake/utf8/lastof.c38
-rw-r--r--core/src/xmake/utf8/utf8.c22
-rw-r--r--core/src/xmake/utf8/utf8.h4
4 files changed, 44 insertions, 62 deletions
diff --git a/core/src/xmake/string/lastof.c b/core/src/xmake/string/lastof.c
index 9ac6c6784..912647a9c 100644
--- a/core/src/xmake/string/lastof.c
+++ b/core/src/xmake/string/lastof.c
@@ -29,39 +29,7 @@
* includes
*/
#include "prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * private implementation
- */
-static tb_void_t xm_string_lastof_str(
- lua_State *lua, tb_char_t const *cstr, tb_size_t nstr, tb_char_t const *csubstr, tb_size_t nsubstr) {
- // find it
- tb_char_t const *curr = tb_null;
- tb_char_t const *next = cstr;
- do {
- next = tb_strstr(next, csubstr); // faster than tb_strnstr()
- if (next) {
- curr = next;
- next += nsubstr;
- }
-
- } while (!next);
-
- // found?
- if (curr) {
- lua_pushinteger(lua, curr - cstr + 1);
- } else {
- lua_pushnil(lua);
- }
-}
-static tb_void_t xm_string_lastof_chr(lua_State *lua, tb_char_t const *cstr, tb_size_t nstr, tb_char_t ch) {
- tb_char_t const *pos = tb_strrchr(cstr, ch); // faster than tb_strnrchr()
- if (pos) {
- lua_pushinteger(lua, pos - cstr + 1);
- } else {
- lua_pushnil(lua);
- }
-}
+#include "../utf8/utf8.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
@@ -84,11 +52,11 @@ tb_int_t xm_string_lastof(lua_State *lua) {
tb_char_t const *csubstr = luaL_checklstring(lua, 2, &nsubstr);
// lastof it
- lua_newtable(lua);
- if (nsubstr == 1) {
- xm_string_lastof_chr(lua, cstr, (tb_size_t)nstr, csubstr[0]);
+ tb_long_t char_pos = xm_utf8_lastof_impl(cstr, nstr, csubstr, nsubstr);
+ if (char_pos > 0) {
+ lua_pushinteger(lua, char_pos);
} else {
- xm_string_lastof_str(lua, cstr, (tb_size_t)nstr, csubstr, nsubstr);
+ lua_pushnil(lua);
}
return 1;
}
diff --git a/core/src/xmake/utf8/lastof.c b/core/src/xmake/utf8/lastof.c
index 8e22b16ba..165da3b69 100644
--- a/core/src/xmake/utf8/lastof.c
+++ b/core/src/xmake/utf8/lastof.c
@@ -36,42 +36,30 @@ tb_int_t xm_utf8_lastof(lua_State *lua) {
size_t sublen;
tb_char_t const* sub = luaL_checklstring(lua, 2, &sublen);
tb_int_t plain = lua_toboolean(lua, 3);
+ tb_long_t byte_pos = 0;
if (plain) {
- tb_long_t char_pos = xm_utf8_lastof_impl(s, len, sub, sublen);
- if (char_pos > 0) {
- lua_pushinteger(lua, char_pos);
- } else {
- lua_pushnil(lua);
- }
- return 1;
+ byte_pos = xm_utf8_lastof_impl(s, len, sub, sublen);
} else {
lua_getglobal(lua, "string");
lua_getfield(lua, -1, "lastof");
lua_pushvalue(lua, 1); // s
lua_pushvalue(lua, 2); // pattern
lua_pushboolean(lua, 0); // plain = false
-
lua_call(lua, 3, 1);
-
- // Stack: [args, string_table, result]
- if (lua_isnil(lua, -1)) {
- return 1;
+ if (!lua_isnil(lua, -1)) {
+ byte_pos = (tb_long_t)lua_tointeger(lua, -1);
}
+ }
- lua_Integer byte_pos = lua_tointeger(lua, -1);
- if (byte_pos > 0) {
- tb_long_t count = xm_utf8_len_impl(s, len, 1, byte_pos - 1, tb_true, tb_null);
- if (count >= 0) {
- if (xm_utf8_iscont(s[byte_pos - 1])) {
- lua_pushinteger(lua, count);
- } else {
- lua_pushinteger(lua, count + 1);
- }
- return 1;
- }
+ if (byte_pos > 0) {
+ tb_long_t char_pos = xm_utf8_charpos(s, len, byte_pos);
+ if (char_pos > 0) {
+ lua_pushinteger(lua, char_pos);
+ return 1;
}
- lua_pushnil(lua);
- return 1;
}
+
+ lua_pushnil(lua);
+ return 1;
}
diff --git a/core/src/xmake/utf8/utf8.c b/core/src/xmake/utf8/utf8.c
index 3b23532c5..3748e0975 100644
--- a/core/src/xmake/utf8/utf8.c
+++ b/core/src/xmake/utf8/utf8.c
@@ -105,6 +105,27 @@ tb_size_t xm_utf8_encode(tb_char_t* s, xm_utf8_int_t val) {
return 0;
}
+tb_long_t xm_utf8_charpos(tb_char_t const* s, tb_size_t len, tb_long_t byte_pos) {
+ if (byte_pos <= 0) return 0;
+ if (byte_pos > len + 1) byte_pos = len + 1;
+
+ // adjust byte_pos to the start of the character
+ //
+ // performance:
+ // 0(1) complexity, because utf8 sequence is max 4 bytes
+ while (byte_pos > 1 && xm_utf8_iscont(s[byte_pos - 1])) {
+ byte_pos--;
+ }
+
+ // get character position
+ tb_long_t count = xm_utf8_len_impl(s, len, 1, byte_pos - 1, tb_true, tb_null);
+ return count >= 0? count + 1 : -1;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation interfaces
+ */
+
tb_long_t xm_utf8_len_impl(tb_char_t const* s, tb_size_t len, tb_long_t posi, tb_long_t posj, tb_bool_t strict, tb_size_t* errpos) {
tb_assert_and_check_return_val(s, -1);
@@ -313,3 +334,4 @@ tb_char_t const* xm_utf8_sub_impl(tb_char_t const* s, tb_size_t len, tb_long_t i
*psublen = end_byte - start_byte;
return s + start_byte - 1;
}
+
diff --git a/core/src/xmake/utf8/utf8.h b/core/src/xmake/utf8/utf8.h
index f50b21e44..f1d374af3 100644
--- a/core/src/xmake/utf8/utf8.h
+++ b/core/src/xmake/utf8/utf8.h
@@ -41,7 +41,11 @@ static __tb_inline__ tb_long_t xm_utf8_posrelat(tb_long_t pos, tb_size_t len) {
tb_char_t const* xm_utf8_decode(tb_char_t const* s, xm_utf8_int_t* val, tb_bool_t strict);
tb_size_t xm_utf8_encode(tb_char_t* s, xm_utf8_int_t val);
+tb_long_t xm_utf8_charpos(tb_char_t const* s, tb_size_t len, tb_long_t byte_pos);
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation interfaces
+ */
tb_long_t xm_utf8_len_impl(tb_char_t const* s, tb_size_t len, tb_long_t posi, tb_long_t posj, tb_bool_t strict, tb_size_t* errpos);
tb_long_t xm_utf8_offset_impl(tb_char_t const* s, tb_size_t len, tb_long_t n, tb_long_t posi);
tb_bool_t xm_utf8_codepoint_impl(tb_char_t const* s, tb_size_t len, tb_long_t posi, tb_long_t posj, tb_bool_t strict, xm_utf8_codepoint_func_t func, tb_cpointer_t udata);