struct CFunc
{
static int indexMetaMethod (lua_State* L)
{
int result = 0;
lua_getmetatable (L, 1); for (;;)
{
lua_pushvalue (L, 2); lua_rawget (L, -2); if (lua_isnil (L, -1)) {
lua_pop (L, 1); rawgetfield (L, -1, "__propget"); lua_pushvalue (L, 2); lua_rawget (L, -2); lua_remove (L, -2); if (lua_iscfunction (L, -1))
{
lua_remove (L, -2); lua_pushvalue (L, 1); lua_call (L, 1, 1); result = 1;
break;
}
else
{
assert (lua_isnil (L, -1));
lua_pop (L, 1); }
}
else
{
assert (lua_istable (L, -1) || lua_iscfunction (L, -1));
lua_remove (L, -2);
result = 1;
break;
}
rawgetfield (L, -1, "__parent");
if (lua_istable (L, -1))
{
lua_remove (L, -2);
}
else
{
assert (lua_isnil (L, -1));
lua_remove (L, -2);
result = 1;
break;
}
}
return result;
}
static int newindexMetaMethod (lua_State* L)
{
int result = 0;
lua_getmetatable (L, 1); for (;;)
{
rawgetfield (L, -1, "__propset"); assert (lua_istable (L, -1));
lua_pushvalue (L, 2); lua_rawget (L, -2); lua_remove (L, -2); if (lua_iscfunction (L, -1)) {
lua_remove (L, -2); lua_pushvalue (L, 3); lua_call (L, 1, 0); result = 0;
break;
}
else
{
assert (lua_isnil (L, -1));
lua_pop (L, 1);
}
rawgetfield (L, -1, "__parent");
if (lua_istable (L, -1))
{
lua_remove (L, -2);
}
else
{
assert (lua_isnil (L, -1));
lua_pop (L, 2);
luaL_error (L,"no writable variable '%s'", lua_tostring (L, 2));
}
}
return result;
}
static int readOnlyError (lua_State* L)
{
std::string s;
s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only";
return luaL_error (L, s.c_str ());
}
template <class T>
static int getVariable (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
T const* ptr = static_cast <T const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (ptr != 0);
Stack <T>::push (L, *ptr);
return 1;
}
template <class T>
static int setVariable (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
T* ptr = static_cast <T*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (ptr != 0);
*ptr = Stack <T>::get (L, 1);
return 0;
}
template <class FnPtr,
class ReturnType = typename FuncTraits <FnPtr>::ReturnType>
struct Call
{
typedef typename FuncTraits <FnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params> args (L);
Stack <typename FuncTraits <FnPtr>::ReturnType>::push (L, FuncTraits <FnPtr>::call (fnptr, args));
return 1;
}
};
template <class FnPtr>
struct Call <FnPtr, void>
{
typedef typename FuncTraits <FnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params> args (L);
FuncTraits <FnPtr>::call (fnptr, args);
return 0;
}
};
template <class MemFnPtr,
class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
struct CallMember
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
typedef typename FuncTraits <MemFnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
T* const t = Userdata::get <T> (L, 1, false);
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params, 2> args (L);
Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
return 1;
}
};
template <class MemFnPtr,
class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
struct CallConstMember
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
typedef typename FuncTraits <MemFnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
T const* const t = Userdata::get <T> (L, 1, true);
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params, 2> args(L);
Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
return 1;
}
};
template <class MemFnPtr>
struct CallMember <MemFnPtr, void>
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
typedef typename FuncTraits <MemFnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
T* const t = Userdata::get <T> (L, 1, false);
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params, 2> args (L);
FuncTraits <MemFnPtr>::call (t, fnptr, args);
return 0;
}
};
template <class MemFnPtr>
struct CallConstMember <MemFnPtr, void>
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
typedef typename FuncTraits <MemFnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
T const* const t = Userdata::get <T> (L, 1, true);
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params, 2> args (L);
FuncTraits <MemFnPtr>::call (t, fnptr, args);
return 0;
}
};
template <class T>
struct CallMemberCFunction
{
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
typedef int (T::*MFP)(lua_State* L);
T* const t = Userdata::get <T> (L, 1, false);
MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return (t->*fnptr) (L);
}
};
template <class T>
struct CallConstMemberCFunction
{
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
typedef int (T::*MFP)(lua_State* L);
T const* const t = Userdata::get <T> (L, 1, true);
MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return (t->*fnptr) (L);
}
};
template <class MemFnPtr, bool isConst>
struct CallMemberFunctionHelper
{
static void add (lua_State* L, char const* name, MemFnPtr mf)
{
new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
lua_pushcclosure (L, &CallConstMember <MemFnPtr>::f, 1);
lua_pushvalue (L, -1);
rawsetfield (L, -5, name); rawsetfield (L, -3, name); }
};
template <class MemFnPtr>
struct CallMemberFunctionHelper <MemFnPtr, false>
{
static void add (lua_State* L, char const* name, MemFnPtr mf)
{
new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
lua_pushcclosure (L, &CallMember <MemFnPtr>::f, 1);
rawsetfield (L, -3, name); }
};
template <class C>
static int gcMetaMethod (lua_State* L)
{
Userdata* const ud = Userdata::getExact <C> (L, 1);
ud->~Userdata ();
return 0;
}
template <class C, typename T>
static int getProperty (lua_State* L)
{
C const* const c = Userdata::get <C> (L, 1, true);
T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
Stack <T>::push (L, c->**mp);
return 1;
}
template <class C, typename T>
static int setProperty (lua_State* L)
{
C* const c = Userdata::get <C> (L, 1, false);
T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
c->**mp = Stack <T>::get (L, 2);
return 0;
}
};