Lots of work on LuaStack
This commit is contained in:
264
luprex/syscpp/luastack.hpp
Normal file
264
luprex/syscpp/luastack.hpp
Normal file
@@ -0,0 +1,264 @@
|
||||
|
||||
|
||||
#ifndef LUASTACK_HPP
|
||||
#define LUASTACK_HPP
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "luajit.h"
|
||||
}
|
||||
|
||||
#include <string>
|
||||
|
||||
// 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 N, lua_CFunction FN>
|
||||
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<int NARG, int NVAR, int NRET, class... SS>
|
||||
void count_slots(LuaArg &v, SS & ... stackslots)
|
||||
{
|
||||
count_slots<NARG+1, NRET, NVAR>(stackslots...);
|
||||
}
|
||||
|
||||
template<int NARG, int NVAR, int NRET, class... SS>
|
||||
void count_slots(LuaVar &v, SS & ... stackslots)
|
||||
{
|
||||
count_slots<NARG, NVAR+1, NRET>(stackslots...);
|
||||
}
|
||||
template<int NARG, int NVAR, int NRET, class... SS>
|
||||
void count_slots(LuaRet &v, SS & ... stackslots)
|
||||
{
|
||||
count_slots<NARG, NVAR, NRET+1>(stackslots...);
|
||||
}
|
||||
|
||||
template<int NARG, int NVAR, int NRET>
|
||||
void count_slots() {
|
||||
count_slots_finalize(NARG, NVAR, NRET);
|
||||
}
|
||||
|
||||
void count_slots_finalize(int narg, int nvar, int nret);
|
||||
|
||||
template<class... SS>
|
||||
void assign_slots(int argp, int varp, int retp, LuaArg &v, SS & ... stackslots) {
|
||||
v.index_ = argp;
|
||||
assign_slots(argp + 1, varp, retp, stackslots...);
|
||||
}
|
||||
|
||||
template<class... SS>
|
||||
void assign_slots(int argp, int varp, int retp, LuaVar &v, SS & ... stackslots) {
|
||||
v.index_ = varp;
|
||||
assign_slots(argp, varp+1, retp, stackslots...);
|
||||
}
|
||||
|
||||
template<class... SS>
|
||||
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<class... SS>
|
||||
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
|
||||
Reference in New Issue
Block a user