diff options
| author | ruki <[email protected]> | 2026-01-21 00:32:48 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2026-01-21 00:32:48 +0800 |
| commit | 443fc30ae713b14623ac20bd5f1e8fdb12740783 (patch) | |
| tree | 3ec726af7f2c4452726bd825fa240341ad01fb0a /core/src/xmake/utf8 | |
| parent | 91843ffb82564d29ce9a9e386f2c9292620a5ba9 (diff) | |
improve lastof
Diffstat (limited to 'core/src/xmake/utf8')
| -rw-r--r-- | core/src/xmake/utf8/lastof.c | 38 | ||||
| -rw-r--r-- | core/src/xmake/utf8/utf8.c | 22 | ||||
| -rw-r--r-- | core/src/xmake/utf8/utf8.h | 4 |
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); |
