From b09a20ebeab636fc6fa3fde4dcc1759908e51558 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Mon, 5 Jul 2021 15:44:37 -0400 Subject: [PATCH] Allow limited access to unsafepairs/unsafenext --- luprex/core/cpp/table.cpp | 36 ++++++++++++++++++++++++++++++------ luprex/core/cpp/table.hpp | 9 ++++++--- luprex/core/lua/inspect.lua | 2 +- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/luprex/core/cpp/table.cpp b/luprex/core/cpp/table.cpp index 2703c3ce..eafc72ef 100644 --- a/luprex/core/cpp/table.cpp +++ b/luprex/core/cpp/table.cpp @@ -313,7 +313,7 @@ static void auxsort (lua_State *L, int tab, int l, int u) { } /* repeat the routine for the larger one */ } -int table_sortedpairs(lua_State *L, bool *unsortable) { +int table_getpairs(lua_State *L, bool sort, bool *unsortable) { lua_checkstack(L, 40); LuaArg tab; LuaVar key, value; @@ -328,7 +328,10 @@ int table_sortedpairs(lua_State *L, bool *unsortable) { lua_pushnil(L); int total = 0; while (lua_next(L, tab.index()) != 0) { - total += 1; + int ktype = lua_type(L, -2); + if (ktype == LUA_TNUMBER || ktype == LUA_TSTRING || ktype == LUA_TBOOLEAN) { + total += 1; + } lua_pop(L, 1); } // Create the table, store the initial 1. @@ -350,7 +353,9 @@ int table_sortedpairs(lua_State *L, bool *unsortable) { lua_pop(L, 1); } } - auxsort(L, pairs.index(), 1, total); + if (sort) { + auxsort(L, pairs.index(), 1, total); + } return LS.result(); } @@ -362,7 +367,7 @@ int table_sortedpairs(lua_State *L, bool *unsortable) { // ///////////////////////////////////////////////////////////// -static int nextsortedpair(lua_State *L) { +LuaDefine(table_nextpair, "c") { if (lua_gettop(L) < 2) { luaL_error(L, "Not enough arguments to nextpair"); } @@ -387,18 +392,37 @@ static int nextsortedpair(lua_State *L) { // ///////////////////////////////////////////////////////////// +LuaDefine(table_unsafenext, "c") { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + +LuaDefine(table_unsafepairs, "c") { + luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */ + lua_pushcfunction(L, table_unsafenext); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnil(L); + return 3; +} + LuaDefine(table_pairs, "f") { LuaArg tab; LuaRet closure, rtab, key; LuaStack LS(L, tab, closure, rtab, key); lua_pushvalue(L, tab.index()); bool unsortable; - table_sortedpairs(L, &unsortable); + table_getpairs(L, true, &unsortable); if (unsortable) { luaL_error(L, "Cannot iterate over a table with unsortable keys"); } lua_replace(L, rtab.index()); - LS.set(closure, nextsortedpair); + LS.set(closure, table_nextpair); LS.set(key, LuaNil); return LS.result(); } diff --git a/luprex/core/cpp/table.hpp b/luprex/core/cpp/table.hpp index f5a23b7e..daf12a4d 100644 --- a/luprex/core/cpp/table.hpp +++ b/luprex/core/cpp/table.hpp @@ -78,10 +78,13 @@ int table_count(lua_State *L); // This is not exposed directly to lua, but it is used // in the new version of the 'pairs' iterator. // -// The boolean 'unsortable' is set to indicate whether -// or not the table contains unsortable values. +// The boolean 'sort' is used to control whether the pairs +// are to be sorted or not. // -int table_sortedpairs(lua_State *L, bool *unsortable); +// The boolean 'unsortable' returns a flag indicating +// whether or not unsortable items were omitted. +// +int table_getpairs(lua_State *L, bool sort, bool *unsortable); // table_clear // diff --git a/luprex/core/lua/inspect.lua b/luprex/core/lua/inspect.lua index 3c94fc3c..f65730fc 100644 --- a/luprex/core/lua/inspect.lua +++ b/luprex/core/lua/inspect.lua @@ -36,7 +36,7 @@ inspect.KEY = {} inspect.METATABLE = {} local function rawpairs(t) - return next, t, nil + return table.unsafepairs(t) end -- Apostrophizes the string if it has quotes, but not aphostrophes