summaryrefslogtreecommitdiff
path: root/core/src/xmake/string/split.c
diff options
context:
space:
mode:
authorruki <[email protected]>2020-03-01 22:48:48 +0800
committerruki <[email protected]>2020-03-01 22:48:48 +0800
commit2b41fac5b92bc0e5e3c4a848dfd7d9a1435fd20f (patch)
tree58dabccfd6158af8a83d19f56517c40c415f5405 /core/src/xmake/string/split.c
parentfc36d8022fed422d34498bc111cd69bff5b08c60 (diff)
improve string.split
Diffstat (limited to 'core/src/xmake/string/split.c')
-rw-r--r--core/src/xmake/string/split.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/core/src/xmake/string/split.c b/core/src/xmake/string/split.c
new file mode 100644
index 000000000..7954caab3
--- /dev/null
+++ b/core/src/xmake/string/split.c
@@ -0,0 +1,132 @@
+/*!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-2020, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file split.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "string_split"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private implementation
+ */
+static tb_void_t xm_string_split_str(lua_State* lua, tb_char_t const* cstr, tb_size_t nstr, tb_char_t const* cdls, tb_size_t ndls, tb_bool_t strict, tb_int_t limit)
+{
+ tb_int_t num = 0;
+ tb_char_t const* end = cstr + nstr;
+ tb_char_t const* pos = tb_strstr(cstr, cdls); // faster than tb_strnstr()
+ while (pos && pos < end)
+ {
+ if (pos > cstr || strict)
+ {
+ if (limit > 0 && num + 1 >= limit)
+ break;
+
+ lua_pushlstring(lua, cstr, pos - cstr);
+ lua_rawseti(lua, -2, ++num);
+ }
+
+ cstr = pos + ndls;
+ pos = tb_strstr(cstr, cdls);
+ }
+ if (cstr < end)
+ {
+ lua_pushlstring(lua, cstr, end - cstr);
+ lua_rawseti(lua, -2, ++num);
+ }
+ else if (strict && (limit < 0 || num < limit) && cstr == end)
+ {
+ lua_pushliteral(lua, "");
+ lua_rawseti(lua, -2, ++num);
+ }
+}
+static tb_void_t xm_string_split_chr(lua_State* lua, tb_char_t const* cstr, tb_size_t nstr, tb_char_t ch, tb_bool_t strict, tb_int_t limit)
+{
+ tb_int_t num = 0;
+ tb_char_t const* end = cstr + nstr;
+ tb_char_t const* pos = tb_strchr(cstr, ch); // faster than tb_strnchr()
+ while (pos && pos < end)
+ {
+ if (pos > cstr || strict)
+ {
+ if (limit > 0 && num + 1 >= limit)
+ break;
+
+ lua_pushlstring(lua, cstr, pos - cstr);
+ lua_rawseti(lua, -2, ++num);
+ }
+
+ cstr = pos + 1;
+ pos = tb_strchr(cstr, ch);
+ }
+ if (cstr < end)
+ {
+ lua_pushlstring(lua, cstr, end - cstr);
+ lua_rawseti(lua, -2, ++num);
+ }
+ else if (strict && (limit < 0 || num < limit) && cstr == end)
+ {
+ lua_pushliteral(lua, "");
+ lua_rawseti(lua, -2, ++num);
+ }
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+/* split string (only support plain text)
+ *
+ * @param str the string
+ * @param delimiter the delimiter
+ * @param strict is strict?
+ * @param limit the limit count
+ */
+tb_int_t xm_string_split(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // get string
+ size_t nstr = 0;
+ tb_char_t const* cstr = luaL_checklstring(lua, 1, &nstr);
+
+ // get delimiter
+ size_t ndls = 0;
+ tb_char_t const* cdls = luaL_checklstring(lua, 2, &ndls);
+
+ // is strict?
+ tb_bool_t const strict = (tb_bool_t)lua_toboolean(lua, 3);
+
+ // get limit count
+ tb_int_t const limit = (tb_int_t)luaL_optinteger(lua, 4, -1);
+
+ // split it
+ lua_newtable(lua);
+ if (ndls == 1) xm_string_split_chr(lua, cstr, (tb_size_t)nstr, cdls[0], strict, limit);
+ else xm_string_split_str(lua, cstr, (tb_size_t)nstr, cdls, ndls, strict, limit);
+ return 1;
+}