添加lua+luatinker
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
add_library(LuaTinker STATIC
|
||||
lua_tinker.cpp
|
||||
lua_tinker.h
|
||||
)
|
||||
|
||||
target_include_directories(LuaTinker
|
||||
PRIVATE
|
||||
../lua/src
|
||||
)
|
||||
|
||||
@@ -0,0 +1,745 @@
|
||||
// lua_tinker.cpp
|
||||
//
|
||||
// LuaTinker - Simple and light C++ wrapper for Lua.
|
||||
//
|
||||
// Copyright (c) 2005-2007 Kwon-il Lee (zupet@hitel.net)
|
||||
//
|
||||
// please check Licence.txt file for licence and legal issues.
|
||||
|
||||
#include <iostream>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
};
|
||||
|
||||
#include "lua_tinker.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* init */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void lua_tinker::init(lua_State *L)
|
||||
{
|
||||
init_s64(L);
|
||||
init_u64(L);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* __s64 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int tostring_s64(lua_State *L)
|
||||
{
|
||||
char temp[64];
|
||||
sprintf_s(temp, "%I64d", *(long long*)lua_topointer(L, 1));
|
||||
lua_pushstring(L, temp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int eq_s64(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, memcmp(lua_topointer(L, 1), lua_topointer(L, 2), sizeof(long long)) == 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int lt_s64(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, memcmp(lua_topointer(L, 1), lua_topointer(L, 2), sizeof(long long)) < 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int le_s64(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, memcmp(lua_topointer(L, 1), lua_topointer(L, 2), sizeof(long long)) <= 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void lua_tinker::init_s64(lua_State *L)
|
||||
{
|
||||
const char* name = "__s64";
|
||||
lua_pushstring(L, name);
|
||||
lua_newtable(L);
|
||||
|
||||
lua_pushstring(L, "__name");
|
||||
lua_pushstring(L, name);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__tostring");
|
||||
lua_pushcclosure(L, tostring_s64, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__eq");
|
||||
lua_pushcclosure(L, eq_s64, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__lt");
|
||||
lua_pushcclosure(L, lt_s64, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__le");
|
||||
lua_pushcclosure(L, le_s64, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* __u64 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int tostring_u64(lua_State *L)
|
||||
{
|
||||
char temp[64];
|
||||
sprintf_s(temp, "%I64u", *(unsigned long long*)lua_topointer(L, 1));
|
||||
lua_pushstring(L, temp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int eq_u64(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, memcmp(lua_topointer(L, 1), lua_topointer(L, 2), sizeof(unsigned long long)) == 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int lt_u64(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, memcmp(lua_topointer(L, 1), lua_topointer(L, 2), sizeof(unsigned long long)) < 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int le_u64(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, memcmp(lua_topointer(L, 1), lua_topointer(L, 2), sizeof(unsigned long long)) <= 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void lua_tinker::init_u64(lua_State *L)
|
||||
{
|
||||
const char* name = "__u64";
|
||||
lua_pushstring(L, name);
|
||||
lua_newtable(L);
|
||||
|
||||
lua_pushstring(L, "__name");
|
||||
lua_pushstring(L, name);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__tostring");
|
||||
lua_pushcclosure(L, tostring_u64, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__eq");
|
||||
lua_pushcclosure(L, eq_u64, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__lt");
|
||||
lua_pushcclosure(L, lt_u64, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__le");
|
||||
lua_pushcclosure(L, le_u64, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* excution */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void lua_tinker::dofile(lua_State *L, const char *filename)
|
||||
{
|
||||
lua_pushcclosure(L, on_error, 0);
|
||||
int errfunc = lua_gettop(L);
|
||||
|
||||
if(luaL_loadfile(L, filename) == 0)
|
||||
{
|
||||
lua_pcall(L, 0, 1, errfunc);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error(L, "%s", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
lua_remove(L, errfunc);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void lua_tinker::dostring(lua_State *L, const char* buff)
|
||||
{
|
||||
lua_tinker::dobuffer(L, buff, strlen(buff));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void lua_tinker::dobuffer(lua_State *L, const char* buff, size_t len)
|
||||
{
|
||||
lua_pushcclosure(L, on_error, 0);
|
||||
int errfunc = lua_gettop(L);
|
||||
|
||||
if(luaL_loadbuffer(L, buff, len, "lua_tinker::dobuffer()") == 0)
|
||||
{
|
||||
lua_pcall(L, 0, 1, errfunc);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error(L, "%s", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
lua_remove(L, errfunc);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* debug helpers */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void call_stack(lua_State* L, int n)
|
||||
{
|
||||
lua_Debug ar;
|
||||
if(lua_getstack(L, n, &ar) == 1)
|
||||
{
|
||||
lua_getinfo(L, "nSlu", &ar);
|
||||
|
||||
const char* indent;
|
||||
if(n == 0)
|
||||
{
|
||||
indent = "->\t";
|
||||
lua_tinker::print_error(L, "\t<call stack>");
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = "\t";
|
||||
}
|
||||
|
||||
if(ar.name)
|
||||
lua_tinker::print_error(L, "%s%s() : line %d [%s : line %d]", indent, ar.name, ar.currentline, ar.source, ar.linedefined);
|
||||
else
|
||||
lua_tinker::print_error(L, "%sunknown : line %d [%s : line %d]", indent, ar.currentline, ar.source, ar.linedefined);
|
||||
|
||||
call_stack(L, n+1);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int lua_tinker::on_error(lua_State *L)
|
||||
{
|
||||
print_error(L, "%s", lua_tostring(L, -1));
|
||||
|
||||
call_stack(L, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void lua_tinker::print_error(lua_State *L, const char* fmt, ...)
|
||||
{
|
||||
char text[4096];
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsprintf_s(text, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
lua_pushstring(L, "_ALERT");
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
if(lua_isfunction(L, -1))
|
||||
{
|
||||
lua_pushstring(L, text);
|
||||
lua_call(L, 1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s\n", text);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void lua_tinker::enum_stack(lua_State *L)
|
||||
{
|
||||
int top = lua_gettop(L);
|
||||
print_error(L, "Type:%d", top);
|
||||
for(int i=1; i<=lua_gettop(L); ++i)
|
||||
{
|
||||
switch(lua_type(L, i))
|
||||
{
|
||||
case LUA_TNIL:
|
||||
print_error(L, "\t%s", lua_typename(L, lua_type(L, i)));
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
print_error(L, "\t%s %s", lua_typename(L, lua_type(L, i)), lua_toboolean(L, i)?"true":"false");
|
||||
break;
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
print_error(L, "\t%s 0x%08p", lua_typename(L, lua_type(L, i)), lua_topointer(L, i));
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
print_error(L, "\t%s %f", lua_typename(L, lua_type(L, i)), lua_tonumber(L, i));
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
print_error(L, "\t%s %s", lua_typename(L, lua_type(L, i)), lua_tostring(L, i));
|
||||
break;
|
||||
case LUA_TTABLE:
|
||||
print_error(L, "\t%s 0x%08p", lua_typename(L, lua_type(L, i)), lua_topointer(L, i));
|
||||
break;
|
||||
case LUA_TFUNCTION:
|
||||
print_error(L, "\t%s() 0x%08p", lua_typename(L, lua_type(L, i)), lua_topointer(L, i));
|
||||
break;
|
||||
case LUA_TUSERDATA:
|
||||
print_error(L, "\t%s 0x%08p", lua_typename(L, lua_type(L, i)), lua_topointer(L, i));
|
||||
break;
|
||||
case LUA_TTHREAD:
|
||||
print_error(L, "\t%s", lua_typename(L, lua_type(L, i)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* read */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
template<>
|
||||
char* lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (char*)lua_tostring(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
const char* lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (const char*)lua_tostring(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
char lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (char)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned char lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (unsigned char)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
short lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (short)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned short lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (unsigned short)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
long lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (long)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned long lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (unsigned long)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
int lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (int)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned int lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (unsigned int)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
float lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (float)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
double lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return (double)lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
if(lua_isboolean(L, index))
|
||||
return lua_toboolean(L, index) != 0;
|
||||
else
|
||||
return lua_tonumber(L, index) != 0;
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<>
|
||||
long long lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
if(lua_isnumber(L,index))
|
||||
return (long long)lua_tonumber(L, index);
|
||||
else
|
||||
return *(long long*)lua_touserdata(L, index);
|
||||
}
|
||||
template<>
|
||||
unsigned long long lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
if(lua_isnumber(L,index))
|
||||
return (unsigned long long)lua_tonumber(L, index);
|
||||
else
|
||||
return *(unsigned long long*)lua_touserdata(L, index);
|
||||
}
|
||||
|
||||
template<>
|
||||
lua_tinker::table lua_tinker::read(lua_State *L, int index)
|
||||
{
|
||||
return table(L, index);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* push */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, char ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, unsigned char ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, short ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, unsigned short ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, long ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, unsigned long ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, int ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, unsigned int ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, float ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, double ret)
|
||||
{
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, char* ret)
|
||||
{
|
||||
lua_pushstring(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, const char* ret)
|
||||
{
|
||||
lua_pushstring(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, bool ret)
|
||||
{
|
||||
lua_pushboolean(L, ret);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, lua_value* ret)
|
||||
{
|
||||
if(ret) ret->to_lua(L); else lua_pushnil(L);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, long long ret)
|
||||
{
|
||||
*(long long*)lua_newuserdata(L, sizeof(long long)) = ret;
|
||||
lua_pushstring(L, "__s64");
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, unsigned long long ret)
|
||||
{
|
||||
*(unsigned long long*)lua_newuserdata(L, sizeof(unsigned long long)) = ret;
|
||||
lua_pushstring(L, "__u64");
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
template<>
|
||||
void lua_tinker::push(lua_State *L, lua_tinker::table ret)
|
||||
{
|
||||
lua_pushvalue(L, ret.m_obj->m_index);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* pop */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
template<>
|
||||
void lua_tinker::pop(lua_State *L)
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
template<>
|
||||
lua_tinker::table lua_tinker::pop(lua_State *L)
|
||||
{
|
||||
return table(L, lua_gettop(L));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Tinker Class Helper */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void invoke_parent(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, "__parent");
|
||||
lua_rawget(L, -2);
|
||||
if(lua_istable(L,-1))
|
||||
{
|
||||
lua_pushvalue(L,2);
|
||||
lua_rawget(L, -2);
|
||||
if(!lua_isnil(L,-1))
|
||||
{
|
||||
lua_remove(L,-2);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_remove(L, -1);
|
||||
invoke_parent(L);
|
||||
lua_remove(L,-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int lua_tinker::meta_get(lua_State *L)
|
||||
{
|
||||
lua_getmetatable(L,1);
|
||||
lua_pushvalue(L,2);
|
||||
lua_rawget(L,-2);
|
||||
|
||||
if(lua_isuserdata(L,-1))
|
||||
{
|
||||
user2type<var_base*>::invoke(L,-1)->get(L);
|
||||
lua_remove(L, -2);
|
||||
}
|
||||
else if(lua_isnil(L,-1))
|
||||
{
|
||||
lua_remove(L,-1);
|
||||
invoke_parent(L);
|
||||
if(lua_isnil(L,-1))
|
||||
{
|
||||
lua_pushfstring(L, "can't find '%s' class variable. (forgot registering class variable ?)", lua_tostring(L, 2));
|
||||
lua_error(L);
|
||||
}
|
||||
}
|
||||
|
||||
lua_remove(L,-2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int lua_tinker::meta_set(lua_State *L)
|
||||
{
|
||||
lua_getmetatable(L,1);
|
||||
lua_pushvalue(L,2);
|
||||
lua_rawget(L,-2);
|
||||
|
||||
if(lua_isuserdata(L,-1))
|
||||
{
|
||||
user2type<var_base*>::invoke(L,-1)->set(L);
|
||||
}
|
||||
else if(lua_isnil(L, -1))
|
||||
{
|
||||
lua_pushvalue(L,2);
|
||||
lua_pushvalue(L,3);
|
||||
lua_rawset(L, -4);
|
||||
}
|
||||
lua_settop(L, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void lua_tinker::push_meta(lua_State *L, const char* name)
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* table object on stack */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
lua_tinker::table_obj::table_obj(lua_State* L, int index)
|
||||
:m_L(L)
|
||||
,m_index(index)
|
||||
,m_ref(0)
|
||||
{
|
||||
if(lua_isnil(m_L, m_index))
|
||||
{
|
||||
m_pointer = NULL;
|
||||
lua_remove(m_L, m_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pointer = lua_topointer(m_L, m_index);
|
||||
}
|
||||
}
|
||||
|
||||
lua_tinker::table_obj::~table_obj()
|
||||
{
|
||||
if(validate())
|
||||
{
|
||||
lua_remove(m_L, m_index);
|
||||
}
|
||||
}
|
||||
|
||||
void lua_tinker::table_obj::inc_ref()
|
||||
{
|
||||
++m_ref;
|
||||
}
|
||||
|
||||
void lua_tinker::table_obj::dec_ref()
|
||||
{
|
||||
if(--m_ref == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool lua_tinker::table_obj::validate()
|
||||
{
|
||||
if(m_pointer != NULL)
|
||||
{
|
||||
if(m_pointer == lua_topointer(m_L, m_index))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int top = lua_gettop(m_L);
|
||||
|
||||
for(int i=1; i<=top; ++i)
|
||||
{
|
||||
if(m_pointer == lua_topointer(m_L, i))
|
||||
{
|
||||
m_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
m_pointer = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Table Object Holder */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
lua_tinker::table::table(lua_State* L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
|
||||
m_obj = new table_obj(L, lua_gettop(L));
|
||||
|
||||
m_obj->inc_ref();
|
||||
}
|
||||
|
||||
lua_tinker::table::table(lua_State* L, const char* name)
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
|
||||
if(lua_istable(L, -1) == 0)
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, name);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
|
||||
m_obj = new table_obj(L, lua_gettop(L));
|
||||
}
|
||||
|
||||
lua_tinker::table::table(lua_State* L, int index)
|
||||
{
|
||||
if(index < 0)
|
||||
{
|
||||
index = lua_gettop(L) + index + 1;
|
||||
}
|
||||
|
||||
m_obj = new table_obj(L, index);
|
||||
|
||||
m_obj->inc_ref();
|
||||
}
|
||||
|
||||
lua_tinker::table::table(const table& input)
|
||||
{
|
||||
m_obj = input.m_obj;
|
||||
|
||||
m_obj->inc_ref();
|
||||
}
|
||||
|
||||
lua_tinker::table::~table()
|
||||
{
|
||||
m_obj->dec_ref();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@@ -0,0 +1,982 @@
|
||||
// lua_tinker.h
|
||||
//
|
||||
// LuaTinker - Simple and light C++ wrapper for Lua.
|
||||
//
|
||||
// Copyright (c) 2005-2007 Kwon-il Lee (zupet@hitel.net)
|
||||
//
|
||||
// please check Licence.txt file for licence and legal issues.
|
||||
|
||||
#if !defined(_LUA_TINKER_H_)
|
||||
#define _LUA_TINKER_H_
|
||||
|
||||
#include <new>
|
||||
#include <string.h>
|
||||
|
||||
namespace lua_tinker
|
||||
{
|
||||
// init LuaTinker
|
||||
void init(lua_State *L);
|
||||
|
||||
void init_s64(lua_State *L);
|
||||
void init_u64(lua_State *L);
|
||||
|
||||
// string-buffer excution
|
||||
void dofile(lua_State *L, const char *filename);
|
||||
void dostring(lua_State *L, const char* buff);
|
||||
void dobuffer(lua_State *L, const char* buff, size_t sz);
|
||||
|
||||
// debug helpers
|
||||
void enum_stack(lua_State *L);
|
||||
int on_error(lua_State *L);
|
||||
void print_error(lua_State *L, const char* fmt, ...);
|
||||
|
||||
// dynamic type extention
|
||||
struct lua_value
|
||||
{
|
||||
virtual void to_lua(lua_State *L) = 0;
|
||||
};
|
||||
|
||||
// type trait
|
||||
template<typename T> struct class_name;
|
||||
struct table;
|
||||
|
||||
template<bool C, typename A, typename B> struct if_ {};
|
||||
template<typename A, typename B> struct if_<true, A, B> { typedef A type; };
|
||||
template<typename A, typename B> struct if_<false, A, B> { typedef B type; };
|
||||
|
||||
template<typename A>
|
||||
struct is_ptr { static const bool value = false; };
|
||||
template<typename A>
|
||||
struct is_ptr<A*> { static const bool value = true; };
|
||||
|
||||
template<typename A>
|
||||
struct is_ref { static const bool value = false; };
|
||||
template<typename A>
|
||||
struct is_ref<A&> { static const bool value = true; };
|
||||
|
||||
template<typename A>
|
||||
struct remove_const { typedef A type; };
|
||||
template<typename A>
|
||||
struct remove_const<const A> { typedef A type; };
|
||||
|
||||
template<typename A>
|
||||
struct base_type { typedef A type; };
|
||||
template<typename A>
|
||||
struct base_type<A*> { typedef A type; };
|
||||
template<typename A>
|
||||
struct base_type<A&> { typedef A type; };
|
||||
|
||||
template<typename A>
|
||||
struct class_type { typedef typename remove_const<typename base_type<A>::type>::type type; };
|
||||
|
||||
template<typename A>
|
||||
struct is_obj { static const bool value = true; };
|
||||
template<> struct is_obj<char> { static const bool value = false; };
|
||||
template<> struct is_obj<unsigned char> { static const bool value = false; };
|
||||
template<> struct is_obj<short> { static const bool value = false; };
|
||||
template<> struct is_obj<unsigned short> { static const bool value = false; };
|
||||
template<> struct is_obj<long> { static const bool value = false; };
|
||||
template<> struct is_obj<unsigned long> { static const bool value = false; };
|
||||
template<> struct is_obj<int> { static const bool value = false; };
|
||||
template<> struct is_obj<unsigned int> { static const bool value = false; };
|
||||
template<> struct is_obj<float> { static const bool value = false; };
|
||||
template<> struct is_obj<double> { static const bool value = false; };
|
||||
template<> struct is_obj<char*> { static const bool value = false; };
|
||||
template<> struct is_obj<const char*> { static const bool value = false; };
|
||||
template<> struct is_obj<bool> { static const bool value = false; };
|
||||
template<> struct is_obj<lua_value*> { static const bool value = false; };
|
||||
template<> struct is_obj<long long> { static const bool value = false; };
|
||||
template<> struct is_obj<unsigned long long> { static const bool value = false; };
|
||||
template<> struct is_obj<table> { static const bool value = false; };
|
||||
|
||||
/////////////////////////////////
|
||||
enum { no = 1, yes = 2 };
|
||||
typedef char (& no_type )[no];
|
||||
typedef char (& yes_type)[yes];
|
||||
|
||||
struct int_conv_type { int_conv_type(int); };
|
||||
|
||||
no_type int_conv_tester (...);
|
||||
yes_type int_conv_tester (int_conv_type);
|
||||
|
||||
no_type vfnd_ptr_tester (const volatile char *);
|
||||
no_type vfnd_ptr_tester (const volatile short *);
|
||||
no_type vfnd_ptr_tester (const volatile int *);
|
||||
no_type vfnd_ptr_tester (const volatile long *);
|
||||
no_type vfnd_ptr_tester (const volatile double *);
|
||||
no_type vfnd_ptr_tester (const volatile float *);
|
||||
no_type vfnd_ptr_tester (const volatile bool *);
|
||||
yes_type vfnd_ptr_tester (const volatile void *);
|
||||
|
||||
template <typename T> T* add_ptr(T&);
|
||||
|
||||
template <bool C> struct bool_to_yesno { typedef no_type type; };
|
||||
template <> struct bool_to_yesno<true> { typedef yes_type type; };
|
||||
|
||||
template <typename T>
|
||||
struct is_enum
|
||||
{
|
||||
static T arg;
|
||||
static const bool value = ( (sizeof(int_conv_tester(arg)) == sizeof(yes_type)) && (sizeof(vfnd_ptr_tester(add_ptr(arg))) == sizeof(yes_type)) );
|
||||
};
|
||||
/////////////////////////////////
|
||||
|
||||
// from lua
|
||||
template<typename T>
|
||||
struct void2val { static T invoke(void* input){ return *(T*)input; } };
|
||||
template<typename T>
|
||||
struct void2ptr { static T* invoke(void* input){ return (T*)input; } };
|
||||
template<typename T>
|
||||
struct void2ref { static T& invoke(void* input){ return *(T*)input; } };
|
||||
|
||||
template<typename T>
|
||||
struct void2type
|
||||
{
|
||||
static T invoke(void* ptr)
|
||||
{
|
||||
return if_<is_ptr<T>::value
|
||||
,void2ptr<typename base_type<T>::type>
|
||||
,typename if_<is_ref<T>::value
|
||||
,void2ref<typename base_type<T>::type>
|
||||
,void2val<typename base_type<T>::type>
|
||||
>::type
|
||||
>::type::invoke(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
struct user
|
||||
{
|
||||
user(void* p) : m_p(p) {}
|
||||
virtual ~user() {}
|
||||
void* m_p;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct user2type { static T invoke(lua_State *L, int index) { return void2type<T>::invoke(lua_touserdata(L, index)); } };
|
||||
|
||||
template<typename T>
|
||||
struct lua2enum { static T invoke(lua_State *L, int index) { return (T)(int)lua_tonumber(L, index); } };
|
||||
|
||||
template<typename T>
|
||||
struct lua2object
|
||||
{
|
||||
static T invoke(lua_State *L, int index)
|
||||
{
|
||||
if(!lua_isuserdata(L,index))
|
||||
{
|
||||
lua_pushstring(L, "no class at first argument. (forgot ':' expression ?)");
|
||||
lua_error(L);
|
||||
}
|
||||
return void2type<T>::invoke(user2type<user*>::invoke(L,index)->m_p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T lua2type(lua_State *L, int index)
|
||||
{
|
||||
return if_<is_enum<T>::value
|
||||
,lua2enum<T>
|
||||
,lua2object<T>
|
||||
>::type::invoke(L, index);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct val2user : user
|
||||
{
|
||||
val2user() : user(new T) {}
|
||||
|
||||
template<typename T1>
|
||||
val2user(T1 t1) : user(new T(t1)) {}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
val2user(T1 t1, T2 t2) : user(new T(t1, t2)) {}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
val2user(T1 t1, T2 t2, T3 t3) : user(new T(t1, t2, t3)) {}
|
||||
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
val2user(T1 t1, T2 t2, T3 t3, T4 t4) : user(new T(t1, t2, t3,t4)) {}
|
||||
|
||||
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
val2user(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) : user(new T(t1, t2, t3,t4,t5)) {}
|
||||
|
||||
~val2user() { delete ((T*)m_p); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ptr2user : user
|
||||
{
|
||||
ptr2user(T* t) : user((void*)t) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ref2user : user
|
||||
{
|
||||
ref2user(T& t) : user(&t) {}
|
||||
};
|
||||
|
||||
// to lua
|
||||
template<typename T>
|
||||
struct val2lua { static void invoke(lua_State *L, T& input){ new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(input); } };
|
||||
template<typename T>
|
||||
struct ptr2lua { static void invoke(lua_State *L, T* input){ if(input) new(lua_newuserdata(L, sizeof(ptr2user<T>))) ptr2user<T>(input); else lua_pushnil(L); } };
|
||||
template<typename T>
|
||||
struct ref2lua { static void invoke(lua_State *L, T& input){ new(lua_newuserdata(L, sizeof(ref2user<T>))) ref2user<T>(input); } };
|
||||
|
||||
template<typename T>
|
||||
struct enum2lua { static void invoke(lua_State *L, T val) { lua_pushnumber(L, (int)val); } };
|
||||
|
||||
template<typename T>
|
||||
struct object2lua
|
||||
{
|
||||
static void invoke(lua_State *L, T val)
|
||||
{
|
||||
if_<is_ptr<T>::value
|
||||
,ptr2lua<typename base_type<T>::type>
|
||||
,typename if_<is_ref<T>::value
|
||||
,ref2lua<typename base_type<T>::type>
|
||||
,val2lua<typename base_type<T>::type>
|
||||
>::type
|
||||
>::type::invoke(L, val);
|
||||
|
||||
push_meta(L, class_name<typename class_type<T>::type>::name());
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void type2lua(lua_State *L, T val)
|
||||
{
|
||||
if_<is_enum<T>::value
|
||||
,enum2lua<T>
|
||||
,object2lua<T>
|
||||
>::type::invoke(L, val);
|
||||
}
|
||||
|
||||
// get value from cclosure
|
||||
template<typename T>
|
||||
T upvalue_(lua_State *L)
|
||||
{
|
||||
return user2type<T>::invoke(L, lua_upvalueindex(1));
|
||||
}
|
||||
|
||||
// read a value from lua stack
|
||||
template<typename T>
|
||||
T read(lua_State *L, int index) { return lua2type<T>(L, index); }
|
||||
|
||||
template<> char* read(lua_State *L, int index);
|
||||
template<> const char* read(lua_State *L, int index);
|
||||
template<> char read(lua_State *L, int index);
|
||||
template<> unsigned char read(lua_State *L, int index);
|
||||
template<> short read(lua_State *L, int index);
|
||||
template<> unsigned short read(lua_State *L, int index);
|
||||
template<> long read(lua_State *L, int index);
|
||||
template<> unsigned long read(lua_State *L, int index);
|
||||
template<> int read(lua_State *L, int index);
|
||||
template<> unsigned int read(lua_State *L, int index);
|
||||
template<> float read(lua_State *L, int index);
|
||||
template<> double read(lua_State *L, int index);
|
||||
template<> bool read(lua_State *L, int index);
|
||||
template<> void read(lua_State *L, int index);
|
||||
template<> long long read(lua_State *L, int index);
|
||||
template<> unsigned long long read(lua_State *L, int index);
|
||||
template<> table read(lua_State *L, int index);
|
||||
|
||||
// push a value to lua stack
|
||||
template<typename T>
|
||||
void push(lua_State *L, T ret) { type2lua<T>(L, ret); }
|
||||
|
||||
template<> void push(lua_State *L, char ret);
|
||||
template<> void push(lua_State *L, unsigned char ret);
|
||||
template<> void push(lua_State *L, short ret);
|
||||
template<> void push(lua_State *L, unsigned short ret);
|
||||
template<> void push(lua_State *L, long ret);
|
||||
template<> void push(lua_State *L, unsigned long ret);
|
||||
template<> void push(lua_State *L, int ret);
|
||||
template<> void push(lua_State *L, unsigned int ret);
|
||||
template<> void push(lua_State *L, float ret);
|
||||
template<> void push(lua_State *L, double ret);
|
||||
template<> void push(lua_State *L, char* ret);
|
||||
template<> void push(lua_State *L, const char* ret);
|
||||
template<> void push(lua_State *L, bool ret);
|
||||
template<> void push(lua_State *L, lua_value* ret);
|
||||
template<> void push(lua_State *L, long long ret);
|
||||
template<> void push(lua_State *L, unsigned long long ret);
|
||||
template<> void push(lua_State *L, table ret);
|
||||
|
||||
// pop a value from lua stack
|
||||
template<typename T>
|
||||
T pop(lua_State *L) { T t = read<T>(L, -1); lua_pop(L, 1); return t; }
|
||||
|
||||
template<> void pop(lua_State *L);
|
||||
template<> table pop(lua_State *L);
|
||||
|
||||
// functor (with return value)
|
||||
template<typename RVal, typename T1=void, typename T2=void, typename T3=void, typename T4=void, typename T5=void>
|
||||
struct functor
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,upvalue_<RVal(*)(T1,T2,T3,T4,T5)>(L)(read<T1>(L,1),read<T2>(L,2),read<T3>(L,3),read<T4>(L,4),read<T5>(L,5))); return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal, typename T1, typename T2, typename T3, typename T4>
|
||||
struct functor<RVal,T1,T2,T3,T4>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,upvalue_<RVal(*)(T1,T2,T3,T4)>(L)(read<T1>(L,1),read<T2>(L,2),read<T3>(L,3),read<T4>(L,4))); return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal, typename T1, typename T2, typename T3>
|
||||
struct functor<RVal,T1,T2,T3>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,upvalue_<RVal(*)(T1,T2,T3)>(L)(read<T1>(L,1),read<T2>(L,2),read<T3>(L,3))); return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal, typename T1, typename T2>
|
||||
struct functor<RVal,T1,T2>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,upvalue_<RVal(*)(T1,T2)>(L)(read<T1>(L,1),read<T2>(L,2))); return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal, typename T1>
|
||||
struct functor<RVal,T1>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,upvalue_<RVal(*)(T1)>(L)(read<T1>(L,1))); return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal>
|
||||
struct functor<RVal>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,upvalue_<RVal(*)()>(L)()); return 1; }
|
||||
};
|
||||
|
||||
// functor (without return value)
|
||||
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
struct functor<void, T1, T2, T3, T4, T5>
|
||||
{
|
||||
static int invoke(lua_State *L) { upvalue_<void(*)(T1,T2,T3,T4,T5)>(L)(read<T1>(L,1),read<T2>(L,2),read<T3>(L,3),read<T4>(L,4),read<T5>(L,5)); return 0; }
|
||||
};
|
||||
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
struct functor<void, T1, T2, T3, T4>
|
||||
{
|
||||
static int invoke(lua_State *L) { upvalue_<void(*)(T1,T2,T3,T4)>(L)(read<T1>(L,1),read<T2>(L,2),read<T3>(L,3),read<T4>(L,4)); return 0; }
|
||||
};
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
struct functor<void, T1, T2, T3>
|
||||
{
|
||||
static int invoke(lua_State *L) { upvalue_<void(*)(T1,T2,T3)>(L)(read<T1>(L,1),read<T2>(L,2),read<T3>(L,3)); return 0; }
|
||||
};
|
||||
|
||||
template<typename T1, typename T2>
|
||||
struct functor<void, T1, T2>
|
||||
{
|
||||
static int invoke(lua_State *L) { upvalue_<void(*)(T1,T2)>(L)(read<T1>(L,1),read<T2>(L,2)); return 0; }
|
||||
};
|
||||
|
||||
template<typename T1>
|
||||
struct functor<void, T1>
|
||||
{
|
||||
static int invoke(lua_State *L) { upvalue_<void(*)(T1)>(L)(read<T1>(L,1)); return 0; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct functor<void>
|
||||
{
|
||||
static int invoke(lua_State *L) { upvalue_<void(*)()>(L)(); return 0; }
|
||||
};
|
||||
|
||||
// functor (non-managed)
|
||||
template<typename T1>
|
||||
struct functor<int, lua_State*, T1>
|
||||
{
|
||||
static int invoke(lua_State *L) { return upvalue_<int(*)(lua_State*,T1)>(L)(L,read<T1>(L,1)); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct functor<int,lua_State*>
|
||||
{
|
||||
static int invoke(lua_State *L) { return upvalue_<int(*)(lua_State*)>(L)(L); }
|
||||
};
|
||||
|
||||
// push_functor
|
||||
template<typename RVal>
|
||||
void push_functor(lua_State *L, RVal (*func)())
|
||||
{
|
||||
lua_pushcclosure(L, functor<RVal>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T1>
|
||||
void push_functor(lua_State *L, RVal (*func)(T1))
|
||||
{
|
||||
lua_pushcclosure(L, functor<RVal,T1>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T1, typename T2>
|
||||
void push_functor(lua_State *L, RVal (*func)(T1,T2))
|
||||
{
|
||||
lua_pushcclosure(L, functor<RVal,T1,T2>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T1, typename T2, typename T3>
|
||||
void push_functor(lua_State *L, RVal (*func)(T1,T2,T3))
|
||||
{
|
||||
lua_pushcclosure(L, functor<RVal,T1,T2,T3>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T1, typename T2, typename T3, typename T4>
|
||||
void push_functor(lua_State *L, RVal (*func)(T1,T2,T3,T4))
|
||||
{
|
||||
lua_pushcclosure(L, functor<RVal,T1,T2,T3,T4>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
void push_functor(lua_State *L, RVal (*func)(T1,T2,T3,T4,T5))
|
||||
{
|
||||
lua_pushcclosure(L, functor<RVal,T1,T2,T3,T4,T5>::invoke, 1);
|
||||
}
|
||||
|
||||
// member variable
|
||||
struct var_base
|
||||
{
|
||||
virtual void get(lua_State *L) = 0;
|
||||
virtual void set(lua_State *L) = 0;
|
||||
};
|
||||
|
||||
template<typename T, typename V>
|
||||
struct mem_var : var_base
|
||||
{
|
||||
V T::*_var;
|
||||
mem_var(V T::*val) : _var(val) {}
|
||||
void get(lua_State *L) { push<if_<is_obj<V>::value,V&,V>::type>(L, read<T*>(L,1)->*(_var)); }
|
||||
void set(lua_State *L) { read<T*>(L,1)->*(_var) = read<V>(L, 3); }
|
||||
};
|
||||
|
||||
// class member functor (with return value)
|
||||
template<typename RVal, typename T, typename T1=void, typename T2=void, typename T3=void, typename T4=void, typename T5=void>
|
||||
struct mem_functor
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,(read<T*>(L,1)->*upvalue_<RVal(T::*)(T1,T2,T3,T4,T5)>(L))(read<T1>(L,2),read<T2>(L,3),read<T3>(L,4),read<T4>(L,5),read<T5>(L,6)));; return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2, typename T3, typename T4>
|
||||
struct mem_functor<RVal,T,T1,T2,T3,T4>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,(read<T*>(L,1)->*upvalue_<RVal(T::*)(T1,T2,T3,T4)>(L))(read<T1>(L,2),read<T2>(L,3),read<T3>(L,4),read<T4>(L,5))); return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2, typename T3>
|
||||
struct mem_functor<RVal,T,T1,T2,T3>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,(read<T*>(L,1)->*upvalue_<RVal(T::*)(T1,T2,T3)>(L))(read<T1>(L,2),read<T2>(L,3),read<T3>(L,4))); return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2>
|
||||
struct mem_functor<RVal,T,T1, T2>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,(read<T*>(L,1)->*upvalue_<RVal(T::*)(T1,T2)>(L))(read<T1>(L,2),read<T2>(L,3))); return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal, typename T, typename T1>
|
||||
struct mem_functor<RVal,T,T1>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,(read<T*>(L,1)->*upvalue_<RVal(T::*)(T1)>(L))(read<T1>(L,2))); return 1; }
|
||||
};
|
||||
|
||||
template<typename RVal, typename T>
|
||||
struct mem_functor<RVal,T>
|
||||
{
|
||||
static int invoke(lua_State *L) { push(L,(read<T*>(L,1)->*upvalue_<RVal(T::*)()>(L))()); return 1; }
|
||||
};
|
||||
|
||||
// class member functor (without return value)
|
||||
template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
struct mem_functor<void,T,T1,T2,T3,T4,T5>
|
||||
{
|
||||
static int invoke(lua_State *L) { (read<T*>(L,1)->*upvalue_<void(T::*)(T1,T2,T3,T4,T5)>(L))(read<T1>(L,2),read<T2>(L,3),read<T3>(L,4),read<T4>(L,5),read<T5>(L,6)); return 0; }
|
||||
};
|
||||
|
||||
template<typename T, typename T1, typename T2, typename T3, typename T4>
|
||||
struct mem_functor<void,T,T1,T2,T3,T4>
|
||||
{
|
||||
static int invoke(lua_State *L) { (read<T*>(L,1)->*upvalue_<void(T::*)(T1,T2,T3,T4)>(L))(read<T1>(L,2),read<T2>(L,3),read<T3>(L,4),read<T4>(L,5)); return 0; }
|
||||
};
|
||||
|
||||
template<typename T, typename T1, typename T2, typename T3>
|
||||
struct mem_functor<void,T,T1,T2,T3>
|
||||
{
|
||||
static int invoke(lua_State *L) { (read<T*>(L,1)->*upvalue_<void(T::*)(T1,T2,T3)>(L))(read<T1>(L,2),read<T2>(L,3),read<T3>(L,4)); return 0; }
|
||||
};
|
||||
|
||||
template<typename T, typename T1, typename T2>
|
||||
struct mem_functor<void,T,T1,T2>
|
||||
{
|
||||
static int invoke(lua_State *L) { (read<T*>(L,1)->*upvalue_<void(T::*)(T1,T2)>(L))(read<T1>(L,2),read<T2>(L,3)); return 0; }
|
||||
};
|
||||
|
||||
template<typename T, typename T1>
|
||||
struct mem_functor<void,T,T1>
|
||||
{
|
||||
static int invoke(lua_State *L) { (read<T*>(L,1)->*upvalue_<void(T::*)(T1)>(L))(read<T1>(L,2)); return 0; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct mem_functor<void,T>
|
||||
{
|
||||
static int invoke(lua_State *L) { (read<T*>(L,1)->*upvalue_<void(T::*)()>(L))(); return 0; }
|
||||
};
|
||||
|
||||
// class member functor (non-managed)
|
||||
template<typename T, typename T1>
|
||||
struct mem_functor<int,T,lua_State*,T1>
|
||||
{
|
||||
static int invoke(lua_State *L) { return (read<T*>(L,1)->*upvalue_<int(T::*)(lua_State*,T1)>(L))(L, read<T1>(L,2)); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct mem_functor<int,T,lua_State*>
|
||||
{
|
||||
static int invoke(lua_State *L) { return (read<T*>(L,1)->*upvalue_<int(T::*)(lua_State*)>(L))(L); }
|
||||
};
|
||||
|
||||
// push_functor
|
||||
template<typename RVal, typename T>
|
||||
void push_functor(lua_State *L, RVal (T::*func)())
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T>
|
||||
void push_functor(lua_State *L, RVal (T::*func)() const)
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1))
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1) const)
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1,T2))
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1,T2>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1,T2) const)
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1,T2>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2, typename T3>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1,T2,T3))
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1,T2,T3>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2, typename T3>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1,T2,T3) const)
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1,T2,T3>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2, typename T3, typename T4>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1,T2,T3,T4))
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1,T2,T3,T4>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2, typename T3, typename T4>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1,T2,T3,T4) const)
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1,T2,T3,T4>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1,T2,T3,T4,T5))
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1,T2,T3,T4,T5>::invoke, 1);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
void push_functor(lua_State *L, RVal (T::*func)(T1,T2,T3,T4,T5) const)
|
||||
{
|
||||
lua_pushcclosure(L, mem_functor<RVal,T,T1,T2,T3,T4,T5>::invoke, 1);
|
||||
}
|
||||
|
||||
// constructor
|
||||
template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
int constructor(lua_State *L)
|
||||
{
|
||||
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(read<T1>(L,2),read<T2>(L,3),read<T3>(L,4),read<T4>(L,5),read<T5>(L,6));
|
||||
push_meta(L, class_name<typename class_type<T>::type>::name());
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T, typename T1, typename T2, typename T3, typename T4>
|
||||
int constructor(lua_State *L)
|
||||
{
|
||||
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(read<T1>(L,2),read<T2>(L,3),read<T3>(L,4),read<T4>(L,5));
|
||||
push_meta(L, class_name<typename class_type<T>::type>::name());
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T, typename T1, typename T2, typename T3>
|
||||
int constructor(lua_State *L)
|
||||
{
|
||||
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(read<T1>(L,2),read<T2>(L,3),read<T3>(L,4));
|
||||
push_meta(L, class_name<typename class_type<T>::type>::name());
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T, typename T1, typename T2>
|
||||
int constructor(lua_State *L)
|
||||
{
|
||||
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(read<T1>(L,2),read<T2>(L,3));
|
||||
push_meta(L, class_name<typename class_type<T>::type>::name());
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T, typename T1>
|
||||
int constructor(lua_State *L)
|
||||
{
|
||||
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(read<T1>(L,2));
|
||||
push_meta(L, class_name<typename class_type<T>::type>::name());
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int constructor(lua_State *L)
|
||||
{
|
||||
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>();
|
||||
push_meta(L, class_name<typename class_type<T>::type>::name());
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// destroyer
|
||||
template<typename T>
|
||||
int destroyer(lua_State *L)
|
||||
{
|
||||
((user*)lua_touserdata(L, 1))->~user();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// global function
|
||||
template<typename F>
|
||||
void def(lua_State* L, const char* name, F func)
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
lua_pushlightuserdata(L, (void*)func);
|
||||
push_functor(L, func);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
|
||||
// global variable
|
||||
template<typename T>
|
||||
void set(lua_State* L, const char* name, T object)
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
push(L, object);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get(lua_State* L, const char* name)
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
return pop<T>(L);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void decl(lua_State* L, const char* name, T object)
|
||||
{
|
||||
set(L, name, object);
|
||||
}
|
||||
|
||||
// call
|
||||
template<typename RVal>
|
||||
RVal call(lua_State* L, const char* name)
|
||||
{
|
||||
lua_pushcclosure(L, on_error, 0);
|
||||
int errfunc = lua_gettop(L);
|
||||
|
||||
lua_pushstring(L, name);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
|
||||
if(lua_isfunction(L,-1))
|
||||
{
|
||||
lua_pcall(L, 0, 1, errfunc);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error(L, "lua_tinker::call() attempt to call global `%s' (not a function)", name);
|
||||
}
|
||||
|
||||
lua_remove(L, errfunc);
|
||||
return pop<RVal>(L);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T1>
|
||||
RVal call(lua_State* L, const char* name, T1 arg)
|
||||
{
|
||||
lua_pushcclosure(L, on_error, 0);
|
||||
int errfunc = lua_gettop(L);
|
||||
|
||||
lua_pushstring(L, name);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
if(lua_isfunction(L,-1))
|
||||
{
|
||||
push(L, arg);
|
||||
lua_pcall(L, 1, 1, errfunc);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error(L, "lua_tinker::call() attempt to call global `%s' (not a function)", name);
|
||||
}
|
||||
|
||||
lua_remove(L, errfunc);
|
||||
return pop<RVal>(L);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T1, typename T2>
|
||||
RVal call(lua_State* L, const char* name, T1 arg1, T2 arg2)
|
||||
{
|
||||
lua_pushcclosure(L, on_error, 0);
|
||||
int errfunc = lua_gettop(L);
|
||||
|
||||
lua_pushstring(L, name);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
if(lua_isfunction(L,-1))
|
||||
{
|
||||
push(L, arg1);
|
||||
push(L, arg2);
|
||||
lua_pcall(L, 2, 1, errfunc);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error(L, "lua_tinker::call() attempt to call global `%s' (not a function)", name);
|
||||
}
|
||||
|
||||
lua_remove(L, errfunc);
|
||||
return pop<RVal>(L);
|
||||
}
|
||||
|
||||
template<typename RVal, typename T1, typename T2, typename T3>
|
||||
RVal call(lua_State* L, const char* name, T1 arg1, T2 arg2, T3 arg3)
|
||||
{
|
||||
lua_pushcclosure(L, on_error, 0);
|
||||
int errfunc = lua_gettop(L);
|
||||
|
||||
lua_pushstring(L, name);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
if(lua_isfunction(L,-1))
|
||||
{
|
||||
push(L, arg1);
|
||||
push(L, arg2);
|
||||
push(L, arg3);
|
||||
lua_pcall(L, 3, 1, errfunc);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error(L, "lua_tinker::call() attempt to call global `%s' (not a function)", name);
|
||||
}
|
||||
|
||||
lua_remove(L, errfunc);
|
||||
return pop<RVal>(L);
|
||||
}
|
||||
|
||||
// class helper
|
||||
int meta_get(lua_State *L);
|
||||
int meta_set(lua_State *L);
|
||||
void push_meta(lua_State *L, const char* name);
|
||||
|
||||
// class init
|
||||
template<typename T>
|
||||
void class_add(lua_State* L, const char* name)
|
||||
{
|
||||
class_name<T>::name(name);
|
||||
|
||||
lua_pushstring(L, name);
|
||||
lua_newtable(L);
|
||||
|
||||
lua_pushstring(L, "__name");
|
||||
lua_pushstring(L, name);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__index");
|
||||
lua_pushcclosure(L, meta_get, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__newindex");
|
||||
lua_pushcclosure(L, meta_set, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "__gc");
|
||||
lua_pushcclosure(L, destroyer<T>, 0);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
|
||||
// Tinker Class Inheritence
|
||||
template<typename T, typename P>
|
||||
void class_inh(lua_State* L)
|
||||
{
|
||||
push_meta(L, class_name<T>::name());
|
||||
if(lua_istable(L, -1))
|
||||
{
|
||||
lua_pushstring(L, "__parent");
|
||||
push_meta(L, class_name<P>::name());
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// Tinker Class Constructor
|
||||
template<typename T, typename F>
|
||||
void class_con(lua_State* L,F func)
|
||||
{
|
||||
push_meta(L, class_name<T>::name());
|
||||
if(lua_istable(L, -1))
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "__call");
|
||||
lua_pushcclosure(L, func, 0);
|
||||
lua_rawset(L, -3);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// Tinker Class Functions
|
||||
template<typename T, typename F>
|
||||
void class_def(lua_State* L, const char* name, F func)
|
||||
{
|
||||
push_meta(L, class_name<T>::name());
|
||||
if(lua_istable(L, -1))
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
new(lua_newuserdata(L,sizeof(F))) F(func);
|
||||
push_functor(L, func);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// Tinker Class Variables
|
||||
template<typename T, typename BASE, typename VAR>
|
||||
void class_mem(lua_State* L, const char* name, VAR BASE::*val)
|
||||
{
|
||||
push_meta(L, class_name<T>::name());
|
||||
if(lua_istable(L, -1))
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
new(lua_newuserdata(L,sizeof(mem_var<BASE,VAR>))) mem_var<BASE,VAR>(val);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct class_name
|
||||
{
|
||||
// global name
|
||||
static const char* name(const char* name = NULL)
|
||||
{
|
||||
static char temp[256] = "";
|
||||
if(name) strcpy_s(temp, name);
|
||||
return temp;
|
||||
}
|
||||
};
|
||||
|
||||
// Table Object on Stack
|
||||
struct table_obj
|
||||
{
|
||||
table_obj(lua_State* L, int index);
|
||||
~table_obj();
|
||||
|
||||
void inc_ref();
|
||||
void dec_ref();
|
||||
|
||||
bool validate();
|
||||
|
||||
template<typename T>
|
||||
void set(const char* name, T object)
|
||||
{
|
||||
if(validate())
|
||||
{
|
||||
lua_pushstring(m_L, name);
|
||||
push(m_L, object);
|
||||
lua_settable(m_L, m_index);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get(const char* name)
|
||||
{
|
||||
if(validate())
|
||||
{
|
||||
lua_pushstring(m_L, name);
|
||||
lua_gettable(m_L, m_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushnil(m_L);
|
||||
}
|
||||
|
||||
return pop<T>(m_L);
|
||||
}
|
||||
|
||||
lua_State* m_L;
|
||||
int m_index;
|
||||
const void* m_pointer;
|
||||
int m_ref;
|
||||
};
|
||||
|
||||
// Table Object Holder
|
||||
struct table
|
||||
{
|
||||
table(lua_State* L);
|
||||
table(lua_State* L, int index);
|
||||
table(lua_State* L, const char* name);
|
||||
table(const table& input);
|
||||
~table();
|
||||
|
||||
template<typename T>
|
||||
void set(const char* name, T object)
|
||||
{
|
||||
m_obj->set(name, object);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get(const char* name)
|
||||
{
|
||||
return m_obj->get<T>(name);
|
||||
}
|
||||
|
||||
table_obj* m_obj;
|
||||
};
|
||||
|
||||
} // namespace lua_tinker
|
||||
|
||||
#endif //_LUA_TINKER_H_
|
||||
Reference in New Issue
Block a user