diff options
Diffstat (limited to 'lib/supple/capi.c')
-rw-r--r-- | lib/supple/capi.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/supple/capi.c b/lib/supple/capi.c index 125a415..38c4f27 100644 --- a/lib/supple/capi.c +++ b/lib/supple/capi.c @@ -349,6 +349,80 @@ supple_capi_raw_getmm(lua_State *L) return 1; } +static int +supple_capi_next(lua_State *L) +{ + int type; + + lua_settop(L, 2); + + type = lua_type(L, 1); + if (type == LUA_TTABLE) { + /* It is a table, so do the equiv of luaB_next */ + if (lua_next(L, 1)) + /* return the k/v pair we got */ + return 2; + /* didn't get a k/v pair, so push a nil key and return */ + lua_pushnil(L); + return 1; + } else { + /* Do we have a metatable? */ + if (lua_getmetatable(L, 1)) { + /* We do, do we have a __next entry? */ + lua_getfield(L, -1, "__next"); + if (!lua_isnil(L, -1)) { + /* we do, so let's call that instead */ + lua_insert(L, 1); + lua_settop(L, 3); + lua_call(L, 2, LUA_MULTRET); + return lua_gettop(L); + } + } + } + /* Fell out of the ladders so return an error */ + return luaL_error(L, "Expected table (or iterable) as argument 1"); +} + +static int +supple_capi_ipairs_iterator(lua_State *L) +{ + /* Obj Int -> (NewInt Value|nothing) */ + int i = luaL_checkint(L, 2) + 1; + lua_pushinteger(L, i); + if (lua_type(L, 1) == LUA_TTABLE) { + lua_rawgeti(L, 1, i); + } else { + lua_pushinteger(L, i); + lua_gettable(L, 1); /* Use this so __index is used */ + } + return lua_isnil(L, -1) ? 0 : 2; +} + +static int +supple_capi_ipairs(lua_State *L) +{ + /* Replacement ipairs which uses our iterator so that fetches + * cross the proxy boundary transparently if needed. + */ + /* We register this with the iterator as the first upvalue */ + lua_pushvalue(L, lua_upvalueindex(1)); /* iterator */ + lua_pushvalue(L, 1); /* state (table?) */ + lua_pushinteger(L, 0); /* initial value */ + return 3; +} + +static int +supple_capi_pairs(lua_State *L) +{ + /* Replacement pairs which uses our next function. It is + * provided as our upvalue + */ + lua_pushvalue(L, lua_upvalueindex(1)); + lua_pushvalue(L, 1); + lua_pushnil(L); + return 3; +} + static const struct luaL_Reg supple_capi_functions[] = { { "explain", supple_capi_explain }, @@ -357,6 +431,7 @@ supple_capi_functions[] = { { "rawtype", supple_capi_rawtype }, { "lockdown", supple_capi_lockdown }, { "raw_getmm", supple_capi_raw_getmm }, + { "next", supple_capi_next }, { NULL, NULL } }; @@ -368,5 +443,11 @@ luaopen_supple_capi(lua_State *L) lua_setfield(L, -2, "_API"); lua_pushnumber(L, CAPI_ABI); lua_setfield(L, -2, "_ABI"); + lua_pushcclosure(L, supple_capi_ipairs_iterator, 0); + lua_pushcclosure(L, supple_capi_ipairs, 1); + lua_setfield(L, -2, "ipairs"); + lua_pushcclosure(L, supple_capi_next, 0); + lua_pushcclosure(L, supple_capi_pairs, 1); + lua_setfield(L, -2, "pairs"); return 1; } |