#ifndef LUASTACK_HPP #define LUASTACK_HPP extern "C" { #include "lua.h" #include "lauxlib.h" #include "lualib.h" #include "luajit.h" } #include // LuaArgCheck // // This is a template that, when given a lua_CFunction that doesn't // verify the number of arguments on the stack, returns a new lua_CFunction // that *does* verify the number of arguments on the stack. // // In general, your lua_CFunctions should not verify the number of // arguments on the stack. Instead, they should assume that the stack // contains arbitrary stuff underneath the arguments. That makes your // lua_CFunctions callable from both C and Lua. But it is desirable to // check arguments (only when calling from lua), so it is useful to use // LuaArgCheck when turning a lua_CFunction into a lua closure. // template int LuaArgCheck(lua_State *L) { if (lua_gettop(L) != N) { lua_pushfstring(L, "expected %d arguments, got %d", N, lua_gettop(L)); lua_error(L); } FN(L); } // LuaSlot // // An LuaSlot contains a lua stack index. It is initialized by the // LuaStack and contains the same index until the LuaStack // is destroyed. You can convert an LuaSlot into a lua stack index // by simply coercing it to 'int'. // // There are three variants of LuaSlot that you can use: LuaArg (function // argument), LuaRet (function return value), and LuaVar (function local // variable). // class LuaSlot { protected: int index_; private: inline operator int() const { return index_; } public: LuaSlot(int n) { index_ = n; } LuaSlot() { index_ = 0; } int index() const { return index_; } friend class LuaStack; }; class LuaArg : public LuaSlot {}; class LuaRet : public LuaSlot {}; class LuaVar : public LuaSlot {}; extern LuaSlot LuaRegistry; extern LuaSlot LuaGlobals; class LuaUpvalue : public LuaSlot { public: LuaUpvalue(int n) { index_ = lua_upvalueindex(n); } }; class LuaStack { private: int narg_; int ngap_; int nvar_; int nret_; int argpos_; int gappos_; int varpos_; int retpos_; int rettop_; int finaltop_; lua_State *L_; template void count_slots(LuaArg &v, SS & ... stackslots) { count_slots(stackslots...); } template void count_slots(LuaVar &v, SS & ... stackslots) { count_slots(stackslots...); } template void count_slots(LuaRet &v, SS & ... stackslots) { count_slots(stackslots...); } template void count_slots() { count_slots_finalize(NARG, NVAR, NRET); } void count_slots_finalize(int narg, int nvar, int nret); template void assign_slots(int argp, int varp, int retp, LuaArg &v, SS & ... stackslots) { v.index_ = argp; assign_slots(argp + 1, varp, retp, stackslots...); } template void assign_slots(int argp, int varp, int retp, LuaVar &v, SS & ... stackslots) { v.index_ = varp; assign_slots(argp, varp+1, retp, stackslots...); } template void assign_slots(int argp, int varp, int retp, LuaRet &v, SS & ... stackslots) { v.index_ = retp; assign_slots(argp, varp, retp+1, stackslots...); } void assign_slots(int argp, int varp, int retp) {} void clear_frame(); public: template LuaStack(lua_State *L, SS & ... stackslots) { L_ = L; count_slots<0, 0, 0>(stackslots...); assign_slots(argpos_, varpos_, retpos_, stackslots...); clear_frame(); } ~LuaStack() {}; int result(); public: static void reg(lua_State *L, const char *classname, const char *funcname, lua_CFunction fn); void setnil(LuaSlot target) const; void setboolean(LuaSlot target, bool b) const; void setboolean(LuaSlot target, int b) const; void setstring(LuaSlot target, const char *str) const; void setstring(LuaSlot target, const std::string &str) const; void setnumber(LuaSlot target, double value) const; bool isboolean(LuaSlot s) { return lua_isboolean(L_, s); } bool iscfunction(LuaSlot s) { return lua_iscfunction(L_, s); } bool isfunction(LuaSlot s) { return lua_isfunction(L_, s); } bool islightuserdata(LuaSlot s) { return lua_islightuserdata(L_, s); } bool isnil(LuaSlot s) { return lua_isnil(L_, s); } bool isnumber(LuaSlot s) { return lua_isnumber(L_, s); } bool isstring(LuaSlot s) { return lua_isstring(L_, s); } bool istable(LuaSlot s) { return lua_istable(L_, s); } bool isthread(LuaSlot s) { return lua_isthread(L_, s); } bool isuserdata(LuaSlot s) { return lua_isuserdata(L_, s); } bool toboolean(LuaSlot s) { return lua_toboolean(L_, s); } int tointeger(LuaSlot s) { return lua_tointeger(L_, s); } double tonumber(LuaSlot s) { return lua_tonumber(L_, s); } std::string tostring(LuaSlot s); lua_State *tothread(LuaSlot s) { return lua_tothread(L_, s); } int checkint(LuaSlot s) { return luaL_checkint(L_, s); } long checklong(LuaSlot s) { return luaL_checklong(L_, s); } double checknumber(LuaSlot s) { return luaL_checknumber(L_, s); } std::string checkstring(LuaSlot s); void checktype(LuaSlot s, int t) { return luaL_checktype(L_, s, t); } void clearmetatable(LuaSlot tab) { lua_pushnil(L_); lua_setmetatable(L_, tab); } void setmetatable(LuaSlot tab, LuaSlot mt) { lua_pushvalue(L_, mt); lua_setmetatable(L_, tab); } void rawget(LuaSlot target, LuaSlot tab, LuaSlot key) const { lua_pushvalue(L_, key); lua_rawget(L_, tab); lua_replace(L_, target); } void rawset(LuaSlot tab, LuaSlot key, LuaSlot value) const { lua_pushvalue(L_, key); lua_pushvalue(L_, value); lua_rawset(L_, tab); } int next(LuaSlot tab, LuaSlot key, LuaSlot value) const { lua_pushvalue(L_, key); int ret = lua_next(L_, tab); if (ret != 0) { lua_replace(L_, value); lua_replace(L_, key); } return ret; } void setfield(LuaSlot tab, const char *field, LuaSlot value) const { lua_pushvalue(L_, value); lua_setfield(L_, tab, field); } void setfield(LuaSlot tab, const char *field, const char *value) const { lua_pushstring(L_, value); lua_setfield(L_, tab, field); } void setfield(LuaSlot tab, const char *field, const std::string &value) const { lua_pushlstring(L_, value.c_str(), value.size()); lua_setfield(L_, tab, field); } void getfield(LuaSlot target, LuaSlot tab, const char *field) const { lua_getfield(L_, tab, field); lua_replace(L_, target); } void newtable(LuaSlot target) const { lua_newtable(L_); lua_replace(L_, target); } void checknometa(LuaSlot index) const { if (lua_istable(L_, index)) { if (!lua_getmetatable(L_, index)) { return; } } luaL_error(L_, "expected simple table with no metatable"); } }; #endif // LUASTACK_HPP