diff options
author | Benoit Giannangeli <benoit.giannangeli@boursorama.fr> | 2017-03-20 16:15:36 +0100 |
---|---|---|
committer | Benoit Giannangeli <benoit.giannangeli@boursorama.fr> | 2017-03-20 16:15:36 +0100 |
commit | 5f5ba74ace8a956ae48a9f0b182a157052c2546e (patch) | |
tree | 93381379f3711fd5ad67015d686dbfd518c0eef5 /src | |
parent | 645437b8e0846635f886520bb679a79ec1849c09 (diff) | |
download | fengari-5f5ba74ace8a956ae48a9f0b182a157052c2546e.tar.gz fengari-5f5ba74ace8a956ae48a9f0b182a157052c2546e.tar.bz2 fengari-5f5ba74ace8a956ae48a9f0b182a157052c2546e.zip |
string.gsub
Diffstat (limited to 'src')
-rw-r--r-- | src/lapi.js | 20 | ||||
-rw-r--r-- | src/lstrlib.js | 40 |
2 files changed, 60 insertions, 0 deletions
diff --git a/src/lapi.js b/src/lapi.js index a884a97..6840ef9 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -428,6 +428,14 @@ const lua_createtable = function(L, narray, nrec) { assert(L.top <= L.ci.top, "stack overflow"); }; +const lua_newuserdata = function(L, u) { + L.stack[L.top++] = new lobject.TValue(CT.LUA_TUSERDATA, u); + + assert(L.top <= L.ci.top, "stack overflow"); + + return L.stack[L.top - 1].value; +}; + const aux_upvalue = function(fi, n) { switch(fi.ttype()) { case CT.LUAT_TCCL: { /* C closure */ @@ -578,6 +586,16 @@ const lua_tonumber = function(L, idx) { return lvm.tonumber(index2addr(L, idx)); }; +const lua_touserdata = function(L, idx) { + let o = index2addr(L, idx); + switch (o.ttnov()) { + case CT.LUA_TUSERDATA: + case CT.LUA_TLIGHTUSERDATA: + return o.value; + default: return null; + } +}; + const lua_tothread = function(L, idx) { let o = index2addr(L, idx); return o.ttisthread() ? o.value : null; @@ -879,6 +897,7 @@ module.exports.lua_istable = lua_istable; module.exports.lua_len = lua_len; module.exports.lua_load = lua_load; module.exports.lua_newtable = lua_newtable; +module.exports.lua_newuserdata = lua_newuserdata; module.exports.lua_next = lua_next; module.exports.lua_pcall = lua_pcall; module.exports.lua_pcallk = lua_pcallk; @@ -924,6 +943,7 @@ module.exports.lua_tonumber = lua_tonumber; module.exports.lua_topointer = lua_topointer; module.exports.lua_tostring = lua_tostring; module.exports.lua_tothread = lua_tothread; +module.exports.lua_touserdata = lua_touserdata; module.exports.lua_type = lua_type; module.exports.lua_typename = lua_typename; module.exports.lua_version = lua_version; diff --git a/src/lstrlib.js b/src/lstrlib.js index cedb403..9caa3cc 100644 --- a/src/lstrlib.js +++ b/src/lstrlib.js @@ -1221,12 +1221,52 @@ const str_match = function(L) { return str_find_aux(L, 0); }; +/* state for 'gmatch' */ +class GMatchState { + constructor() { + this.src = NaN; /* current position */ + this.p = NaN; /* pattern */ + this.lastmatch = NaN; /* end of last match */ + this.ms = new MatchState(); /* match state */ + } +} + +const gmatch_aux = function(L) { + let gm = lapi.lua_touserdata(L, lua.lua_upvalueindex(3)); + gm.ms.L = L; + for (let src = 0; src < gm.ms.src_end; src++) { + reprepstate(gm.ms); + let e; + if ((e = match(gm.ms, src, gm.p)) !== null && e !== gm.lastmatch) { + gm.src = gm.lastmatch = e; + return push_captures(gm.ms, src, e); + } + } + return 0; /* not found */ +}; + +const str_gmatch = function(L) { + let s = lauxlib.luaL_checkstring(L, 1); + let p = lauxlib.luaL_checkstring(L, 2); + let ls = s.length; + let lp = p.length; + lapi.lua_settop(L, 2); /* keep them on closure to avoid being collected */ + let gm = lapi.lua_newuserdata(L, new GMatchState()); + prepstate(gm.ms, L, s, ls, p, lp); + gm.src = s; + gm.p = p; + gm.lastmatch = null; + lapi.lua_pushcclosure(L, gmatch_aux, 3); + return 1; +}; + const strlib = { "byte": str_byte, "char": str_char, "dump": str_dump, "find": str_find, "format": str_format, + "gmatch": str_gmatch, "len": str_len, "lower": str_lower, "match": str_match, |