Skip to content

Commit

Permalink
Merge branch 'hchunhui:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
shewer authored Jul 24, 2022
2 parents 052f028 + 43877c6 commit a13205d
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 49 deletions.
8 changes: 4 additions & 4 deletions src/lib/lua.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,16 +265,16 @@ std::shared_ptr<LuaObj> LuaObj::todata(lua_State *L, int i) {
}

void export_type(lua_State *L,
const char *name, lua_CFunction gc,
const LuaTypeInfo *type, lua_CFunction gc,
const luaL_Reg *funcs, const luaL_Reg *methods,
const luaL_Reg *vars_get, const luaL_Reg *vars_set) {
for (int i = 0; funcs[i].name; i++) {
lua_register(L, funcs[i].name, funcs[i].func);
}

luaL_newmetatable(L, name);
lua_pushstring(L, name);
lua_setfield(L, -2, "name");
luaL_newmetatable(L, type->name());
lua_pushlightuserdata(L, (void *) type);
lua_setfield(L, -2, "type");
if (gc) {
lua_pushcfunction(L, gc);
lua_setfield(L, -2, "__gc");
Expand Down
90 changes: 55 additions & 35 deletions src/lib/lua_templates.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,36 @@ class LUAWRAPPER_LOCAL C_State {
}
};

struct LUAWRAPPER_LOCAL LuaTypeInfo {
const std::type_info *ti;
size_t hash;

template<typename T>
static const LuaTypeInfo &make() {
auto &i = typeid(T);
static LuaTypeInfo r = {&i, i.hash_code()};
return r;
}

const char *name() const {
return ti->name();
}

bool operator==(const LuaTypeInfo &o) const {
return hash == o.hash && *ti == *o.ti;
}
};

//--- LuaType
// Generic case (includes pointers)
template<typename T>
struct LUAWRAPPER_LOCAL LuaType {
static const char *name() {
return typeid(LuaType<T>).name();
static const LuaTypeInfo *type() {
return &LuaTypeInfo::make<LuaType<T>>();
}

static int gc(lua_State *L) {
T *o = (T *) luaL_checkudata(L, 1, name());
T *o = (T *) luaL_checkudata(L, 1, type()->name());
o->~T();
return 0;
}
Expand Down Expand Up @@ -100,14 +120,14 @@ struct LUAWRAPPER_LOCAL LuaType {

void *u = lua_newuserdata(L, sizeof(T));
new(u) T(o);
luaL_getmetatable(L, name());
luaL_getmetatable(L, type()->name());
if (lua_isnil(L, -1)) {
// If T is not registered,
// registers a "__gc" to prevent memory leaks.
lua_pop(L, 1);
luaL_newmetatable(L, name());
lua_pushstring(L, name());
lua_setfield(L, -2, "name");
luaL_newmetatable(L, type()->name());
lua_pushlightuserdata(L, (void *) type());
lua_setfield(L, -2, "type");
lua_pushcfunction(L, gc);
lua_setfield(L, -2, "__gc");
}
Expand All @@ -118,11 +138,11 @@ struct LUAWRAPPER_LOCAL LuaType {
typedef typename std::remove_const<T>::type U;

if (lua_getmetatable(L, i)) {
lua_getfield(L, -1, "name");
const char *tname = luaL_checkstring(L, -1);
lua_getfield(L, -1, "type");
auto ttype = (const LuaTypeInfo *) lua_touserdata(L, -1);
void *_p = lua_touserdata(L, i);
if (strcmp(tname, name()) == 0 ||
strcmp(tname, LuaType<U>::name()) == 0) {
if (*ttype == *type() ||
*ttype == *LuaType<U>::type()) {
auto o = (T *) _p;
lua_pop(L, 2);
return *o;
Expand All @@ -131,7 +151,7 @@ struct LUAWRAPPER_LOCAL LuaType {
lua_pop(L, 2);
}

const char *msg = lua_pushfstring(L, "%s expected", name());
const char *msg = lua_pushfstring(L, "%s expected", type()->name());
luaL_argerror(L, i, msg);
abort(); // unreachable
}
Expand All @@ -140,53 +160,53 @@ struct LUAWRAPPER_LOCAL LuaType {
// References
template<typename T>
struct LuaType<T &> {
static const char *name() {
return typeid(LuaType<T &>).name();
static const LuaTypeInfo *type() {
return &LuaTypeInfo::make<LuaType<T &>>();
}

static void pushdata(lua_State *L, T &o) {
T **u = (T**) lua_newuserdata(L, sizeof(T *));
*u = std::addressof(o);
luaL_setmetatable(L, name());
luaL_setmetatable(L, type()->name());
}

static T &todata(lua_State *L, int i, C_State * = NULL) {
typedef typename std::remove_const<T>::type U;

if (lua_getmetatable(L, i)) {
lua_getfield(L, -1, "name");
const char *tname = luaL_checkstring(L, -1);
lua_getfield(L, -1, "type");
auto ttype = (const LuaTypeInfo *) lua_touserdata(L, -1);
void *_p = lua_touserdata(L, i);
if (strcmp(tname, name()) == 0 ||
strcmp(tname, LuaType<U &>::name()) == 0) {
if (*ttype == *type() ||
*ttype == *LuaType<U &>::type()) {
auto po = (T **) _p;
lua_pop(L, 2);
return **po;
}

if (strcmp(tname, LuaType<std::shared_ptr<T>>::name()) == 0 ||
strcmp(tname, LuaType<std::shared_ptr<U>>::name()) == 0) {
if (*ttype == *LuaType<std::shared_ptr<T>>::type() ||
*ttype == *LuaType<std::shared_ptr<U>>::type()) {
auto ao = (std::shared_ptr<T> *) _p;
lua_pop(L, 2);
return *(*ao).get();
}

if (strcmp(tname, LuaType<std::unique_ptr<T>>::name()) == 0 ||
strcmp(tname, LuaType<std::unique_ptr<U>>::name()) == 0) {
if (*ttype == *LuaType<std::unique_ptr<T>>::type() ||
*ttype == *LuaType<std::unique_ptr<U>>::type()) {
auto ao = (std::unique_ptr<T> *) _p;
lua_pop(L, 2);
return *(*ao).get();
}

if (strcmp(tname, LuaType<T *>::name()) == 0 ||
strcmp(tname, LuaType<U *>::name()) == 0) {
if (*ttype == *LuaType<T *>::type() ||
*ttype == *LuaType<U *>::type()) {
auto p = (T **) _p;
lua_pop(L, 2);
return **p;
}

if (strcmp(tname, LuaType<T>::name()) == 0 ||
strcmp(tname, LuaType<U>::name()) == 0) {
if (*ttype == *LuaType<T>::type() ||
*ttype == *LuaType<U>::type()) {
auto o = (T *) _p;
lua_pop(L, 2);
return *o;
Expand All @@ -195,7 +215,7 @@ struct LuaType<T &> {
lua_pop(L, 2);
}

const char *msg = lua_pushfstring(L, "%s expected", name());
const char *msg = lua_pushfstring(L, "%s expected", type()->name());
luaL_argerror(L, i, msg);
abort(); // unreachable
}
Expand All @@ -205,27 +225,27 @@ template<typename T>
struct LuaType<std::unique_ptr<T>> {
using UT = std::unique_ptr<T>;

static const char *name() {
return typeid(LuaType<UT>).name();
static const LuaTypeInfo *type() {
return &LuaTypeInfo::make<LuaType<UT>>();
}

static int gc(lua_State *L) {
UT *o = (UT *) luaL_checkudata(L, 1, name());
UT *o = (UT *) luaL_checkudata(L, 1, type()->name());
o->~UT();
return 0;
}

static void pushdata(lua_State *L, UT &o) {
void *u = lua_newuserdata(L, sizeof(UT));
new(u) UT(std::move(o));
luaL_getmetatable(L, name());
luaL_getmetatable(L, type()->name());
if (lua_isnil(L, -1)) {
// If T is not registered,
// registers a "__gc" to prevent memory leaks.
lua_pop(L, 1);
luaL_newmetatable(L, name());
lua_pushstring(L, name());
lua_setfield(L, -2, "name");
luaL_newmetatable(L, type()->name());
lua_pushlightuserdata(L, (void *) type());
lua_setfield(L, -2, "type");
lua_pushcfunction(L, gc);
lua_setfield(L, -2, "__gc");
}
Expand Down
20 changes: 10 additions & 10 deletions src/types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1657,26 +1657,26 @@ namespace OpenccReg{
//--- Lua
#define EXPORT(ns, L) \
do { \
export_type(L, LuaType<ns::T>::name(), LuaType<ns::T>::gc, \
export_type(L, LuaType<ns::T>::type(), LuaType<ns::T>::gc, \
ns::funcs, ns::methods, ns::vars_get, ns::vars_set); \
export_type(L, LuaType<ns::T &>::name(), NULL, \
export_type(L, LuaType<ns::T &>::type(), NULL, \
ns::funcs, ns::methods, ns::vars_get, ns::vars_set); \
export_type(L, LuaType<const ns::T>::name(), LuaType<ns::T>::gc, \
export_type(L, LuaType<const ns::T>::type(), LuaType<ns::T>::gc, \
ns::funcs, ns::methods, ns::vars_get, ns::vars_set); \
export_type(L, LuaType<const ns::T &>::name(), NULL, \
export_type(L, LuaType<const ns::T &>::type(), NULL, \
ns::funcs, ns::methods, ns::vars_get, ns::vars_set); \
export_type(L, LuaType<an<ns::T>>::name(), LuaType<an<ns::T>>::gc, \
export_type(L, LuaType<an<ns::T>>::type(), LuaType<an<ns::T>>::gc, \
ns::funcs, ns::methods, ns::vars_get, ns::vars_set); \
export_type(L, LuaType<an<const ns::T>>::name(), LuaType<an<const ns::T>>::gc, \
export_type(L, LuaType<an<const ns::T>>::type(), LuaType<an<const ns::T>>::gc, \
ns::funcs, ns::methods, ns::vars_get, ns::vars_set); \
export_type(L, LuaType<ns::T *>::name(), NULL, \
export_type(L, LuaType<ns::T *>::type(), NULL, \
ns::funcs, ns::methods, ns::vars_get, ns::vars_set); \
export_type(L, LuaType<const ns::T *>::name(), NULL, \
export_type(L, LuaType<const ns::T *>::type(), NULL, \
ns::funcs, ns::methods, ns::vars_get, ns::vars_set); \
} while (0)

void export_type(lua_State *L,
const char *name, lua_CFunction gc,
const LuaTypeInfo *type, lua_CFunction gc,
const luaL_Reg *funcs, const luaL_Reg *methods,
const luaL_Reg *vars_get, const luaL_Reg *vars_set);

Expand Down Expand Up @@ -1718,6 +1718,6 @@ void types_init(lua_State *L) {
EXPORT_TYPES_EXT(L);
#endif

export_type(L, LuaType<the<SchemaReg::T>>::name(), LuaType<the<SchemaReg::T>>::gc,
export_type(L, LuaType<the<SchemaReg::T>>::type(), LuaType<the<SchemaReg::T>>::gc,
SchemaReg::funcs, SchemaReg::methods, SchemaReg::vars_get, SchemaReg::vars_set);
}

0 comments on commit a13205d

Please sign in to comment.