summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-01-21 00:00:00 +0800
committerruki <[email protected]>2026-01-21 00:00:00 +0800
commit91843ffb82564d29ce9a9e386f2c9292620a5ba9 (patch)
treee3b81ebb411c9f9ce6ae2b3357ccc6ae2363f334
parent6eade15143027afad000a48c941f1e9168104a54 (diff)
improve utf8.lastof
-rw-r--r--core/src/xmake/utf8/find.c6
-rw-r--r--core/src/xmake/utf8/lastof.c54
-rw-r--r--core/src/xmake/utf8/utf8.c23
-rw-r--r--core/src/xmake/utf8/utf8.h1
-rw-r--r--tests/modules/utf8/test.lua9
-rw-r--r--xmake/core/base/utf8.lua4
6 files changed, 73 insertions, 24 deletions
diff --git a/core/src/xmake/utf8/find.c b/core/src/xmake/utf8/find.c
index 8f8a5a97f..cc57f1e69 100644
--- a/core/src/xmake/utf8/find.c
+++ b/core/src/xmake/utf8/find.c
@@ -25,7 +25,7 @@
#include "utf8.h"
/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
+ * private implementation
*/
static tb_int_t xm_utf8_find_impl_plain(lua_State* lua, tb_char_t const* s, size_t len, tb_char_t const* sub, size_t sublen, lua_Integer init) {
@@ -110,6 +110,10 @@ static tb_int_t xm_utf8_find_impl_pattern(lua_State* lua, tb_char_t const* s, si
return nres;
}
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
/* utf8.find(s, target [, init [, plain]])
*/
tb_int_t xm_utf8_find(lua_State *lua) {
diff --git a/core/src/xmake/utf8/lastof.c b/core/src/xmake/utf8/lastof.c
index 8c5ec7dd3..8e22b16ba 100644
--- a/core/src/xmake/utf8/lastof.c
+++ b/core/src/xmake/utf8/lastof.c
@@ -28,38 +28,50 @@
* implementation
*/
-/* utf8.lastof(s, substr)
+/* utf8.lastof(s, pattern, plain)
*/
tb_int_t xm_utf8_lastof(lua_State *lua) {
size_t len;
tb_char_t const* s = luaL_checklstring(lua, 1, &len);
size_t sublen;
tb_char_t const* sub = luaL_checklstring(lua, 2, &sublen);
+ tb_int_t plain = lua_toboolean(lua, 3);
- if (sublen == 0) {
- lua_pushnil(lua);
+ 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;
- }
+ } 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
- tb_char_t const* p = s;
- tb_char_t const* last = tb_null;
-
- while (1) {
- p = tb_strstr(p, sub);
- if (!p) break;
- last = p;
- p += 1;
- }
+ lua_call(lua, 3, 1);
- if (last) {
- tb_long_t count = xm_utf8_len_impl(s, len, 1, last - s, tb_true, tb_null);
- if (count < 0) {
- lua_pushnil(lua);
- return 1;
+ // Stack: [args, string_table, result]
+ if (lua_isnil(lua, -1)) {
+ return 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;
+ }
}
- lua_pushinteger(lua, count + 1);
- } else {
lua_pushnil(lua);
+ return 1;
}
- return 1;
}
diff --git a/core/src/xmake/utf8/utf8.c b/core/src/xmake/utf8/utf8.c
index 3b54a0f37..3b23532c5 100644
--- a/core/src/xmake/utf8/utf8.c
+++ b/core/src/xmake/utf8/utf8.c
@@ -239,6 +239,29 @@ tb_long_t xm_utf8_find_impl(tb_char_t const* s, tb_size_t len, tb_char_t const*
return char_start;
}
+tb_long_t xm_utf8_lastof_impl(tb_char_t const* s, tb_size_t len, tb_char_t const* sub, tb_size_t sublen) {
+ tb_assert_and_check_return_val(s && sub, 0);
+
+ if (sublen == 0) return 0;
+
+ tb_char_t const* p = s;
+ tb_char_t const* last = tb_null;
+
+ while (1) {
+ p = tb_strstr(p, sub);
+ if (!p) break;
+ last = p;
+ p += 1;
+ }
+
+ if (last) {
+ tb_long_t count = xm_utf8_len_impl(s, len, 1, last - s, tb_true, tb_null);
+ if (count < 0) return 0;
+ return count + 1;
+ }
+ return 0;
+}
+
tb_char_t const* xm_utf8_sub_impl(tb_char_t const* s, tb_size_t len, tb_long_t i, tb_long_t j, tb_size_t* psublen) {
tb_assert_and_check_return_val(s && psublen, tb_null);
*psublen = 0;
diff --git a/core/src/xmake/utf8/utf8.h b/core/src/xmake/utf8/utf8.h
index 8a61afe10..f50b21e44 100644
--- a/core/src/xmake/utf8/utf8.h
+++ b/core/src/xmake/utf8/utf8.h
@@ -46,6 +46,7 @@ tb_long_t xm_utf8_len_impl(tb_char_t const* s, tb_size_t len, tb_long_
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);
tb_long_t xm_utf8_find_impl(tb_char_t const* s, tb_size_t len, tb_char_t const* sub, tb_size_t sublen, tb_long_t init, tb_long_t* pchar_end);
+tb_long_t xm_utf8_lastof_impl(tb_char_t const* s, tb_size_t len, tb_char_t const* sub, tb_size_t sublen);
tb_char_t const* xm_utf8_sub_impl(tb_char_t const* s, tb_size_t len, tb_long_t i, tb_long_t j, tb_size_t* psublen);
#endif
diff --git a/tests/modules/utf8/test.lua b/tests/modules/utf8/test.lua
index 51b21d1c3..af0c98997 100644
--- a/tests/modules/utf8/test.lua
+++ b/tests/modules/utf8/test.lua
@@ -105,6 +105,15 @@ function test_lastof(t)
t:are_equal(utf8.lastof("A你好A", "好"), 3)
t:are_equal(utf8.lastof("ABC", "D"), nil)
+
+ -- plain
+ t:are_equal(utf8.lastof("ABC", "A", true), 1)
+ t:are_equal(utf8.lastof("ABC", "B", true), 2)
+ t:are_equal(utf8.lastof("ABC", ".", true), nil)
+
+ -- pattern
+ t:are_equal(utf8.lastof("ABC", "."), 3)
+ t:are_equal(utf8.lastof("你好", "."), 2)
end
function test_find(t)
diff --git a/xmake/core/base/utf8.lua b/xmake/core/base/utf8.lua
index 2878404fb..dfcfdfbf0 100644
--- a/xmake/core/base/utf8.lua
+++ b/xmake/core/base/utf8.lua
@@ -30,8 +30,8 @@ local utf8 = utf8 or {}
-- @interface utf8.offset(s, n [, i])
-- @interface utf8.codes(s [, lax])
-- @interface utf8.sub(s, i [, j])
--- @interface utf8.lastof(s, substr)
--- @interface utf8.find(s, target [, init])
+-- @interface utf8.lastof(s, pattern [, plain])
+-- @interface utf8.find(s, pattern [, init [, plain]])
--
-- the char pattern