From e29fd4d0ead4353ff2e03fcd793400d8e0779481 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sat, 7 Nov 2015 18:42:19 +0000 Subject: MirLua: added metatables wrapper git-svn-id: http://svn.miranda-ng.org/main/trunk@15697 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MirLua/src/mlua_metatable.h | 155 ++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 plugins/MirLua/src/mlua_metatable.h (limited to 'plugins/MirLua/src/mlua_metatable.h') diff --git a/plugins/MirLua/src/mlua_metatable.h b/plugins/MirLua/src/mlua_metatable.h new file mode 100644 index 0000000000..ffedc22134 --- /dev/null +++ b/plugins/MirLua/src/mlua_metatable.h @@ -0,0 +1,155 @@ +#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 + +struct MTField +{ + size_t offset; + size_t size; + int type; + + MTField(size_t offset, size_t size, int type) + : offset(offset), size(size), type(type) { } +}; + +template +class MT +{ +private: + static const char *name; + static std::map fields; + + template static int GetType(R T::*) { return NULL; } + + template<> static int GetType(int T::*) { return LUA_TINTEGER; } + template<> static int GetType(unsigned int T::*) { return LUA_TINTEGER; } + template<> static int GetType(long T::*) { return LUA_TINTEGER; } + template<> static int GetType(unsigned long T::*) { return LUA_TINTEGER; } + template<> static int GetType(long long T::*) { return LUA_TINTEGER; } + template<> static int GetType(unsigned long long T::*) { return LUA_TINTEGER; } + + template<> static int GetType(char* T::*) { return LUA_TSTRINGA; } + template<> static int GetType(wchar_t* T::*) { return LUA_TSTRINGW; } + + template + static R GetValue(const T *obj, size_t offset, size_t size) + { + R res; + memcpy(&res, ((char*)obj) + offset, size); + return res; + } + + static int __new(lua_State *L) + { + T *obj = NULL; + T **udata = NULL; + + int type = lua_type(L, 1); + switch (type) + { + case LUA_TLIGHTUSERDATA: + obj = (T*)MT::Load(L); + if (obj == NULL) break; + //case LUA_TNONE: + udata = (T**)lua_newuserdata(L, sizeof(T*)); + *udata = MT::Init(obj); + //case LUA_TUSERDATA: + // luaL_setmetatable(L, MT::name); + // return 1; + } + lua_pushnil(L); + + return 1; + } + + static int __index(lua_State *L) + { + T *obj = *(T**)luaL_checkudata(L, 1, MT::name); + const char *key = lua_tostring(L, 2); + + auto it = fields.find(key); + if (it == fields.end()) + { + lua_pushnil(L); + return 1; + } + + MTField *field = it->second; + size_t offset = field->offset; + size_t size = field->size; + + switch (field->type) + { + case LUA_TBOOLEAN: + lua_pushboolean(L, GetValue(obj, offset, size)); + break; + case LUA_TINTEGER: + lua_pushinteger(L, GetValue(obj, offset, size)); + break; + case LUA_TNUMBER: + lua_pushnumber(L, GetValue(obj, offset, size)); + break; + case LUA_TSTRING: + lua_pushstring(L, GetValue(obj, offset, size)); + break; + case LUA_TSTRINGA: + lua_pushstring(L, ptrA(mir_utf8encode(GetValue(obj, offset, size)))); + break; + case LUA_TSTRINGW: + lua_pushstring(L, ptrA(mir_utf8encodeW(GetValue(obj, offset, size)))); + break; + default: + lua_pushnil(L); + } + + return 1; + } + + static int __gc(lua_State *L) + { + T** obj = (T**)luaL_checkudata(L, 1, MT::name); + MT::Free(obj); + return 0; + } + + static T* Load(lua_State *L) { return (T*)lua_touserdata(L, 1); } + static T* Init(T *val) { return val; } + static void Free(T *obj) { obj = NULL; } + +public: + MT(lua_State *L, const char *tname) + { + MT::name = tname; + + lua_pushcfunction(L, __new); + lua_setglobal(L, MT::name); + + luaL_newmetatable(L, MT::name); + lua_pushcfunction(L, __index); + lua_setfield(L, -2, "__index"); + } + + template + MT& Field(R T::*M, const char *name, int type = LUA_TNONE, size_t size = sizeof(R)) + { + size_t offset = reinterpret_cast(&(((T*)0)->*M)); + if (type == LUA_TNONE) type = GetType(M); + if (type != LUA_TNONE) + fields[name] = new MTField(offset, size, type); + return *this; + } +}; + +template +const char *MT::name; + +template +std::map MT::fields; + +#endif //_LUA_METATABLE_H_ -- cgit v1.2.3