From dba6ba812fadfef61e7adf61ff2a65e03ed36789 Mon Sep 17 00:00:00 2001 From: MikalaiR Date: Fri, 1 Jul 2016 07:43:28 +0000 Subject: MirLua: mlua_metatable rewritted git-svn-id: http://svn.miranda-ng.org/main/trunk@17055 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MirLua/src/mlua_metatable.h | 155 ++++++++++++++++++++++++++---------- 1 file changed, 112 insertions(+), 43 deletions(-) (limited to 'plugins/MirLua/src/mlua_metatable.h') diff --git a/plugins/MirLua/src/mlua_metatable.h b/plugins/MirLua/src/mlua_metatable.h index 1b28285e96..103c8b95d1 100644 --- a/plugins/MirLua/src/mlua_metatable.h +++ b/plugins/MirLua/src/mlua_metatable.h @@ -1,51 +1,73 @@ #ifndef _LUA_METATABLE_H_ #define _LUA_METATABLE_H_ +#include #include #define LUA_TINTEGER LUA_NUMTAGS + 1 #define LUA_TSTRINGA LUA_NUMTAGS + 2 #define LUA_TSTRINGW LUA_NUMTAGS + 3 -template -class MTField : public MZeroedObject +union MTFieldVal { -private: - enum MTFieldGetter - { - MTFG_LAMBDA = 1, - MTFG_OFFSET = 2 - }; + void *userdata; + int boolean; + lua_Integer integer; + lua_Number number; + const char *string; + const char *stringA; + const wchar_t *stringW; +}; + +struct MTField +{ + int lua_type; + MTFieldVal val; +}; - size_t offset; - size_t size; - int type; - int getterType; - std::function lambda; +class CMTField +{ +public: + virtual MTField GetValue(void *obj) = 0; + virtual ~CMTField(){}; +}; +template +class CMTFieldOffset : public CMTField +{ + int lua_type; + ptrdiff_t offset; + size_t size; public: - MTField(size_t offset, size_t size, int type) - : offset(offset), size(size), type(type), getterType(MTFG_OFFSET) { } + CMTFieldOffset(ptrdiff_t off, size_t s, int type) : offset(off), lua_type(type), size(s) {} + virtual MTField GetValue(void *obj) + { + MTField fd = { lua_type }; + //fd.val = *(Ret*)((char*)obj + offset); + memcpy(&fd.val, ((char*)obj + offset), sizeof(Ret)); + return fd; + } +}; - MTField(std::function f, int type) - : lambda(f), type(type), getterType(MTFG_LAMBDA) { } +template +class CMTFieldLambda : public CMTField +{ + int lua_type; + std::function lambda; +public: - int GetType() const { return type; } + CMTFieldLambda(decltype(lambda) f, int type) : lambda(f), lua_type(type) {} - template - R GetValue(T *obj) const + virtual MTField GetValue(void *obj) { - if (getterType == MTFG_LAMBDA) return (R)lambda(obj); - else - { - R res = NULL; - memcpy(&res, ((char*)obj) + offset, size); - return res; - } + MTField tmp = { lua_type }; + tmp.val = lambda((Obj*)obj); + return tmp; } }; + template class MT { @@ -53,7 +75,7 @@ private: lua_State *L; static const char *name; - static std::map*> fields; + static std::map fields; static void Init(lua_State *L, T **obj) { @@ -116,30 +138,30 @@ private: return Index(L, obj); } - MTField *field = it->second; + MTField fieldVal = it->second->GetValue(obj); - switch (field->GetType()) + switch (fieldVal.lua_type) { case LUA_TBOOLEAN: - lua_pushboolean(L, field->GetValue(obj)); + lua_pushboolean(L, fieldVal.val.boolean); break; case LUA_TINTEGER: - lua_pushinteger(L, field->GetValue(obj)); + lua_pushinteger(L, fieldVal.val.integer); break; case LUA_TNUMBER: - lua_pushnumber(L, field->GetValue(obj)); + lua_pushnumber(L, fieldVal.val.number); break; case LUA_TSTRING: - lua_pushstring(L, field->GetValue(obj)); + lua_pushstring(L, fieldVal.val.string); break; case LUA_TSTRINGA: - lua_pushstring(L, ptrA(mir_utf8encode(field->GetValue(obj)))); + lua_pushstring(L, ptrA(mir_utf8encode(fieldVal.val.stringA))); break; case LUA_TSTRINGW: - lua_pushstring(L, T2Utf(field->GetValue(obj))); + lua_pushstring(L, T2Utf(fieldVal.val.stringW)); break; case LUA_TLIGHTUSERDATA: - lua_pushlightuserdata(L, field->GetValue(obj)); + lua_pushlightuserdata(L, fieldVal.val.userdata); break; default: lua_pushnil(L); @@ -147,7 +169,6 @@ private: return 1; } - static int lua__gc(lua_State *L) { T **obj = (T**)luaL_checkudata(L, 1, MT::name); @@ -156,6 +177,52 @@ private: return 0; } + static int lua__tostring(lua_State *L) + { + T *obj = *(T**)luaL_checkudata(L, 1, MT::name); + CMStringA data(MT::name); + data += "("; + + + for (auto it = fields.begin(); it != fields.end(); ++it) + { + data += it->first.c_str(); + data += "="; + MTField fieldVal = it->second->GetValue(obj); + + switch (fieldVal.lua_type) + { + case LUA_TBOOLEAN: + data.Append(fieldVal.val.boolean == 0 ? "false" : "true"); + break; + case LUA_TINTEGER: + data.AppendFormat("%d", fieldVal.val.integer); + break; + case LUA_TNUMBER: + data.AppendFormat("%f", fieldVal.val.number); + break; + case LUA_TSTRING: + data.Append(fieldVal.val.string); + break; + case LUA_TSTRINGA: + data.Append(ptrA(mir_utf8encode(fieldVal.val.stringA))); + break; + case LUA_TSTRINGW: + data.Append(T2Utf(fieldVal.val.stringW)); + break; + case LUA_TLIGHTUSERDATA: + data.AppendFormat("(0x%p)", fieldVal.val.userdata); + break; + default: + data.Append("nil"); + } + data += ", "; + } + data += ")"; + lua_pushstring(L, data.c_str()); + return 1; + } + public: MT(lua_State *L, const char *tname) : L(L) { @@ -170,6 +237,8 @@ public: lua_setfield(L, -2, "__bnot"); lua_pushcfunction(L, lua__gc); lua_setfield(L, -2, "__gc"); + lua_pushcfunction(L, lua__tostring); + lua_setfield(L, -2, "__tostring"); lua_pop(L, 1); lua_createtable(L, 0, 1); @@ -182,13 +251,13 @@ public: } template - MT& Field(R T::*M, const char *name, int type, size_t size = 0) + MT& Field(R T:: *M, const char *name, int type, size_t size = 0) { if (size == 0) size = sizeof(M); - size_t offset = offsetof(T, *M); + size_t offset = (size_t)(&(((T*)0)->*M)); if (type != LUA_TNONE) - fields[name] = new MTField(offset, size, type); + fields[name] = new CMTFieldOffset(offset, size, type); return *this; } @@ -196,7 +265,7 @@ public: MT& Field(const L &f, const char *name, int type) { if (type != LUA_TNONE) - fields[name] = new MTField(f, type); + fields[name] = new CMTFieldLambda(f, type); return *this; } @@ -218,6 +287,6 @@ template const char *MT::name; template -std::map*> MT::fields; +std::map MT::fields; #endif //_LUA_METATABLE_H_ -- cgit v1.2.3