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/m_chat.cpp | 1 + plugins/MirLua/src/m_database.cpp | 4 + plugins/MirLua/src/m_options.cpp | 2 +- plugins/MirLua/src/m_protocols.cpp | 4 +- plugins/MirLua/src/mlua_metatable.h | 155 ++++++++++++++++++++++++++---------- plugins/MirLua/src/mlua_utils.cpp | 13 +-- 6 files changed, 127 insertions(+), 52 deletions(-) (limited to 'plugins') diff --git a/plugins/MirLua/src/m_chat.cpp b/plugins/MirLua/src/m_chat.cpp index dfe8b3c54d..dbecbc774e 100644 --- a/plugins/MirLua/src/m_chat.cpp +++ b/plugins/MirLua/src/m_chat.cpp @@ -5,6 +5,7 @@ static luaL_Reg chatApi[] = { NULL, NULL } }; +template <> int MT::Index(lua_State *L, GCEVENT *gce) { const char *key = lua_tostring(L, 2); diff --git a/plugins/MirLua/src/m_database.cpp b/plugins/MirLua/src/m_database.cpp index b9318c1047..fab5f86d57 100644 --- a/plugins/MirLua/src/m_database.cpp +++ b/plugins/MirLua/src/m_database.cpp @@ -589,6 +589,7 @@ static luaL_Reg databaseApi[] = #define MT_DBCONTACTWRITESETTING "DBCONTACTWRITESETTING" +template <> int MT::Index(lua_State *L, DBCONTACTWRITESETTING *dbcw) { const char *key = luaL_checkstring(L, 2); @@ -639,6 +640,7 @@ int MT::Index(lua_State *L, DBCONTACTWRITESETTING *dbcw) #define MT_DBEVENTINFO "DBEVENTINFO" +template <> void MT::Init(lua_State *L, DBEVENTINFO **dbei) { MEVENT hDbEvent = luaL_checkinteger(L, 1); @@ -650,6 +652,7 @@ void MT::Init(lua_State *L, DBEVENTINFO **dbei) db_event_get((MEVENT)hDbEvent, (*dbei)); } +template <> int MT::Index(lua_State *L, DBEVENTINFO *dbei) { const char *key = luaL_checkstring(L, 2); @@ -669,6 +672,7 @@ int MT::Index(lua_State *L, DBEVENTINFO *dbei) return 1; } +template <> void MT::Free(lua_State*, DBEVENTINFO **dbei) { mir_free((*dbei)->pBlob); diff --git a/plugins/MirLua/src/m_options.cpp b/plugins/MirLua/src/m_options.cpp index 37f1d27b22..6d7ec23d2e 100644 --- a/plugins/MirLua/src/m_options.cpp +++ b/plugins/MirLua/src/m_options.cpp @@ -34,7 +34,7 @@ public: } } - void OnDestroy() + void OnDestroy() override { lua_pushnil(L); lua_rawsetp(L, LUA_REGISTRYINDEX, this); diff --git a/plugins/MirLua/src/m_protocols.cpp b/plugins/MirLua/src/m_protocols.cpp index 354a65daf5..423d732c32 100644 --- a/plugins/MirLua/src/m_protocols.cpp +++ b/plugins/MirLua/src/m_protocols.cpp @@ -233,8 +233,8 @@ LUAMOD_API int luaopen_m_protocols(lua_State *L) MT(L, "CCSDATA") .Field(&CCSDATA::hContact, "hContact", LUA_TINTEGER) .Field(&CCSDATA::szProtoService, "Service", LUA_TSTRINGA) - .Field([](CCSDATA *ccd) { return (void*)ccd->wParam; }, "wParam", LUA_TLIGHTUSERDATA) - .Field([](CCSDATA *ccd) { return (void*)ccd->lParam; }, "lParam", LUA_TLIGHTUSERDATA); + .Field([](CCSDATA *ccd) -> MTFieldVal { MTFieldVal tmp; tmp.userdata = (void*)ccd->wParam; return tmp; }, "wParam", LUA_TLIGHTUSERDATA) + .Field([](CCSDATA *ccd) -> MTFieldVal { MTFieldVal tmp; tmp.userdata = (void*)ccd->lParam; return tmp; }, "lParam", LUA_TLIGHTUSERDATA); MT(L, "PROTORECVEVENT") .Field(&PROTORECVEVENT::timestamp, "Timestamp", LUA_TINTEGER) 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_ diff --git a/plugins/MirLua/src/mlua_utils.cpp b/plugins/MirLua/src/mlua_utils.cpp index 6ee3f44186..ec08831a1d 100644 --- a/plugins/MirLua/src/mlua_utils.cpp +++ b/plugins/MirLua/src/mlua_utils.cpp @@ -79,22 +79,23 @@ int luaM_print(lua_State *L) switch (lua_type(L, i)) { case LUA_TNIL: - data.Append("nil "); + data.Append("nil"); break; case LUA_TBOOLEAN: - data.AppendFormat("%s ", lua_toboolean(L, i) ? "true" : "false"); + data.AppendFormat("%s", lua_toboolean(L, i) ? "true" : "false"); break; case LUA_TNUMBER: case LUA_TSTRING: - data.AppendFormat("%s ", lua_tostring(L, i)); + data.AppendFormat("%s", lua_tostring(L, i)); break; default: - data.AppendFormat("%s(0x%p) ", luaL_typename(L, i), lua_topointer(L, i)); + data.AppendFormat("%s(0x%p)", luaL_typename(L, i), lua_topointer(L, i)); break; } + data += '\t'; } - if (data.GetLength() >= 3) - data.Delete(data.GetLength() - 3, 3); + if (data.GetLength() >= 1) + data.Delete(data.GetLength() - 1, 1); Log(data.GetBuffer()); -- cgit v1.2.3