Skip to content

Instantly share code, notes, and snippets.

@jhseodev
Forked from jarcode-foss/luaF.c
Last active March 11, 2021 23:57
Show Gist options
  • Select an option

  • Save jhseodev/dbcb1eb2d5d88e66044928b68f1690dc to your computer and use it in GitHub Desktop.

Select an option

Save jhseodev/dbcb1eb2d5d88e66044928b68f1690dc to your computer and use it in GitHub Desktop.

Revisions

  1. jhseodev revised this gist Mar 11, 2021. 1 changed file with 26 additions and 6 deletions.
    32 changes: 26 additions & 6 deletions luaF.c
    Original file line number Diff line number Diff line change
    @@ -6,6 +6,20 @@
    // a table construct
    //
    // this avoids extra memory bloat and will keep the resulting strings on the stack
    //
    // Build:
    // gcc -shared -fpic -O -I/usr/include/luajit-2.0 luaF.c -o luaF.so
    //
    // Test Script:
    // local split_test = require("luaF_split")
    // local first, second = split("hello; world", ";")
    //
    // Run:
    // luajit test_script.lua

    #include <string.h>
    #include <lua.h>

    static int luaF_split(lua_State* state) {
    if (lua_isstring(state, 1) && lua_isstring(state, 2)) {
    size_t len, dlen;
    @@ -24,11 +38,11 @@ static int luaF_split(lua_State* state) {
    else d = 0;
    }
    if (d == dlen) { // delimeter matched section
    size_t slen = (i - dlen) - t; // length of section
    size_t slen = i - t; // length of section
    if (slen) {
    char section[slen];
    strncpy(&section, str + t, slen);
    lua_pushlstring(state, &section, slen);
    strncpy(section, str + t, slen);
    lua_pushlstring(state, section, slen);
    }
    else {
    char empty = '\0';
    @@ -41,8 +55,8 @@ static int luaF_split(lua_State* state) {
    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);
    strncpy(section, str + t, slen);
    lua_pushlstring(state, section, slen);
    section_amt++;
    }
    return section_amt;
    @@ -70,4 +84,10 @@ static int luaF_fsplit(lua_State* state) {
    }
    else luaL_error(state, "excepted `function` final argument");
    return 0;
    }
    }

    int luaopen_split(lua_State *L)
    {
    lua_register(L, "luaF_split", luaF_split);
    return 0;
    }
  2. @jarcode-foss jarcode-foss created this gist Dec 20, 2015.
    73 changes: 73 additions & 0 deletions luaF.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    // 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;
    }