summaryrefslogtreecommitdiff
path: root/core/src/xmake/utf8
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/xmake/utf8
parent91843ffb82564d29ce9a9e386f2c9292620a5ba9 (diff)
improve lastof
Diffstat (limited to 'core/src/xmake/utf8')
-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
3 files changed, 39 insertions, 25 deletions
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);