summaryrefslogtreecommitdiff
path: root/core/src/xmake/utf8/find.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/xmake/utf8/find.c')
-rw-r--r--core/src/xmake/utf8/find.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/core/src/xmake/utf8/find.c b/core/src/xmake/utf8/find.c
new file mode 100644
index 000000000..f2268f9b4
--- /dev/null
+++ b/core/src/xmake/utf8/find.c
@@ -0,0 +1,134 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015-present, Xmake Open Source Community.
+ *
+ * @author ruki
+ * @file find.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "utf8.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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) {
+ tb_long_t char_end = 0;
+ tb_long_t char_start = xm_utf8_find_impl(s, len, sub, sublen, (tb_long_t)init, &char_end);
+ if (char_start > 0) {
+ lua_pushinteger(lua, char_start);
+ lua_pushinteger(lua, char_end);
+ return 2;
+ }
+ lua_pushnil(lua);
+ return 1;
+}
+
+static tb_int_t xm_utf8_find_impl_pattern(lua_State* lua, tb_char_t const* s, size_t len, lua_Integer init) {
+ int base = lua_gettop(lua);
+ tb_long_t byte_init = 1;
+ if (init > 0) {
+ if (init > 1) {
+ byte_init = xm_utf8_offset_impl(s, len, (tb_long_t)init, 1);
+ if (byte_init <= 0) {
+ lua_pushnil(lua);
+ return 1;
+ }
+ }
+ } else if (init < 0) {
+ byte_init = xm_utf8_offset_impl(s, len, (tb_long_t)init, len + 1);
+ if (byte_init <= 0) {
+ lua_pushnil(lua);
+ return 1;
+ }
+ }
+
+ lua_getglobal(lua, "string");
+ lua_getfield(lua, -1, "find");
+ lua_pushvalue(lua, 1); // s
+ lua_pushvalue(lua, 2); // pattern
+ lua_pushinteger(lua, byte_init); // init (byte)
+ lua_pushboolean(lua, 0); // plain
+
+ lua_call(lua, 4, LUA_MULTRET);
+
+ // Stack: [args, string_table, results...]
+ int nres = lua_gettop(lua) - (base + 1);
+ if (nres <= 0 || lua_isnil(lua, base + 2)) {
+ lua_pushnil(lua);
+ lua_remove(lua, base + 1);
+ return 1;
+ }
+
+ lua_Integer b_start = lua_tointeger(lua, base + 2);
+ lua_Integer b_end = lua_tointeger(lua, base + 3);
+
+ tb_long_t char_start = 1;
+ if (b_start > 1) {
+ tb_long_t count = xm_utf8_len_impl(s, len, 1, (tb_long_t)b_start - 1, tb_true, tb_null);
+ if (count < 0) {
+ lua_pushnil(lua);
+ lua_remove(lua, base + 1);
+ return 1;
+ }
+ char_start = count + 1;
+ }
+
+ tb_long_t match_char_len = 0;
+ if (b_end >= b_start) {
+ match_char_len = xm_utf8_len_impl(s, len, (tb_long_t)b_start, (tb_long_t)b_end, tb_true, tb_null);
+ if (match_char_len < 0) {
+ lua_pushnil(lua);
+ lua_remove(lua, base + 1);
+ return 1;
+ }
+ }
+
+ lua_pushinteger(lua, char_start);
+ lua_replace(lua, base + 2);
+ lua_pushinteger(lua, char_start + match_char_len - 1);
+ lua_replace(lua, base + 3);
+
+ lua_remove(lua, base + 1);
+
+ return nres;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+/* utf8.find(s, target [, init [, plain]])
+ */
+tb_int_t xm_utf8_find(lua_State *lua) {
+ tb_assert_and_check_return_val(lua, 0);
+
+ 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);
+ lua_Integer init = luaL_optinteger(lua, 3, 1);
+ tb_int_t plain = lua_toboolean(lua, 4);
+
+ if (plain) {
+ return xm_utf8_find_impl_plain(lua, s, len, sub, sublen, init);
+ } else {
+ return xm_utf8_find_impl_pattern(lua, s, len, init);
+ }
+}