Created
December 20, 2015 14:01
-
-
Save jarcode-foss/afd86b57cfe0f65bad68 to your computer and use it in GitHub Desktop.
fast split function for Lua
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Faster split method, the only alternative within lua is using gsub, which | |
// is insanely slower. This function will actually return strings on the stack, | |
// so {str:split(d)} can be used to collect the return values in a table | |
// | |
// A more memory effecient use would be to use string.fsplit rather than using | |
// a table construct | |
// | |
// this avoids extra memory bloat and will keep the resulting strings on the stack | |
static int luaF_split(lua_State* state) { | |
if (lua_isstring(state, 1) && lua_isstring(state, 2)) { | |
size_t len, dlen; | |
char* str = lua_tolstring(state, 1, &len); | |
char* dstr = lua_tolstring(state, 2, &dlen); | |
if (!str || !dstr) return 0; | |
size_t i, t = 0, d = 0; // parse index, last found section index, and delimeter index, respectively | |
size_t section_amt = 0; | |
for (i = 0; i < len; i++) { | |
if (str[i] == dstr[d]) { // match characters, advance 'd' if a character matches | |
d++; | |
} | |
else { // if a comparison failed, reset 'd' idx | |
if (str[i] == *dstr) // if the failed character matches the first delimeter char, set d = 1 | |
d = 1; | |
else d = 0; | |
} | |
if (d == dlen) { // delimeter matched section | |
size_t slen = (i - dlen) - t; // length of section | |
if (slen) { | |
char section[slen]; | |
strncpy(§ion, str + t, slen); | |
lua_pushlstring(state, §ion, slen); | |
} | |
else { | |
char empty = '\0'; | |
lua_pushlstring(state, &empty, 0); | |
} | |
section_amt++; | |
t = i + 1; // move 't' to after the matched delimeter | |
} | |
} | |
if (t < len) { // if the 't' cursor isn't at the end of string, create one more section | |
size_t slen = len - t; // length of section | |
char section[slen]; | |
strncpy(§ion, str + t, slen); | |
lua_pushlstring(state, §ion, slen); | |
section_amt++; | |
} | |
return section_amt; | |
} | |
else luaL_error(state, "excepted `string` arguments"); | |
return 0; | |
} | |
// Splits a string, using a delimeter, and calls a function for each delimeter. | |
// This function can be used to iterate on a split string without ever creating | |
// table garbage | |
static int luaF_fsplit(lua_State* state) { | |
if (lua_isfunction(state, 3)) { | |
// remove string and delimeter | |
lua_remove(state, 1); | |
lua_remove(state, 1); | |
// call split function using the current stack | |
luaB_split(state); | |
// loop on every string result | |
while (lua_gettop(state) != 1) { | |
lua_pushvalue(state, 1); | |
luaB_swap(state, -1, -2); | |
lua_call(state, 1, 0); | |
} | |
} | |
else luaL_error(state, "excepted `function` final argument"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for your code.
but how can uses?
Can you sent a full .so code?