* @brief Native string.split: splits on each literal occurrence of sep, keeping empty fields. */
| 186 | * @brief Native string.split: splits on each literal occurrence of sep, keeping empty fields. |
| 187 | */ |
| 188 | static int luaStringSplit(lua_State* L) |
| 189 | { |
| 190 | Q_ASSERT(L != nullptr); |
| 191 | |
| 192 | size_t slen = 0; |
| 193 | const char* s = luaL_checklstring(L, 1, &slen); |
| 194 | size_t seplen = 0; |
| 195 | const char* sep = luaL_optlstring(L, 2, "", &seplen); |
| 196 | Q_ASSERT(s != nullptr); |
| 197 | |
| 198 | lua_newtable(L); |
| 199 | |
| 200 | if (seplen == 0) { |
| 201 | lua_pushlstring(L, s, slen); |
| 202 | lua_rawseti(L, -2, 1); |
| 203 | return 1; |
| 204 | } |
| 205 | |
| 206 | int idx = 1; |
| 207 | size_t start = 0; |
| 208 | size_t i = 0; |
| 209 | // code-verify off (bounded walk: i advances by >= 1 each step until i + seplen > slen) |
| 210 | while (i + seplen <= slen) { |
| 211 | if (std::memcmp(s + i, sep, seplen) == 0) { |
| 212 | lua_pushlstring(L, s + start, i - start); |
| 213 | lua_rawseti(L, -2, idx++); |
| 214 | i += seplen; |
| 215 | start = i; |
| 216 | } else { |
| 217 | ++i; |
| 218 | } |
| 219 | } |
| 220 | // code-verify on |
| 221 | |
| 222 | lua_pushlstring(L, s + start, slen - start); |
| 223 | lua_rawseti(L, -2, idx); |
| 224 | return 1; |
| 225 | } |
| 226 | |
| 227 | /** |
| 228 | * @brief Loads the Lua compatibility shim and installs the native string.split into the state. |
nothing calls this directly
no test coverage detected