From 66292a6a85cf22cae31520ea4d08c76f544e338a Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Tue, 21 Mar 2017 08:38:41 +0100 Subject: string.gsub tests --- src/lapi.js | 2 +- src/lauxlib.js | 4 +- src/ljstype.js | 10 +-- src/lstrlib.js | 6 +- tests/lstrlib.js | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 201 insertions(+), 10 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 6840ef9..5872545 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -542,7 +542,7 @@ const lua_toboolean = function(L, idx) { const lua_tolstring = function(L, idx) { let o = index2addr(L, idx); - if (!o.ttisstring() && !o.ttisnumber()) + if ((!o.ttisstring() && !o.ttisnumber())) return null; return o.ttisstring() ? o.jsstring() : `${o.value}`; diff --git a/src/lauxlib.js b/src/lauxlib.js index 879d081..ac7ab00 100644 --- a/src/lauxlib.js +++ b/src/lauxlib.js @@ -299,10 +299,12 @@ const luaL_tolstring = function(L, idx) { } else { switch(lapi.lua_type(L, idx)) { case CT.LUA_TNUMBER: - case CT.LUA_TSTRING: case CT.LUA_TBOOLEAN: lapi.lua_pushstring(L, `${lapi.index2addr(L, idx).value}`); break; + case CT.LUA_TSTRING: + lapi.lua_pushstring(L, lapi.index2addr(L, idx).jsstring()); + break; case CT.LUA_TNIL: lapi.lua_pushstring(L, `nil`); break; diff --git a/src/ljstype.js b/src/ljstype.js index ef4be1d..7de9d9a 100644 --- a/src/ljstype.js +++ b/src/ljstype.js @@ -3,23 +3,23 @@ const assert = require('assert'); const lisdigit = function(c) { - return /^\d$/.test(c.charAt(0)); + return typeof c === 'string' && /^\d$/.test(c.charAt(0)); }; const lisxdigit = function(c) { - return /^[0-9a-fA-F]$/.test(c.charAt(0)); + return typeof c === 'string' && /^[0-9a-fA-F]$/.test(c.charAt(0)); }; const lisspace = function(c) { - return /^\s$/.test(c.charAt(0)); + return typeof c === 'string' && /^\s$/.test(c.charAt(0)); }; const lislalpha = function(c) { - return /^[_a-zA-Z]$/.test(c.charAt(0)); + return typeof c === 'string' && /^[_a-zA-Z]$/.test(c.charAt(0)); }; const lislalnum = function(c) { - return /^[_a-zA-Z0-9]$/.test(c.charAt(0)); + return typeof c === 'string' && /^[_a-zA-Z0-9]$/.test(c.charAt(0)); }; module.exports.lisdigit = lisdigit; diff --git a/src/lstrlib.js b/src/lstrlib.js index dc3845b..3872cb2 100644 --- a/src/lstrlib.js +++ b/src/lstrlib.js @@ -176,7 +176,7 @@ const MAX_FORMAT = 32; const isalpha = e => /^[a-zA-Z]$/.test(e.charAt(0)); const isdigit = e => "0".charCodeAt(0) <= e && e <= "9".charCodeAt(0); const iscntrl = e => (0x00 <= e && e <= 0x1f) || e === 0x7f; -const isgraph = e => e.charCodeAt(0) > 32 && e.charCodeAt < 127; // TODO: Will only work for ASCII +const isgraph = e => e.charCodeAt(0) > 32 && e.charCodeAt(0) < 127; // TODO: Will only work for ASCII const islower = e => /^(?![A-Z]).*$/.test(e.charAt(0)); const isupper = e => /^(?![a-z]).*$/.test(e.charAt(0)); const isalnum = e => /^[a-zA-Z0-9]$/.test(e.charAt(0)); @@ -1269,7 +1269,7 @@ const add_s = function(ms, b, s, e) { lauxlib.luaL_addchar(b, news.charAt(i)); else { i++; /* skip ESC */ - if (!isdigit(news.charAt(i))) { + if (!isdigit(news.charCodeAt(i))) { if (news.charAt(i) !== sL_ESC) lauxlib.luaL_error(L, `invalid use of '${sL_ESC}' in replacement string`); lauxlib.luaL_addchar(b, news.charAt(i)); @@ -1277,7 +1277,7 @@ const add_s = function(ms, b, s, e) { lauxlib.luaL_addlstring(b, ms.src.slice(s), e - s); else { push_onecapture(ms, news.charCodeAt(i) - '1'.charCodeAt(0), s, e); - lauxlib.luaL_tostring(L, -1); + lauxlib.luaL_tolstring(L, -1); lapi.lua_remove(L, -2); /* remove original value */ lauxlib.luaL_addvalue(b); /* add capture to accumulated result */ } diff --git a/tests/lstrlib.js b/tests/lstrlib.js index ce77bdc..12df173 100644 --- a/tests/lstrlib.js +++ b/tests/lstrlib.js @@ -677,4 +677,193 @@ test('string.gmatch', function (t) { "Lua", "Correct element(s) on the stack" ); +}); + + +test('string.gsub', function (t) { + let luaCode = ` + return string.gsub("hello world", "(%w+)", "%1 %1") + `, L; + + t.plan(4); + + t.doesNotThrow(function () { + + L = lauxlib.luaL_newstate(); + + linit.luaL_openlibs(L); + + lauxlib.luaL_loadstring(L, luaCode); + + }, "Lua program loaded without error"); + + t.doesNotThrow(function () { + + lapi.lua_call(L, 0, -1); + + }, "Lua program ran without error"); + + t.strictEqual( + lapi.lua_tostring(L, -2), + "hello hello world world", + "Correct element(s) on the stack" + ); + + t.strictEqual( + lapi.lua_tointeger(L, -1), + 2, + "Correct element(s) on the stack" + ); +}); + + +test('string.gsub (number)', function (t) { + let luaCode = ` + return string.gsub("hello world", "%w+", "%0 %0", 1) + `, L; + + t.plan(4); + + t.doesNotThrow(function () { + + L = lauxlib.luaL_newstate(); + + linit.luaL_openlibs(L); + + lauxlib.luaL_loadstring(L, luaCode); + + }, "Lua program loaded without error"); + + t.doesNotThrow(function () { + + lapi.lua_call(L, 0, -1); + + }, "Lua program ran without error"); + + t.strictEqual( + lapi.lua_tostring(L, -2), + "hello hello world", + "Correct element(s) on the stack" + ); + + t.strictEqual( + lapi.lua_tointeger(L, -1), + 1, + "Correct element(s) on the stack" + ); +}); + + +test('string.gsub (pattern)', function (t) { + let luaCode = ` + return string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") + `, L; + + t.plan(4); + + t.doesNotThrow(function () { + + L = lauxlib.luaL_newstate(); + + linit.luaL_openlibs(L); + + lauxlib.luaL_loadstring(L, luaCode); + + }, "Lua program loaded without error"); + + t.doesNotThrow(function () { + + lapi.lua_call(L, 0, -1); + + }, "Lua program ran without error"); + + t.strictEqual( + lapi.lua_tostring(L, -2), + "world hello Lua from", + "Correct element(s) on the stack" + ); + + t.strictEqual( + lapi.lua_tointeger(L, -1), + 2, + "Correct element(s) on the stack" + ); +}); + + +test('string.gsub (function)', function (t) { + let luaCode = ` + return string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) + return load(s)() + end) + `, L; + + t.plan(4); + + t.doesNotThrow(function () { + + L = lauxlib.luaL_newstate(); + + linit.luaL_openlibs(L); + + lauxlib.luaL_loadstring(L, luaCode); + + }, "Lua program loaded without error"); + + t.doesNotThrow(function () { + + lapi.lua_call(L, 0, -1); + + }, "Lua program ran without error"); + + t.strictEqual( + lapi.lua_tostring(L, -2), + "4+5 = 9", + "Correct element(s) on the stack" + ); + + t.strictEqual( + lapi.lua_tointeger(L, -1), + 1, + "Correct element(s) on the stack" + ); +}); + + + +test('string.gsub (table)', function (t) { + let luaCode = ` + local t = {name="lua", version="5.3"} + return string.gsub("$name-$version.tar.gz", "%$(%w+)", t) + `, L; + + t.plan(4); + + t.doesNotThrow(function () { + + L = lauxlib.luaL_newstate(); + + linit.luaL_openlibs(L); + + lauxlib.luaL_loadstring(L, luaCode); + + }, "Lua program loaded without error"); + + t.doesNotThrow(function () { + + lapi.lua_call(L, 0, -1); + + }, "Lua program ran without error"); + + t.strictEqual( + lapi.lua_tostring(L, -2), + "lua-5.3.tar.gz", + "Correct element(s) on the stack" + ); + + t.strictEqual( + lapi.lua_tointeger(L, -1), + 2, + "Correct element(s) on the stack" + ); }); \ No newline at end of file -- cgit v1.2.3-70-g09d2