Skip to content

Instantly share code, notes, and snippets.

@jarcode-foss
Created December 20, 2015 14:01
Show Gist options
  • Save jarcode-foss/afd86b57cfe0f65bad68 to your computer and use it in GitHub Desktop.
Save jarcode-foss/afd86b57cfe0f65bad68 to your computer and use it in GitHub Desktop.
fast split function for Lua
// 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(&section, str + t, slen);
lua_pushlstring(state, &section, 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(&section, str + t, slen);
lua_pushlstring(state, &section, 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;
}
@fslove
Copy link

fslove commented Mar 6, 2018

Thanks for your code.
but how can uses?
Can you sent a full .so code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment