Files
pke/thirdparty/luaplus/Src/LuaPlus/LuaPlusCD.h
2026-02-12 11:46:06 +03:00

2401 lines
80 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// This source file is part of the LuaPlus source distribution and is Copyright
// 2001-2012 by Joshua C. Jensen (jjensen@workspacewhiz.com).
//
// The latest version may be obtained from http://luaplus.org/.
//
// The code presented in this file may be used in any environment it is
// acceptable to use Lua.
///////////////////////////////////////////////////////////////////////////////
#ifndef LUAPLUS__LUAPLUSCD_H
#define LUAPLUS__LUAPLUSCD_H
extern "C" {
#include "lua.h"
#include "lauxlib.h"
}
#include <stdlib.h>
#include <string.h>
// LuaPlus Call Dispatcher
namespace LPCD {
struct LuaLightUserdata {
LuaLightUserdata(const void* value) :
m_value(value) {
}
const void* m_value;
};
struct LuaUserdata {
LuaUserdata(const void* value) :
m_value(value) {
}
const void* m_value;
};
struct LuaNil {
};
template<typename T>
struct Type {
};
// bool types
template<> struct Type<bool> {
static inline void Push(lua_State* L, bool value) { lua_pushboolean(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TBOOLEAN; }
static inline bool Get(lua_State* L, int idx) { return lua_toboolean(L, idx) != 0; }
};
template<> struct Type<bool&> : public Type<bool> {};
template<> struct Type<const bool&> : public Type<bool> {};
// char types
template<> struct Type<char> {
static inline void Push(lua_State* L, char value) { lua_pushinteger(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline char Get(lua_State* L, int idx) { return static_cast<char>(lua_tonumber(L, idx)); }
};
template<> struct Type<char&> : public Type<char> {};
template<> struct Type<const char&> : public Type<char> {};
// unsigned char types
template<> struct Type<unsigned char> {
static inline void Push(lua_State* L, unsigned char value) { lua_pushinteger(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline unsigned char Get(lua_State* L, int idx) { return static_cast<unsigned char>(lua_tonumber(L, idx)); }
};
template<> struct Type<unsigned char&> : public Type<unsigned char> {};
template<> struct Type<const unsigned char&> : public Type<unsigned char> {};
// short types
template<> struct Type<short> {
static inline void Push(lua_State* L, short value) { lua_pushinteger(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline short Get(lua_State* L, int idx) { return static_cast<short>(lua_tonumber(L, idx)); }
};
template<> struct Type<short&> : public Type<short> {};
template<> struct Type<const short&> : public Type<short> {};
// unsigned short types
template<> struct Type<unsigned short> {
static inline void Push(lua_State* L, unsigned short value) { lua_pushinteger(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline unsigned short Get(lua_State* L, int idx) { return static_cast<unsigned short>(lua_tonumber(L, idx)); }
};
template<> struct Type<unsigned short&> : public Type<unsigned short> {};
template<> struct Type<const unsigned short&> : public Type<unsigned short> {};
// int types
template<> struct Type<int> {
static inline void Push(lua_State* L, int value) { lua_pushinteger(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline int Get(lua_State* L, int idx) { return static_cast<int>(lua_tonumber(L, idx)); }
};
template<> struct Type<int&> : public Type<int> {};
template<> struct Type<const int&> : public Type<int> {};
// unsigned int types
template<> struct Type<unsigned int> {
static inline void Push(lua_State* L, unsigned int value) { lua_pushinteger(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline unsigned int Get(lua_State* L, int idx) { return static_cast<unsigned int>(lua_tonumber(L, idx)); }
};
template<> struct Type<unsigned int&> : public Type<unsigned int> {};
template<> struct Type<const unsigned int&> : public Type<unsigned int> {};
// long types
template<> struct Type<long> {
static inline void Push(lua_State* L, long value) { lua_pushinteger(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline long Get(lua_State* L, int idx) { return static_cast<long>(lua_tonumber(L, idx)); }
};
template<> struct Type<long&> : public Type<long> {};
template<> struct Type<const long&> : public Type<long> {};
// unsigned long types
template<> struct Type<unsigned long> {
static inline void Push(lua_State* L, unsigned long value) { lua_pushinteger(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline unsigned long Get(lua_State* L, int idx) { return static_cast<unsigned long>(lua_tonumber(L, idx)); }
};
template<> struct Type<unsigned long&> : public Type<unsigned long> {};
template<> struct Type<const unsigned long&> : public Type<unsigned long> {};
#if defined(_WIN64)
// size_t types
template<> struct Type<size_t> {
static inline void Push(lua_State* L, size_t value) { lua_pushinteger(L, (lua_Integer)value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline size_t Get(lua_State* L, int idx) { return static_cast<size_t>(lua_tointeger(L, idx)); }
};
template<> struct Type<size_t&> : public Type<size_t> {};
template<> struct Type<const size_t&> : public Type<size_t> {};
#endif // _WIN64
// float types
template<> struct Type<float> {
static inline void Push(lua_State* L, float value) { lua_pushnumber(L, (lua_Number)value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline float Get(lua_State* L, int idx) { return static_cast<float>(lua_tonumber(L, idx)); }
};
template<> struct Type<float&> : public Type<float> {};
template<> struct Type<const float&> : public Type<float> {};
// double types
template<> struct Type<double> {
static inline void Push(lua_State* L, double value) { lua_pushnumber(L, (lua_Number)value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline double Get(lua_State* L, int idx) { return static_cast<double>(lua_tonumber(L, idx)); }
};
template<> struct Type<double&> : public Type<double> {};
template<> struct Type<const double&> : public Type<double> {};
// int types
template<> struct Type<lua_Integer> {
static inline void Push(lua_State* L, lua_Integer value) { lua_pushinteger(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; }
static inline int Get(lua_State* L, int idx) { return static_cast<int>(lua_tonumber(L, idx)); }
};
template<> struct Type<lua_Integer&> : public Type<lua_Integer> {};
template<> struct Type<const lua_Integer&> : public Type<lua_Integer> {};
// character pointer types
template<> struct Type<char*> {
static inline void Push(lua_State* L, const char* value) { lua_pushstring(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TSTRING; }
static inline const char* Get(lua_State* L, int idx) { return static_cast<const char*>(lua_tostring(L, idx)); }
};
template<> struct Type<const char*> : public Type<char*> {};
// character array types
template<int NUM_CHARS> struct Type<char [NUM_CHARS]> {
static inline void Push(lua_State* L, const char value[NUM_CHARS]) { lua_pushstring(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TSTRING; }
static inline const char* Get(lua_State* L, int idx) { return static_cast<const char*>(lua_tostring(L, idx)); }
};
template<int NUM_CHARS> struct Type<const char [NUM_CHARS]> {
static inline void Push(lua_State* L, const char value[NUM_CHARS]) { lua_pushstring(L, value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TSTRING; }
static inline const char* Get(lua_State* L, int idx) { return static_cast<const char*>(lua_tostring(L, idx)); }
};
// nil type
template<> struct Type<const LuaNil&> {
static inline void Push(lua_State* L, const LuaNil& value) { lua_pushnil(L); }
static inline bool Match(lua_State* L, int idx) { return true; }
static inline LuaNil Get(lua_State* L, int idx) { (void)L, (void)idx; return LuaNil(); }
};
// c function type
template<> struct Type<lua_CFunction> {
static inline void Push(lua_State* L, const lua_CFunction value) { lua_pushcclosure(L, value, 0); }
static inline bool Match(lua_State* L, int idx) { return true; }
static inline lua_CFunction Get(lua_State* L, int idx) { return static_cast<lua_CFunction>(lua_tocfunction(L, idx)); }
};
// void types
template<> struct Type<void*> {
static inline void Push(lua_State* L, const void* value) { lua_pushlightuserdata(L, (void*)value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TLIGHTUSERDATA; }
static inline void* Get(lua_State* L, int idx) { return static_cast<void*>(lua_touserdata(L, idx)); }
};
template<> struct Type<const void*> : public Type<void*> {};
// light userdata type
template<> struct Type<const LuaLightUserdata&> {
static inline void Push(lua_State* L, const LuaLightUserdata& value) { lua_pushlightuserdata(L, (void*)value.m_value); }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TLIGHTUSERDATA; }
static inline void* Get(lua_State* L, int idx) { return static_cast<void*>(lua_touserdata(L, idx)); }
};
// userdata types
template<> struct Type<LuaUserdata> {
static inline void Push(lua_State* L, LuaUserdata value) { *(void **)(lua_newuserdata(L, sizeof(void *))) = (void*)value.m_value; }
static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TUSERDATA; }
static inline void* Get(lua_State* L, int idx) { return static_cast<void*>(lua_touserdata(L, idx)); }
};
template<> struct Type<LuaUserdata&> : public Type<LuaUserdata> {};
template<> struct Type<const LuaUserdata&> : public Type<LuaUserdata> {};
inline void Push(lua_State* L, const char* value, int len) { lua_pushlstring(L, value, len); }
// inline void Get(TypeWrapper<void>, lua_State*, int)
// { }
// inline lua_State* Get(TypeWrapper<lua_State*>, lua_State* L, int /*idx*/)
// { return L; }
// inline bool Match(TypeWrapper<lua_State*>, lua_State* L, int idx)
// { return lua_type(L, idx) == LUA_TNONE; }
//////////////////////////////////////////////////////////////////////////
#define luaL_argassert(arg, _index_) if (!Type<P##arg>::Match(L, _index_)) \
luaL_argerror(L, _index_, "bad argument")
template<class RT>
struct ReturnSpecialization {
static int Call(RT (*func)(), lua_State* L, int /*index*/) {
RT ret = func();
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1>
static int Call(RT (*func)(P1), lua_State* L, int index) {
luaL_argassert(1, index + 0);
RT ret = func(
Type<P1>::Get(L, index + 0)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1, typename P2>
static int Call(RT (*func)(P1, P2), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
RT ret = func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1, typename P2, typename P3>
static int Call(RT (*func)(P1, P2, P3), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
RT ret = func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1, typename P2, typename P3, typename P4>
static int Call(RT (*func)(P1, P2, P3, P4), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
RT ret = func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1, typename P2, typename P3, typename P4,
typename P5>
static int Call(RT (*func)(P1, P2, P3, P4, P5), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
RT ret = func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6>
static int Call(RT (*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
RT ret = func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6, typename P7>
static int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
RT ret = func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6, typename P7, typename P8>
static int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
RT ret = func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6, typename P7, typename P8,
typename P9>
static int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
RT ret = func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6, typename P7, typename P8,
typename P9, typename P10>
static int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
luaL_argassert(10, index + 9);
RT ret = func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8),
Type<P10>::Get(L, index + 9)
);
Type<RT>::Push(L, ret);
return 1;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
template <typename Callee>
static int Call(Callee& callee, RT (Callee::*func)(), lua_State* L, int /*index*/) {
RT ret = (callee.*func)();
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee>
static int Call(Callee& callee, RT (Callee::*func)() const, lua_State* L, int /*index*/) {
RT ret = (callee.*func)();
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1>
static int Call(Callee& callee, RT (Callee::*func)(P1), lua_State* L, int index) {
luaL_argassert(1, index + 0);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1>
static int Call(Callee& callee, RT (Callee::*func)(P1) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8,
typename P9>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8,
typename P9>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8,
typename P9, typename P10>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
luaL_argassert(10, index + 9);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8),
Type<P10>::Get(L, index + 9)
);
Type<RT>::Push(L, ret);
return 1;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8,
typename P9, typename P10>
static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
luaL_argassert(10, index + 9);
RT ret = (callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8),
Type<P10>::Get(L, index + 9)
);
Type<RT>::Push(L, ret);
return 1;
}
};
template<>
struct ReturnSpecialization<void> {
static int Call(void (*func)(), lua_State* L, int /*index*/) {
(void)L;
func();
return 0;
}
template <typename P1>
static int Call(void (*func)(P1), lua_State* L, int index) {
luaL_argassert(1, index + 0);
func(
Type<P1>::Get(L, index + 0)
);
return 0;
}
template <typename P1, typename P2>
static int Call(void (*func)(P1, P2), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1)
);
return 0;
}
template <typename P1, typename P2, typename P3>
static int Call(void (*func)(P1, P2, P3), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2)
);
return 0;
}
template <typename P1, typename P2, typename P3, typename P4>
static int Call(void (*func)(P1, P2, P3, P4), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3)
);
return 0;
}
template <typename P1, typename P2, typename P3, typename P4, typename P5>
static int Call(void (*func)(P1, P2, P3, P4, P5), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4)
);
return 0;
}
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
static int Call(void (*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5)
);
return 0;
}
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
static int Call(void (*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6)
);
return 0;
}
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
static int Call(void (*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7)
);
return 0;
}
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
static int Call(void (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8)
);
return 0;
}
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
static int Call(void (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
luaL_argassert(10, index + 9);
func(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8),
Type<P10>::Get(L, index + 9)
);
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
template <typename Callee>
static int Call(Callee& callee, void (Callee::*func)(), lua_State* /*L*/, int /*index*/) {
(callee.*func)();
return 0;
}
template <typename Callee>
static int Call(Callee& callee, void (Callee::*func)() const, lua_State* /*L*/, int /*index*/) {
(callee.*func)();
return 0;
}
template <typename Callee, typename P1>
static int Call(Callee& callee, void (Callee::*func)(P1), lua_State* L, int index) {
luaL_argassert(1, index + 0);
(callee.*func)(
Type<P1>::Get(L, index + 0)
);
return 0;
}
template <typename Callee, typename P1>
static int Call(Callee& callee, void (Callee::*func)(P1) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
(callee.*func)(
Type<P1>::Get(L, index + 0)
);
return 0;
}
template <typename Callee, typename P1, typename P2>
static int Call(Callee& callee, void (Callee::*func)(P1, P2), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1)
);
return 0;
}
template <typename Callee, typename P1, typename P2>
static int Call(Callee& callee, void (Callee::*func)(P1, P2) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8,
typename P9>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8,
typename P9>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8,
typename P9, typename P10>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
luaL_argassert(10, index + 9);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8),
Type<P10>::Get(L, index + 9)
);
return 0;
}
template <typename Callee, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7, typename P8,
typename P9, typename P10>
static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) const, lua_State* L, int index) {
luaL_argassert(1, index + 0);
luaL_argassert(2, index + 1);
luaL_argassert(3, index + 2);
luaL_argassert(4, index + 3);
luaL_argassert(5, index + 4);
luaL_argassert(6, index + 5);
luaL_argassert(7, index + 6);
luaL_argassert(8, index + 7);
luaL_argassert(9, index + 8);
luaL_argassert(10, index + 9);
(callee.*func)(
Type<P1>::Get(L, index + 0),
Type<P2>::Get(L, index + 1),
Type<P3>::Get(L, index + 2),
Type<P4>::Get(L, index + 3),
Type<P5>::Get(L, index + 4),
Type<P6>::Get(L, index + 5),
Type<P7>::Get(L, index + 6),
Type<P8>::Get(L, index + 7),
Type<P9>::Get(L, index + 8),
Type<P10>::Get(L, index + 9)
);
return 0;
}
};
template <typename RT>
int Call(RT (*func)(), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1>
int Call(RT (*func)(P1), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1, typename P2>
int Call(RT (*func)(P1, P2), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1, typename P2, typename P3>
int Call(RT (*func)(P1, P2, P3), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1, typename P2, typename P3, typename P4>
int Call(RT (*func)(P1, P2, P3, P4), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1, typename P2, typename P3, typename P4,
typename P5>
int Call(RT (*func)(P1, P2, P3, P4, P5), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6>
int Call(RT (*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6, typename P7>
int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename RT, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(func, L, index);
}
template <typename Callee, typename RT>
int Call(Callee& callee, RT (Callee::*func)(), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT>
int Call(Callee& callee, RT (Callee::*func)() const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1>
int Call(Callee& callee, RT (Callee::*func)(P1), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1>
int Call(Callee& callee, RT (Callee::*func)(P1) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2>
int Call(Callee& callee, RT (Callee::*func)(P1, P2), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2>
int Call(Callee& callee, RT (Callee::*func)(P1, P2) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3,
typename P4>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3,
typename P4>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3,
typename P4, typename P5>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3,
typename P4, typename P5>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3,
typename P4, typename P5, typename P6, typename P7>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
template <typename Callee, typename RT, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) const, lua_State* L, int index) {
return ReturnSpecialization<RT>::Call(callee, func, L, index);
}
inline unsigned char* GetFirstUpvalueAsUserdata(lua_State* L) {
void* buffer;
#ifndef FAST_DISPATCH
buffer = lua_touserdata(L, lua_upvalueindex(1));
#else // FAST_DISPATCH
#endif // FAST_DISPATCH
return (unsigned char*)buffer;
}
// The Helper class is needed for less fortunate compiler template implementations.
template <typename Func>
class DirectCallFunctionDispatchHelper {
public:
static inline int DirectCallFunctionDispatcher(lua_State* L) {
unsigned char* buffer = GetFirstUpvalueAsUserdata(L);
return Call(*(Func*)(buffer), L, 1);
}
};
template <typename Callee, typename Func>
class DirectCallMemberDispatcherHelper {
public:
static inline int DirectCallMemberDispatcher(lua_State* L) {
unsigned char* buffer = GetFirstUpvalueAsUserdata(L);
return Call(**(Callee**)buffer, *(Func*)(buffer + sizeof(Callee*)), L, 1);
}
};
inline int lua_StateFunctionDispatcher(lua_State* L) {
typedef int (*Functor)(lua_State*);
unsigned char* buffer = GetFirstUpvalueAsUserdata(L);
Functor& func = *(Functor*)(buffer);
return (*func)(L);
}
template <typename Callee>
class lua_StateMemberDispatcherHelper {
public:
static inline int lua_StateMemberDispatcher(lua_State* L) {
typedef int (Callee::*Functor)(lua_State*);
unsigned char* buffer = GetFirstUpvalueAsUserdata(L);
Callee& callee = **(Callee**)buffer;
Functor& func = *(Functor*)(buffer + sizeof(Callee*));
return (callee.*func)(L);
}
};
} // namespace LPCD
template <typename Func>
inline void lpcd_pushdirectclosure(lua_State* L, Func func, unsigned int nupvalues = 0) {
unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func));
memcpy(buffer, &func, sizeof(func));
lua_insert(L, -1 - (int)nupvalues);
lua_pushcclosure(L, LPCD::DirectCallFunctionDispatchHelper<Func>::DirectCallFunctionDispatcher, nupvalues + 1);
}
template <typename Callee, typename Func>
inline void lpcd_pushdirectclosure(lua_State* L, const Callee& callee, Func func, unsigned int nupvalues = 0) {
unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(Callee*) + sizeof(func));
const void* pCallee = &callee;
memcpy(buffer, &pCallee, sizeof(Callee*));
memcpy(buffer + sizeof(Callee*), &func, sizeof(func));
lua_insert(L, -1 - (int)nupvalues);
lua_pushcclosure(L, LPCD::DirectCallMemberDispatcherHelper<Callee, Func>::DirectCallMemberDispatcher, nupvalues + 1);
}
inline void lpcd_pushfunctorclosure(lua_State* L, int (*func)(lua_State*), unsigned int nupvalues = 0) {
unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func));
memcpy(buffer, &func, sizeof(func));
lua_insert(L, -1 - (int)nupvalues);
lua_pushcclosure(L, LPCD::lua_StateFunctionDispatcher, nupvalues + 1);
}
template <typename Callee>
inline void lpcd_pushfunctorclosureex(lua_State* L, const Callee& callee, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) {
unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(Callee*) + sizeof(func));
const void* pCallee = &callee;
memcpy(buffer, &pCallee, sizeof(Callee*));
memcpy(buffer + sizeof(Callee*), &func, sizeof(func));
lua_insert(L, -1 - (int)nupvalues);
lua_pushcclosure(L, LPCD::lua_StateMemberDispatcherHelper<Callee>::lua_StateMemberDispatcher, nupvalues + 1);
}
///////////////////////////////////////////////////////////////////////////////
namespace LPCD {
inline void* GetObjectUserdata(lua_State* L) {
int type = lua_type(L, 1);
if (type == LUA_TUSERDATA)
return *(void **)(lua_touserdata(L, 1));
else if (type == LUA_TTABLE) {
lua_pushstring(L, "__object");
lua_rawget(L, 1);
void* ret;
int subType = lua_type(L, -1);
if (subType == LUA_TLIGHTUSERDATA) {
ret = lua_touserdata(L, -1);
} else if (subType == LUA_TUSERDATA) {
ret = *(void **)(lua_touserdata(L, -1));
} else {
ret = NULL;
luaL_error(L, "The table does not have a userdata member called __object.");
}
lua_pop(L, 1);
return ret;
} else {
luaL_argerror(L, 1, "must be userdata or a table with a userdata member called __object");
}
return NULL;
}
inline void* GetInPlaceObjectUserdata(lua_State* L) {
int type = lua_type(L, 1);
if (type == LUA_TUSERDATA)
return lua_touserdata(L, 1);
else if (type == LUA_TTABLE) {
lua_pushstring(L, "__object");
lua_rawget(L, 1);
void* ret;
int subType = lua_type(L, -1);
if (subType == LUA_TLIGHTUSERDATA) {
ret = lua_touserdata(L, -1);
} else if (subType == LUA_TUSERDATA) {
ret = lua_touserdata(L, -1);
} else {
ret = NULL;
luaL_error(L, "The table does not have a userdata member called __object.");
}
lua_pop(L, 1);
return ret;
} else {
luaL_argerror(L, 1, "must be userdata or a table with a userdata member called __object");
}
return NULL;
}
template <typename Callee>
class Object_MemberDispatcherHelper {
public:
static inline int Object_MemberDispatcher(lua_State* L) {
typedef int (Callee::*Functor)(lua_State*);
unsigned char* buffer = GetFirstUpvalueAsUserdata(L);
Functor& func = *(Functor*)(buffer);
Callee& callee = *(Callee*)GetObjectUserdata(L);
return (callee.*func)(L);
}
};
template <typename Callee, typename Func, int startIndex>
class DirectCallObjectMemberDispatcherHelper {
public:
static inline int DirectCallMemberDispatcher(lua_State* L) {
unsigned char* buffer = GetFirstUpvalueAsUserdata(L);
Callee& callee = *(Callee*)GetObjectUserdata(L);
return Call(callee, *(Func*)buffer, L, startIndex);
}
};
template <typename Callee, typename Func, int startIndex>
class DirectCallInPlaceObjectMemberDispatcherHelper {
public:
static inline int DirectCallMemberDispatcher(lua_State* L) {
unsigned char* buffer = GetFirstUpvalueAsUserdata(L);
Callee& callee = *(Callee*)GetInPlaceObjectUserdata(L);
return Call(callee, *(Func*)buffer, L, startIndex);
}
};
inline int PropertyMetatable_newindex(lua_State* L) {
// table key value
lua_pushvalue(L, 2); // table key value key
lua_rawget(L, lua_upvalueindex(1)); // table key value property
if (lua_isfunction(L, -1)) {
if (lua_getupvalue(L, -1, 2)) { // table key value property userdataTest
if (lua_touserdata(L, -1) == (void*)-2) {
lua_pop(L, 1); // table key value property
lua_CFunction f = lua_tocfunction(L, -1); // table key value propertyfunc
lua_getupvalue(L, -1, 1); // table key value propertyfunc offset
lua_replace(L, 4); // table key value offset
return f(L);
}
lua_pop(L, 1); // table key value
}
lua_rawset(L, -3); // table
return 0;
} else if (!lua_isnil(L, -1)) {
lua_pop(L, 1); // table key value
lua_rawset(L, -3); // table
return 0;
}
lua_pop(L, 1); // table key value
if (!lua_getmetatable(L, -3)) // table key value metatable
return 0;
do {
lua_getfield(L, -1, "__newindex"); // table key value metatable __newindex
if (lua_isnil(L, -1)) {
lua_pop(L, 2); // table key value
lua_rawset(L, -3); // table
return 0;
}
lua_getupvalue(L, -1, 1); // table key value metatable __newindex functions
lua_pushvalue(L, 2); // table key value metatable __newindex functions key
lua_rawget(L, -2); // table key value metatable __newindex functions property
if (lua_isfunction(L, -1)) {
if (lua_getupvalue(L, -1, 2)) { // table key value metatable __newindex functions userdataTest
if (lua_touserdata(L, -1) == (void*)-2) {
lua_pop(L, 1); // table key value metatable __newindex functions
lua_CFunction f = lua_tocfunction(L, -1); // table key value metatable __newindex functions
lua_getupvalue(L, -1, 1); // table key value metatable __newindex functions offset
lua_replace(L, 4); // table key value offset __newindex functions
return f(L);
}
lua_pop(L, 2); // table key value metatable __newindex
}
lua_rawset(L, -3); // table key value
return 1;
} else if (!lua_isnil(L, -1)) {
lua_pop(L, 4);
lua_rawset(L, -3);
return 0;
}
lua_pop(L, 3); // table key value metatable
if (!lua_getmetatable(L, 4)) { // table key value metatable metatable2
lua_pop(L, 1);
break;
}
lua_remove(L, -2); // table key value metatable2
} while (true);
lua_rawset(L, -3);
return 0;
}
// function gettable_event (table, key)
// upvalues:
// 1 - function__index
// 2 - properties__index
inline int PropertyMetatable_index(lua_State* L) {
lua_pushvalue(L, 2); // table key key
lua_rawget(L, lua_upvalueindex(1)); // table key property
if (lua_isfunction(L, -1)) {
if (lua_getupvalue(L, -1, 2)) {
if (lua_touserdata(L, -1) == (void*)-2) {
lua_pop(L, 1);
lua_CFunction f = lua_tocfunction(L, -1); // table key propertyfunc
lua_getupvalue(L, -1, 1); // table key propertyfunc offset
lua_replace(L, 3); // table key offset
return f(L);
}
lua_pop(L, 1);
}
return 1;
} else if (!lua_isnil(L, -1))
return 1;
lua_pop(L, 1); // table key
if (!lua_getmetatable(L, -2)) // table key metatable
return 0;
do {
lua_getfield(L, -1, "__index"); // table key metatable __index
if (lua_isnil(L, -1))
return 0;
lua_getupvalue(L, -1, 1); // table key metatable __index functions
lua_pushvalue(L, 2); // table key metatable __index functions key
lua_rawget(L, -2); // table key metatable __index functions property
if (lua_isfunction(L, -1)) {
if (lua_getupvalue(L, -1, 2)) { // table key metatable __index functions userdataTest
if (lua_touserdata(L, -1) == (void*)-2) {
lua_pop(L, 1); // table key metatable __index functions
lua_CFunction f = lua_tocfunction(L, -1); // table key metatable __index functions
lua_getupvalue(L, -1, 1); // table key metatable __index functions offset
lua_replace(L, 3); // table key offset __index functions
return f(L);
}
lua_pop(L, 1); // table key metatable __index functions
}
return 1;
} else if (!lua_isnil(L, -1))
return 1;
lua_pop(L, 3); // table key metatable
if (!lua_getmetatable(L, 3)) // table key metatable metatable2
return 0;
lua_remove(L, -2); // table key metatable2
} while (true);
}
template <typename Object, typename VarType>
class PropertyMemberHelper {
public:
static int PropertyGet(lua_State* L) {
Object* obj = (Object*)LPCD::GetObjectUserdata(L);
void* offset = lua_touserdata(L, 3);
LPCD::Type<VarType>::Push(L, *(VarType*)((unsigned char*)obj + (ptrdiff_t)offset));
return 1;
}
static int PropertySet(lua_State* L) {
Object* obj = (Object*)LPCD::GetObjectUserdata(L);
void* offset = lua_touserdata(L, 4);
if (!LPCD::Type<VarType>::Match(L, 3))
luaL_argerror(L, 3, "bad argument");
*(VarType*)((unsigned char*)obj + (ptrdiff_t)offset) = LPCD::Type<VarType>::Get(L, 3);
return 0;
}
};
template <typename Object, typename VarType>
class InPlacePropertyMemberHelper {
public:
static int PropertyGet(lua_State* L) {
Object* obj = (Object*)LPCD::GetInPlaceObjectUserdata(L);
void* offset = lua_touserdata(L, 3);
LPCD::Type<VarType>::Push(L, *(VarType*)((unsigned char*)obj + (ptrdiff_t)offset));
return 1;
}
static int PropertySet(lua_State* L) {
Object* obj = (Object*)LPCD::GetInPlaceObjectUserdata(L);
void* offset = lua_touserdata(L, 4);
if (!Type<VarType>::Match(L, 3))
luaL_argerror(L, 3, "bad argument");
*(VarType*)((unsigned char*)obj + (ptrdiff_t)offset) = Type<VarType>::Get(L, 3);
return 0;
}
};
template <typename VarType>
class PropertyGlobalHelper {
public:
static int PropertyGet(lua_State* L) {
void* offset = lua_touserdata(L, lua_upvalueindex(1));
LPCD::Type<VarType>::Push(L, *(VarType*)offset);
return 1;
}
static int PropertySet(lua_State* L) {
void* offset = lua_touserdata(L, lua_upvalueindex(1));
if (!LPCD::Type<VarType>::Match(L, 1))
luaL_argerror(L, 2, "bad argument");
*(VarType*)offset = LPCD::Type<VarType>::Get(L, 1);
return 1;
}
};
} // namespace LPCD
template <typename Callee>
inline void lpcd_pushobjectfunctorclosure(lua_State* L, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) {
unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func));
memcpy(buffer, &func, sizeof(func));
lua_pushcclosure(L, LPCD::Object_MemberDispatcherHelper<Callee>::Object_MemberDispatcher, nupvalues + 1);
}
template <typename Callee, typename Func>
inline void lpcd_pushobjectdirectclosure(lua_State* L, const Callee* callee, Func func, unsigned int nupvalues = 0) {
unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func));
memcpy(buffer, &func, sizeof(func));
lua_pushcclosure(L, LPCD::DirectCallObjectMemberDispatcherHelper<Callee, Func, 2>::DirectCallMemberDispatcher, nupvalues + 1);
}
template <typename Callee>
inline void lpcd_pushinplaceobjectfunctorclosure(lua_State* L, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) {
unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func));
memcpy(buffer, &func, sizeof(func));
//lua_pushcclosure(L, LPCD::Object_InPlaceMemberDispatcherHelper<Callee>::Object_MemberDispatcher, nupvalues + 1);
}
template <typename Callee, typename Func>
inline void lpcd_pushinplaceobjectdirectclosure(lua_State* L, const Callee* callee, Func func, unsigned int nupvalues = 0) {
unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func));
memcpy(buffer, &func, sizeof(func));
lua_pushcclosure(L, LPCD::DirectCallInPlaceObjectMemberDispatcherHelper<Callee, Func, 2>::DirectCallMemberDispatcher, nupvalues + 1);
}
template <typename Object, typename VarType>
inline void lpcd_pushmemberpropertygetclosure(lua_State* L, VarType Object::* var) {
lua_pushlightuserdata(L, (void*)&(((Object*)0)->*var));
lua_pushlightuserdata(L, (void*)-2);
lua_pushcclosure(L, &LPCD::PropertyMemberHelper<Object, VarType>::PropertyGet, 2);
}
template <typename Object, typename VarType>
inline void lpcd_pushmemberpropertysetclosure(lua_State* L, VarType Object::* var) {
lua_pushlightuserdata(L, (void*)&(((Object*)0)->*var));
lua_pushlightuserdata(L, (void*)-2);
lua_pushcclosure(L, &LPCD::PropertyMemberHelper<Object, VarType>::PropertySet, 2);
}
template <typename Object, typename VarType>
inline void lpcd_pushmemberinplacepropertygetclosure(lua_State* L, VarType Object::* var) {
lua_pushlightuserdata(L, (void*)&(((Object*)0)->*var));
lua_pushlightuserdata(L, (void*)-2);
lua_pushcclosure(L, &LPCD::InPlacePropertyMemberHelper<Object, VarType>::PropertyGet, 2);
}
template <typename Object, typename VarType>
inline void lpcd_pushmemberinplacepropertysetclosure(lua_State* L, VarType Object::* var) {
lua_pushlightuserdata(L, (void*)&(((Object*)0)->*var));
lua_pushlightuserdata(L, (void*)-2);
lua_pushcclosure(L, &LPCD::InPlacePropertyMemberHelper<Object, VarType>::PropertySet, 2);
}
template <typename VarType>
inline void lpcd_pushglobalpropertygetclosure(lua_State* L, VarType* var) {
lua_pushlightuserdata(L, (void*)var);
lua_pushlightuserdata(L, (void*)-2);
lua_pushcclosure(L, &LPCD::PropertyGlobalHelper<VarType>::PropertyGet, 2);
}
template <typename VarType>
inline void lpcd_pushglobalpropertysetclosure(lua_State* L, VarType* var) {
lua_pushlightuserdata(L, (void*)var);
lua_pushlightuserdata(L, (void*)-2);
lua_pushcclosure(L, &LPCD::PropertyGlobalHelper<VarType>::PropertySet, 2);
}
/* convert a stack index to positive */
#define lpcd_abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
inline void lpcd_integratepropertysupport(lua_State* L, int metatableIndex, bool inPlace = false) {
metatableIndex = lpcd_abs_index(L, metatableIndex);
lua_pushstring(L, "__index"); // metatable "__index"
lua_newtable(L); // metatable "__index" __index
lua_pushboolean(L, inPlace ? 1 : 0);// metatable "__index" __index inPlace
lua_pushcclosure(L, LPCD::PropertyMetatable_index, 2); // metatable "__index" PropertyMetatable_index
lua_rawset(L, metatableIndex); // metatable
lua_pushstring(L, "__newindex"); // metatable "__newindex"
lua_newtable(L); // metatable "__newindex" __newindex
lua_pushboolean(L, inPlace ? 1 : 0);// metatable "__newindex" __newindex inPlace
lua_pushcclosure(L, LPCD::PropertyMetatable_newindex, 2); // metatable "__newindex" PropertyMetatable_newindex
lua_rawset(L, metatableIndex); // metatable
}
inline void lpcd_propertymetatable_getfunctions(lua_State* L, int metatableIndex) {
lua_getfield(L, metatableIndex, "__index"); // (metatable) __index
lua_getupvalue(L, -1, 1); // (metatable) __index props__functions
lua_remove(L, -2); // (metatable) props__functions
}
inline void lpcd_newclassmetatable(lua_State* L, const char* className, const char* baseClassName, bool inPlace = false) {
luaL_newmetatable(L, className); // class_metatable
lpcd_integratepropertysupport(L, -1, inPlace);
if (baseClassName) {
luaL_getmetatable(L, baseClassName); // class_metatable baseClass_metatable
lua_setmetatable(L, -2); // class_metatable
}
}
template <typename Object, typename VarType>
inline void lpcd_propertycreate(lua_State* L, int metatableIndex, const char* varName, VarType Object::* var, bool read = true, bool write = true) {
lua_pushvalue(L, metatableIndex); // metatable
lua_pushstring(L, varName); // metatable varName
if (read) {
lua_getfield(L, -2, "__index"); // metatable varName __index
lua_getupvalue(L, -1, 1); // metatable varName __index functions
lua_getupvalue(L, -2, 2); // metatable varName __index functions inPlace
bool inPlace = lua_toboolean(L, -1) != 0;
lua_pop(L, 1); // metatable varName __index functions
lua_pushvalue(L, -3); // metatable varName __index functions varName
inPlace ? lpcd_pushmemberinplacepropertygetclosure(L, var) : lpcd_pushmemberpropertygetclosure(L, var);
// metatable varName __index functions varName closure
lua_rawset(L, -3); // metatable varName __index functions
lua_pop(L, 2); // metatable varName
}
if (write) {
lua_getfield(L, -2, "__newindex"); // metatable varName __newindex
lua_getupvalue(L, -1, 1); // metatable varName __newindex functions
lua_getupvalue(L, -2, 2); // metatable varName __newindex functions inPlace
bool inPlace = lua_toboolean(L, -1) != 0;
lua_pop(L, 1); // metatable varName __newindex functions
lua_pushvalue(L, -3); // metatable varName __newindex functions varName
inPlace ? lpcd_pushmemberinplacepropertysetclosure(L, var) : lpcd_pushmemberpropertysetclosure(L, var);
// metatable varName __newindex functions varName closure
lua_rawset(L, -3); // metatable varName __newindex functions
lua_pop(L, 2); // metatable varName
}
lua_pop(L, 2);
}
inline void* lpcd_checkobject(lua_State* L, int index, const char* tname, bool throwError = true) {
assert(tname);
int type = lua_type(L, index);
if (type == LUA_TTABLE) {
lua_getfield(L, index, "__object");
if (lua_getmetatable(L, -1)) { /* does it have a metatable? */
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
int equal = lua_rawequal(L, -1, -2); /* does it have the correct mt? */
lua_pop(L, 2); /* remove both metatables */
if (!equal) {
lua_pop(L, 1);
goto error;
}
}
void *p = lua_touserdata(L, -1);
lua_pop(L, 1);
return p;
} else if (type == LUA_TUSERDATA) {
if (lua_getmetatable(L, index)) { /* does it have a metatable? */
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
int equal = lua_rawequal(L, -1, -2); /* does it have the correct mt? */
lua_pop(L, 2); /* remove both metatables */
if (!equal)
goto error;
}
return lua_touserdata(L, index);
}
error:
if (throwError) {
const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, luaL_typename(L, index));
luaL_argerror(L, index, msg);
}
return NULL;
}
namespace LPCD {
class Class {
public:
Class(lua_State* L, const char* className, const char* baseClassName = NULL)
: L(L)
{
lpcd_newclassmetatable(L, className, baseClassName);
lpcd_propertymetatable_getfunctions(L, -1);
}
~Class() {
lua_pop(L, 2);
}
void MetatableFunction(const char* name, lua_CFunction func, unsigned int nupvalues = 0) {
lua_pushcclosure(L, func, nupvalues);
lua_setfield(L, -3, name);
}
template <typename Object, typename VarType>
Class& Property(const char* varName, VarType Object::* var, bool read = true, bool write = true) {
lpcd_propertycreate(L, -2, varName, var, read, write);
return *this;
}
void Function(const char* name, lua_CFunction func, unsigned int nupvalues = 0) {
lua_pushcclosure(L, func, nupvalues);
lua_setfield(L, -2, name);
}
template <typename Callee>
inline Class& ObjectFunctor(const char* name, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) {
lpcd_pushobjectfunctorclosure(L, func, nupvalues);
lua_setfield(L, -2, name);
return *this;
}
template <typename Callee, typename Func>
inline Class& ObjectDirect(const char* name, const Callee* callee, Func func, unsigned int nupvalues = 0) {
lpcd_pushobjectdirectclosure(L, callee, func, nupvalues);
lua_setfield(L, -2, name);
return *this;
}
lua_State* L;
};
class InPlaceClass {
public:
InPlaceClass(lua_State* L, const char* className, const char* baseClassName = NULL)
: L(L)
{
lpcd_newclassmetatable(L, className, baseClassName, true);
lpcd_propertymetatable_getfunctions(L, -1);
}
~InPlaceClass() {
lua_pop(L, 2);
}
void MetatableFunction(const char* name, lua_CFunction func, unsigned int nupvalues = 0) {
lua_pushcclosure(L, func, nupvalues);
lua_setfield(L, -3, name);
}
template <typename Object, typename VarType>
InPlaceClass& Property(const char* varName, VarType Object::* var, bool read = true, bool write = true) {
lpcd_propertycreate(L, -2, varName, var, read, write);
return *this;
}
template <typename Callee>
inline InPlaceClass& ObjectFunctor(const char* name, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) {
lpcd_pushinplaceobjectfunctorclosure(L, func, nupvalues);
lua_setfield(L, -2, name);
return *this;
}
template <typename Callee, typename Func>
inline InPlaceClass& ObjectDirect(const char* name, const Callee* callee, Func func, unsigned int nupvalues = 0) {
lpcd_pushinplaceobjectdirectclosure(L, callee, func, nupvalues);
lua_setfield(L, -2, name);
return *this;
}
lua_State* L;
};
} // namespace LPCD
#endif // LUAPLUS__LUAPLUSCD_H