diff options
author | aunsane <aunsane@gmail.com> | 2017-09-26 23:32:12 +0300 |
---|---|---|
committer | aunsane <aunsane@gmail.com> | 2017-09-26 23:34:06 +0300 |
commit | 2258b1b2cf951347d167d01201f0dc4bbf9a4428 (patch) | |
tree | 1632e76ea7b29da80a24a1c204d5fce932ec5e15 /plugins/MirLua | |
parent | 8756de2ffe2d86c34c8a37f08d68aeeb51b487c3 (diff) |
MirLua: refactoring
- respect metatables in print function
- srmm module functions now return metatable
- version bump
Diffstat (limited to 'plugins/MirLua')
-rw-r--r-- | plugins/MirLua/include/mirlua.h | 8 | ||||
-rw-r--r-- | plugins/MirLua/src/m_database.cpp | 154 | ||||
-rw-r--r-- | plugins/MirLua/src/m_protocols.cpp | 20 | ||||
-rw-r--r-- | plugins/MirLua/src/m_srmm.cpp | 141 | ||||
-rw-r--r-- | plugins/MirLua/src/main.cpp | 1 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua.cpp | 15 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_metatable.h | 232 | ||||
-rw-r--r-- | plugins/MirLua/src/version.h | 2 |
8 files changed, 333 insertions, 240 deletions
diff --git a/plugins/MirLua/include/mirlua.h b/plugins/MirLua/include/mirlua.h index eee10289bb..6cf96011ff 100644 --- a/plugins/MirLua/include/mirlua.h +++ b/plugins/MirLua/include/mirlua.h @@ -14,8 +14,12 @@ __forceinline UINT_PTR luaM_tomparam(lua_State *L, int idx) case LUA_TLIGHTUSERDATA: return (UINT_PTR)lua_touserdata(L, idx); case LUA_TNUMBER: - if (lua_isinteger(L, idx)) - return (UINT_PTR)lua_tointeger(L, idx); + { + lua_Integer res = 0; + lua_Number num = lua_tonumber(L, idx); + if (lua_numbertointeger(num, &res)) + return res; + } } return NULL; } diff --git a/plugins/MirLua/src/m_database.cpp b/plugins/MirLua/src/m_database.cpp index bdb5822fcf..7519caa8c8 100644 --- a/plugins/MirLua/src/m_database.cpp +++ b/plugins/MirLua/src/m_database.cpp @@ -1,5 +1,44 @@ #include "stdafx.h"
+void luaM_pushdbvt(lua_State *L, const DBVARIANT &value)
+{
+ switch (value.type)
+ {
+ case DBVT_BYTE:
+ lua_pushinteger(L, value.bVal);
+ break;
+ case DBVT_WORD:
+ lua_pushinteger(L,value.wVal);
+ break;
+ case DBVT_DWORD:
+ lua_pushnumber(L, value.dVal);
+ break;
+ case DBVT_ASCIIZ:
+ lua_pushstring(L, ptrA(mir_utf8encode(value.pszVal)));
+ break;
+ case DBVT_UTF8:
+ lua_pushstring(L, value.pszVal);
+ break;
+ case DBVT_WCHAR:
+ lua_pushstring(L, ptrA(mir_utf8encodeW(value.pwszVal)));
+ break;
+ case DBVT_BLOB:
+ {
+ lua_createtable(L, value.cpbVal, 0);
+ for (int i = 0; i < value.cpbVal; i++)
+ {
+ lua_pushinteger(L, value.pbVal[i]);
+ lua_rawseti(L, -2, i + 1);
+ }
+ }
+ break;
+ default:
+ lua_pushnil(L);
+ }
+}
+
+/***********************************************/
+
static int db_FindFirstContact(lua_State *L)
{
ObsoleteMethod(L, "Use Contacts method");
@@ -328,7 +367,7 @@ static int db_AddEvent(lua_State *L) {
MCONTACT hContact = luaL_checkinteger(L, 1);
- DBEVENTINFO dbei = {};
+ DBEVENTINFO dbei;
MakeDbEvent(L, dbei);
MEVENT hDbEvent = db_event_add(hContact, &dbei);
@@ -398,6 +437,17 @@ static int db_Modules(lua_State *L) return 1;
}
+static int db_DeleteModule(lua_State *L)
+{
+ MCONTACT hContact = lua_tointeger(L, 1);
+ const char *szModule = luaL_checkstring(L, 2);
+
+ INT_PTR res = db_delete_module(hContact, szModule);
+ lua_pushboolean(L, !res);
+
+ return 1;
+}
+
static int SettingsEnumProc(const char* szSetting, LPARAM lParam)
{
if (szSetting)
@@ -429,17 +479,6 @@ static int db_SettingIterator(lua_State *L) return 1;
}
-static int db_DeleteModule(lua_State *L)
-{
- MCONTACT hContact = lua_tointeger(L, 1);
- LPCSTR szModule = luaL_checkstring(L, 2);
-
- INT_PTR res = db_delete_module(hContact, szModule);
- lua_pushboolean(L, !res);
-
- return 1;
-}
-
static int db_Settings(lua_State *L)
{
MCONTACT hContact = lua_tointeger(L, 1);
@@ -458,8 +497,8 @@ static int db_Settings(lua_State *L) static int db_GetSetting(lua_State *L)
{
MCONTACT hContact = lua_tointeger(L, 1);
- LPCSTR szModule = luaL_checkstring(L, 2);
- LPCSTR szSetting = luaL_checkstring(L, 3);
+ const char *szModule = luaL_checkstring(L, 2);
+ const char *szSetting = luaL_checkstring(L, 3);
DBVARIANT dbv;
if (db_get(hContact, szModule, szSetting, &dbv))
@@ -468,55 +507,26 @@ static int db_GetSetting(lua_State *L) return 1;
}
- switch (dbv.type)
- {
- case DBVT_BYTE:
- lua_pushinteger(L, dbv.bVal);
- break;
- case DBVT_WORD:
- lua_pushinteger(L, dbv.wVal);
- break;
- case DBVT_DWORD:
- lua_pushnumber(L, dbv.dVal);
- break;
- case DBVT_ASCIIZ:
- lua_pushstring(L, ptrA(mir_utf8encode(dbv.pszVal)));
- break;
- case DBVT_UTF8:
- lua_pushstring(L, dbv.pszVal);
- break;
- case DBVT_WCHAR:
- lua_pushstring(L, ptrA(mir_utf8encodeW(dbv.pwszVal)));
- break;
- case DBVT_BLOB:
+ luaM_pushdbvt(L, dbv);
+ db_free(&dbv);
+
+ if (lua_isnil(L, -1) && !lua_isnoneornil(L, 4))
{
- lua_createtable(L, dbv.cpbVal, 0);
- for (int i = 0; i < dbv.cpbVal; i++)
- {
- lua_pushinteger(L, dbv.pbVal[i]);
- lua_rawseti(L, -2, i + 1);
- }
- }
- break;
- default:
- db_free(&dbv);
+ lua_pop(L, 1);
lua_pushvalue(L, 4);
- return 1;
}
- lua_pushinteger(L, dbv.type);
- db_free(&dbv);
- return 2;
+ return 1;
}
static int db_WriteSetting(lua_State *L)
{
MCONTACT hContact = lua_tointeger(L, 1);
- LPCSTR szModule = luaL_checkstring(L, 2);
- LPCSTR szSetting = luaL_checkstring(L, 3);
+ const char *szModule = luaL_checkstring(L, 2);
+ const char *szSetting = luaL_checkstring(L, 3);
luaL_checkany(L, 4);
- DBVARIANT dbv = { 0 };
+ DBVARIANT dbv;
if (lua_isnoneornil(L, 5))
{
int type = lua_type(L, 4);
@@ -646,46 +656,12 @@ static luaL_Reg databaseApi[] = #define MT_DBCONTACTWRITESETTING "DBCONTACTWRITESETTING"
template <>
-int MT<DBCONTACTWRITESETTING>::Index(lua_State *L, DBCONTACTWRITESETTING *dbcw)
+int MT<DBCONTACTWRITESETTING>::Get(lua_State *L, DBCONTACTWRITESETTING *dbcw)
{
const char *key = luaL_checkstring(L, 2);
if (mir_strcmpi(key, "Value") == 0)
- {
- switch (dbcw->value.type)
- {
- case DBVT_BYTE:
- lua_pushinteger(L, dbcw->value.bVal);
- break;
- case DBVT_WORD:
- lua_pushinteger(L, dbcw->value.wVal);
- break;
- case DBVT_DWORD:
- lua_pushnumber(L, dbcw->value.dVal);
- break;
- case DBVT_ASCIIZ:
- lua_pushstring(L, ptrA(mir_utf8encode(dbcw->value.pszVal)));
- break;
- case DBVT_UTF8:
- lua_pushstring(L, dbcw->value.pszVal);
- break;
- case DBVT_WCHAR:
- lua_pushstring(L, ptrA(mir_utf8encodeW(dbcw->value.pwszVal)));
- break;
- case DBVT_BLOB:
- {
- lua_createtable(L, dbcw->value.cpbVal, 0);
- for (int i = 0; i < dbcw->value.cpbVal; i++)
- {
- lua_pushinteger(L, dbcw->value.pbVal[i]);
- lua_rawseti(L, -2, i + 1);
- }
- }
- break;
- default:
- lua_pushnil(L);
- }
- }
+ luaM_pushdbvt(L, dbcw->value);
else
lua_pushnil(L);
@@ -710,7 +686,7 @@ DBEVENTINFO* MT<DBEVENTINFO>::Init(lua_State *L) }
template <>
-int MT<DBEVENTINFO>::Index(lua_State *L, DBEVENTINFO *dbei)
+int MT<DBEVENTINFO>::Get(lua_State *L, DBEVENTINFO *dbei)
{
const char *key = luaL_checkstring(L, 2);
diff --git a/plugins/MirLua/src/m_protocols.cpp b/plugins/MirLua/src/m_protocols.cpp index 979388eed6..42b24c4936 100644 --- a/plugins/MirLua/src/m_protocols.cpp +++ b/plugins/MirLua/src/m_protocols.cpp @@ -25,7 +25,7 @@ static int lua_GetProtocol(lua_State *L) PROTOCOLDESCRIPTOR *pd = Proto_IsProtocolLoaded(szProto);
if (pd)
- MT<PROTOCOLDESCRIPTOR>::Set(L, pd);
+ MT<PROTOCOLDESCRIPTOR>::Apply(L, pd);
else
lua_pushnil(L);
@@ -42,7 +42,7 @@ static int lua_ProtocolIterator(lua_State *L) {
lua_pushinteger(L, (i + 1));
lua_replace(L, lua_upvalueindex(1));
- MT<PROTOCOLDESCRIPTOR>::Set(L, protos[i]);
+ MT<PROTOCOLDESCRIPTOR>::Apply(L, protos[i]);
}
else
lua_pushnil(L);
@@ -110,7 +110,7 @@ static int lua_GetAccount(lua_State *L) PROTOACCOUNT *pa = Proto_GetAccount(name);
if (pa)
- MT<PROTOACCOUNT>::Set(L, pa);
+ MT<PROTOACCOUNT>::Apply(L, pa);
else
lua_pushnil(L);
@@ -132,7 +132,7 @@ static int lua_AccountIterator(lua_State *L) {
lua_pushinteger(L, (i + 1));
lua_replace(L, lua_upvalueindex(1));
- MT<PROTOACCOUNT>::Set(L, accounts[i]);
+ MT<PROTOACCOUNT>::Apply(L, accounts[i]);
}
else
lua_pushnil(L);
@@ -153,8 +153,8 @@ static int lua_Accounts(lua_State *L) break;
case LUA_TUSERDATA:
{
- PROTOCOLDESCRIPTOR **pd = (PROTOCOLDESCRIPTOR**)luaL_checkudata(L, 1, MT_PROTOCOLDESCRIPTOR);
- szProto = (*pd)->szName;
+ PROTOCOLDESCRIPTOR *pd = *(PROTOCOLDESCRIPTOR**)luaL_checkudata(L, 1, MT_PROTOCOLDESCRIPTOR);
+ szProto = pd->szName;
break;
}
default:
@@ -188,8 +188,8 @@ static int lua_CallService(lua_State *L) break;
case LUA_TUSERDATA:
{
- PROTOACCOUNT **pa = (PROTOACCOUNT**)luaL_checkudata(L, 1, MT_PROTOACCOUNT);
- szModule = (*pa)->szModuleName;
+ PROTOACCOUNT *pa = *(PROTOACCOUNT**)luaL_checkudata(L, 1, MT_PROTOACCOUNT);
+ szModule = pa->szModuleName;
break;
}
default:
@@ -266,8 +266,8 @@ LUAMOD_API int luaopen_m_protocols(lua_State *L) MT<CCSDATA>(L, "CCSDATA")
.Field(&CCSDATA::hContact, "hContact", LUA_TINTEGER)
.Field(&CCSDATA::szProtoService, "Service", LUA_TSTRINGA)
- .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);
+ .Field(&CCSDATA::wParam, "wParam", LUA_TLIGHTUSERDATA)
+ .Field(&CCSDATA::lParam, "lParam", LUA_TLIGHTUSERDATA);
MT<PROTORECVEVENT>(L, "PROTORECVEVENT")
.Field(&PROTORECVEVENT::timestamp, "Timestamp", LUA_TINTEGER)
diff --git a/plugins/MirLua/src/m_srmm.cpp b/plugins/MirLua/src/m_srmm.cpp index a1b7240cec..c28f2de4ce 100644 --- a/plugins/MirLua/src/m_srmm.cpp +++ b/plugins/MirLua/src/m_srmm.cpp @@ -1,5 +1,7 @@ #include "stdafx.h" +#define MT_BBBUTTON "BBButton" + static void MakeBBButton(lua_State *L, BBButton &bbb) { bbb.dwDefPos = 100; @@ -29,56 +31,114 @@ static void MakeBBButton(lua_State *L, BBButton &bbb) lua_pop(L, 1); } +/***********************************************/ + static int lua_AddButton(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); - BBButton bbb; - MakeBBButton(L, bbb); + BBButton *bbb = (BBButton*)mir_calloc(sizeof(BBButton)); + MakeBBButton(L, *bbb); int hScriptLangpack = CMLuaScript::GetScriptIdFromEnviroment(L); - - INT_PTR res = Srmm_AddButton(&bbb, hScriptLangpack); - lua_pushboolean(L, res == 0); - - mir_free((void*)bbb.pszModuleName); - mir_free((void*)bbb.pwszText); - mir_free((void*)bbb.pwszTooltip); + if (Srmm_AddButton(bbb, hScriptLangpack)) + { + lua_pushnil(L); + return 1; + } + + MT<BBButton>::Apply(L, bbb); return 1; } static int lua_ModifyButton(lua_State *L) { - if (lua_type(L, 1) != LUA_TTABLE) + switch (lua_type(L, 1)) { - lua_pushlightuserdata(L, 0); - return 1; + case LUA_TTABLE: + { + BBButton bbb; + MakeBBButton(L, bbb); + INT_PTR res = Srmm_ModifyButton(&bbb); + mir_free((void*)bbb.pszModuleName); + mir_free((void*)bbb.pwszText); + mir_free((void*)bbb.pwszTooltip); + lua_pushboolean(L, !res); + break; + } + case LUA_TUSERDATA: + { + BBButton *bbb = *(BBButton**)luaL_checkudata(L, 1, MT_BBBUTTON); + luaL_checktype(L, 2, LUA_TTABLE); + { + if (lua_getfield(L, -1, "Text")) + { + mir_free((void*)bbb->pwszText); + bbb->pwszText = mir_utf8decodeW(lua_tostring(L, -1)); + } + lua_pop(L, 1); + + if (lua_getfield(L, -1, "Tooltip")) + { + mir_free((void*)bbb->pwszTooltip); + bbb->pwszTooltip = mir_utf8decodeW(lua_tostring(L, -1)); + } + lua_pop(L, 1); + + if (lua_getfield(L, -1, "Flags")) + bbb->bbbFlags = luaL_optinteger(L, -1, BBBF_ISIMBUTTON); + lua_pop(L, 1); + + if (lua_getfield(L, -1, "Icon")) + bbb->hIcon = (HANDLE)lua_touserdata(L, -1); + lua_pop(L, 1); + } + INT_PTR res = Srmm_ModifyButton(bbb); + lua_pushvalue(L, 1); + break; + } + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); } - - BBButton bbb; - MakeBBButton(L, bbb); - - INT_PTR res = Srmm_ModifyButton(&bbb); - lua_pushinteger(L, res); - - mir_free((void*)bbb.pszModuleName); - mir_free((void*)bbb.pwszText); - mir_free((void*)bbb.pwszTooltip); return 1; } static int lua_RemoveButton(lua_State *L) { - ptrA szModuleName(mir_utf8decodeA(luaL_checkstring(L, 1))); - - BBButton mbb = {}; - mbb.pszModuleName = szModuleName; - mbb.dwButtonID = luaL_checkinteger(L, 2); - - INT_PTR res = Srmm_RemoveButton(&mbb); - lua_pushinteger(L, res); + switch (lua_type(L, 1)) + { + case LUA_TSTRING: + { + BBButton bbb; + bbb.pszModuleName = mir_utf8decodeA(lua_tostring(L, 1)); + bbb.dwButtonID = luaL_checkinteger(L, 2); + INT_PTR res = Srmm_RemoveButton(&bbb); + mir_free((void*)bbb.pszModuleName); + lua_pushboolean(L, !res); + break; + } + case LUA_TTABLE: + { + BBButton bbb; + bbb.pszModuleName = mir_utf8decodeA(luaL_checkstring(L, 1)); + bbb.dwButtonID = luaL_checkinteger(L, 2); + INT_PTR res = Srmm_RemoveButton(&bbb); + mir_free((void*)bbb.pszModuleName); + lua_pushboolean(L, !res); + break; + } + case LUA_TUSERDATA: + { + BBButton *bbb = *(BBButton**)luaL_checkudata(L, 1, MT_BBBUTTON); + INT_PTR res = Srmm_RemoveButton(bbb); + lua_pushboolean(L, !res); + break; + } + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } return 1; } @@ -94,10 +154,31 @@ static luaL_Reg srmmApi[] = /***********************************************/ +template <> +void MT<BBButton>::Free(lua_State*, BBButton **bbb) +{ + mir_free((void*)(*bbb)->pszModuleName); + mir_free((void*)(*bbb)->pwszText); + mir_free((void*)(*bbb)->pwszTooltip); + mir_free(*bbb); +} + +/***********************************************/ + LUAMOD_API int luaopen_m_srmm(lua_State *L) { luaL_newlib(L, srmmApi); + MT<BBButton>(L, MT_BBBUTTON) + .Field(&BBButton::pszModuleName, "Module", LUA_TSTRINGA) + .Field(&BBButton::dwButtonID, "ButtonId", LUA_TINTEGER) + .Field(&BBButton::pwszText, "Text", LUA_TSTRINGW) + .Field(&BBButton::pwszTooltip, "Tooltip", LUA_TSTRINGW) + .Field(&BBButton::bbbFlags, "Flags", LUA_TINTEGER) + .Field(&BBButton::hIcon, "Icon", LUA_TLIGHTUSERDATA) + .Field(lua_ModifyButton, "Modify") + .Field(lua_RemoveButton, "Remove"); + MT<CustomButtonClickData>(L, "CustomButtonClickData") .Field(&CustomButtonClickData::pszModule, "Module", LUA_TSTRINGA) .Field(&CustomButtonClickData::dwButtonId, "ButtonId", LUA_TINTEGER) diff --git a/plugins/MirLua/src/main.cpp b/plugins/MirLua/src/main.cpp index 7648ecf930..0da7a5d157 100644 --- a/plugins/MirLua/src/main.cpp +++ b/plugins/MirLua/src/main.cpp @@ -74,6 +74,7 @@ extern "C" int __declspec(dllexport) Load(void) hRecvMessage = CreateHookableEvent(MODULE PSR_MESSAGE);
CreateProtoServiceFunction(MODULE, PSR_MESSAGE, FilterRecvMessage);
+
return 0;
}
diff --git a/plugins/MirLua/src/mlua.cpp b/plugins/MirLua/src/mlua.cpp index d3c835ee7d..5229196f64 100644 --- a/plugins/MirLua/src/mlua.cpp +++ b/plugins/MirLua/src/mlua.cpp @@ -42,6 +42,21 @@ static int mlua_print(lua_State *L) data.AppendFormat("%s", lua_tostring(L, i));
break;
default:
+ if (lua_getmetatable(L, 1))
+ {
+ if (lua_getfield(L, -1, "__tostring") == LUA_TFUNCTION)
+ {
+ lua_pushvalue(L, 1);
+ if (luaM_pcall(L, 1, 1) == LUA_OK)
+ {
+ data.AppendFormat("%s", lua_tostring(L, -1));
+ lua_pop(L, 2);
+ break;
+ }
+ lua_pop(L, 2);
+ }
+ lua_pop(L, 1);
+ }
data.AppendFormat("%s(0x%p)", luaL_typename(L, i), lua_topointer(L, i));
break;
}
diff --git a/plugins/MirLua/src/mlua_metatable.h b/plugins/MirLua/src/mlua_metatable.h index 58dfede077..04173a2a56 100644 --- a/plugins/MirLua/src/mlua_metatable.h +++ b/plugins/MirLua/src/mlua_metatable.h @@ -9,7 +9,7 @@ #define LUA_TSTRINGA LUA_NUMTAGS + 2
#define LUA_TSTRINGW LUA_NUMTAGS + 3
-union MTFieldVal
+union MTValue
{
void *userdata;
int boolean;
@@ -21,88 +21,76 @@ union MTFieldVal lua_CFunction function;
};
-struct MTField
-{
- int lua_type;
- MTFieldVal val;
-};
-
class CMTField
{
- ptrA pszName;
+ ptrA name;
+ int type;
public:
- CMTField(const char *name) :
- pszName(mir_strdup(name))
- {}
+ CMTField(const char *name, int type) :
+ name(mir_strdup(name)), type(type) {}
- const char* GetName() const { return pszName; }
+ virtual ~CMTField() {};
- static int Compare(const CMTField *p1, const CMTField *p2)
- { return mir_strcmp(p1->pszName, p2->pszName);
+ const char* GetName() const { return name; }
+ int GetType() const { return type; }
+
+ static int Compare(const CMTField *p1, const CMTField *p2) {
+ return mir_strcmp(p1->name, p2->name);
}
- virtual MTField GetValue(void *obj) = 0;
- virtual ~CMTField(){};
+ virtual MTValue GetValue(void *obj) = 0;
};
-template <typename Obj, typename Ret>
+template <typename R>
class CMTFieldOffset : public CMTField
{
- int lua_type;
ptrdiff_t offset;
size_t size;
public:
- CMTFieldOffset(const char *name, ptrdiff_t off, size_t s, int type)
- : CMTField(name),
- offset(off), lua_type(type), size(s)
- {}
+ CMTFieldOffset(const char *name, int type, ptrdiff_t offset, size_t size)
+ : CMTField(name, type), offset(offset), size(size) {}
- virtual MTField GetValue(void *obj)
+ virtual MTValue GetValue(void *obj)
{
- MTField fd = { lua_type };
- //fd.val = *(Ret*)((char*)obj + offset);
- memcpy(&fd.val, ((char*)obj + offset), sizeof(Ret));
- return fd;
+ MTValue value;
+ memcpy(&value, ((char*)obj + offset), sizeof(R));
+ return value;
}
};
class CMTFieldFunction : public CMTField
{
- lua_CFunction func;
+ lua_CFunction function;
public:
- CMTFieldFunction(const char *name, lua_CFunction f) :
- CMTField(name),
- func(f)
- {}
+ CMTFieldFunction(const char *name, lua_CFunction function) :
+ CMTField(name, LUA_TFUNCTION), function(function) {}
- virtual MTField GetValue(void*)
+ virtual MTValue GetValue(void*)
{
- MTField tmp = { LUA_TFUNCTION };
- tmp.val.function = func;
- return tmp;
+ MTValue value;
+ value.function = function;
+ return value;
}
};
-template <typename Obj>
+template <typename T>
class CMTFieldLambda : public CMTField
{
- int lua_type;
- std::function<MTFieldVal(Obj*)> lambda;
+ int type;
+ std::function<MTValue(T*)> lambda;
public:
- CMTFieldLambda(const char *name, decltype(lambda) f, int type)
- : CMTField(name),
- lambda(f), lua_type(type)
- {}
+ CMTFieldLambda(const char *name, int type, decltype(lambda) lambda)
+ : CMTField(name, type), lambda(lambda), type(type) {}
- virtual MTField GetValue(void *obj)
+ virtual MTValue GetValue(void *obj)
{
- MTField tmp = { lua_type };
- tmp.val = lambda((Obj*)obj);
- return tmp;
+ CMTValue result = { type };
+ result.Value = lambda((Obj*)obj);
+ return result;
}
};
@@ -113,7 +101,8 @@ private: lua_State *L;
static const char *name;
- static OBJLIST<CMTField> arFields;
+ static const luaL_Reg events[];
+ static OBJLIST<CMTField> fields;
static T* Init(lua_State *L)
{
@@ -121,12 +110,17 @@ private: return (T*)lua_touserdata(L, 1);
}
- static int Index(lua_State *L, T* /*obj*/)
+ static int Get(lua_State *L, T* /*obj*/)
{
lua_pushnil(L);
return 1;
}
+ static bool Set(lua_State *L, T* /*obj*/)
+ {
+ return false;
+ }
+
static void Free(lua_State* /*L*/, T **obj)
{
*obj = NULL;
@@ -135,17 +129,27 @@ private: static int lua__new(lua_State *L)
{
T **udata = (T**)lua_newuserdata(L, sizeof(T*));
+
*udata = Init(L);
if (*udata == NULL)
{
lua_pushnil(L);
return 1;
}
+
luaL_setmetatable(L, MT::name);
return 1;
}
+ static int lua__gc(lua_State *L)
+ {
+ T **obj = (T**)luaL_checkudata(L, 1, MT::name);
+ MT::Free(L, obj);
+
+ return 0;
+ }
+
static int lua__bnot(lua_State *L)
{
T *obj = *(T**)luaL_checkudata(L, 1, MT::name);
@@ -159,36 +163,37 @@ private: T *obj = *(T**)luaL_checkudata(L, 1, MT::name);
const char *key = lua_tostring(L, 2);
- LPCVOID arTmp[2] = { nullptr, key };
- CMTField *pField = arFields.find((CMTField*)&arTmp);
- if (pField == nullptr)
- return Index(L, obj);
+ const void *tmp[2] = { nullptr, key };
+ CMTField *field = fields.find((CMTField*)&tmp);
+ if (field == nullptr)
+ return Get(L, obj);
- MTField fieldVal = pField->GetValue(obj);
- switch (fieldVal.lua_type) {
+ MTValue value = field->GetValue(obj);
+ int type = field->GetType();
+ switch (type) {
case LUA_TBOOLEAN:
- lua_pushboolean(L, fieldVal.val.boolean);
+ lua_pushboolean(L, value.boolean);
break;
case LUA_TINTEGER:
- lua_pushinteger(L, fieldVal.val.integer);
+ lua_pushinteger(L, value.integer);
break;
case LUA_TNUMBER:
- lua_pushnumber(L, fieldVal.val.number);
+ lua_pushnumber(L, value.number);
break;
case LUA_TSTRING:
- lua_pushstring(L, fieldVal.val.string);
+ lua_pushstring(L, value.string);
break;
case LUA_TSTRINGA:
- lua_pushstring(L, ptrA(mir_utf8encode(fieldVal.val.stringA)));
+ lua_pushstring(L, ptrA(mir_utf8encode(value.stringA)));
break;
case LUA_TSTRINGW:
- lua_pushstring(L, T2Utf(fieldVal.val.stringW));
+ lua_pushstring(L, T2Utf(value.stringW));
break;
case LUA_TLIGHTUSERDATA:
- lua_pushlightuserdata(L, fieldVal.val.userdata);
+ lua_pushlightuserdata(L, value.userdata);
break;
case LUA_TFUNCTION:
- lua_pushcfunction(L, fieldVal.val.function);
+ lua_pushcfunction(L, value.function);
break;
default:
lua_pushnil(L);
@@ -197,45 +202,57 @@ private: return 1;
}
+ static int lua__newindex(lua_State *L)
+ {
+ T *obj = *(T**)luaL_checkudata(L, 1, MT::name);
+
+ if (!Set(L, obj)) {
+ const char *key = lua_tostring(L, 2);
+ luaL_error(L, "attempt to index a %s value (%s is readonly)", MT::name, key);
+ }
+
+ return 0;
+ }
+
static int lua__tostring(lua_State *L)
{
T *obj = *(T**)luaL_checkudata(L, 1, MT::name);
CMStringA data(MT::name);
data += "(";
- for (int i = 0; i < arFields.getCount(); i++)
- {
- CMTField &F = arFields[i];
+ for (int i = 0; i < fields.getCount(); i++) {
+ CMTField &field = fields[i];
- data += F.GetName();
+ data += field.GetName();
data += "=";
- MTField fieldVal = F.GetValue(obj);
- switch (fieldVal.lua_type)
- {
+ MTValue value = field.GetValue(obj);
+ int type = field.GetType();
+ switch (type) {
+ case LUA_TNIL:
+ data.Append("nil");
+ break;
case LUA_TBOOLEAN:
- data.Append(fieldVal.val.boolean == 0 ? "false" : "true");
+ data.Append(value.boolean == 0 ? "false" : "true");
break;
case LUA_TINTEGER:
- data.AppendFormat("%d", fieldVal.val.integer);
+ data.AppendFormat("%d", value.integer);
break;
case LUA_TNUMBER:
- data.AppendFormat("%f", fieldVal.val.number);
+ data.AppendFormat("%f", value.number);
break;
case LUA_TSTRING:
- data.Append(fieldVal.val.string);
+ data.Append(value.string);
break;
case LUA_TSTRINGA:
- data.Append(ptrA(mir_utf8encode(fieldVal.val.stringA)));
+ data.Append(ptrA(mir_utf8encode(value.stringA)));
break;
case LUA_TSTRINGW:
- data.Append(T2Utf(fieldVal.val.stringW));
- break;
- case LUA_TLIGHTUSERDATA:
- data.AppendFormat("(0x%p)", fieldVal.val.userdata);
+ data.Append(T2Utf(value.stringW));
break;
default:
- data.Append("nil");
+ data.AppendFormat("%s(0x%p)", lua_typename(L, type), value.userdata);
+ break;
}
data += ", ";
}
@@ -244,40 +261,29 @@ private: return 1;
}
- static int lua__gc(lua_State *L)
- {
- T **obj = (T**)luaL_checkudata(L, 1, MT::name);
- MT::Free(L, obj);
-
- return 0;
- }
-
static int lua__call(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
+ int nres = lua_gettop(L) - 1;
+
lua_getfield(L, 1, "new");
- lua_pushvalue(L, 2);
- luaM_pcall(L, 1, 1);
+ for (int i = 1; i <= nres; i++)
+ lua_pushvalue(L, i + 1);
+ luaM_pcall(L, nres, 1);
return 1;
}
public:
- MT(lua_State *L, const char *tname) : L(L)
+ MT(lua_State *L, const char *tname)
+ : L(L)
{
MT::name = tname;
luaL_newmetatable(L, MT::name);
- lua_pushcfunction(L, lua__index);
- lua_setfield(L, -2, "__index");
- lua_pushcfunction(L, lua__bnot);
- lua_setfield(L, -2, "__bnot");
- lua_pushcfunction(L, lua__tostring);
- lua_setfield(L, -2, "__tostring");
- lua_pushcfunction(L, lua__gc);
- lua_setfield(L, -2, "__gc");
+ luaL_setfuncs(L, events, 0);
lua_pop(L, 1);
lua_createtable(L, 0, 1);
@@ -298,28 +304,27 @@ public: size = sizeof(M);
size_t offset = (size_t)(&(((T*)0)->*M));
if (type != LUA_TNONE)
- arFields.insert(new CMTFieldOffset<T, R>(name, offset, size, type));
+ fields.insert(new CMTFieldOffset<R>(name, type, offset, size));
return *this;
}
template<typename L>
- MT& Field(const L &f, const char *name, int type)
+ MT& Field(const L &lambda, const char *name, int type)
{
if (type != LUA_TNONE)
- arFields.insert(new CMTFieldLambda<T>(name, f, type));
+ fields.insert(new CMTFieldLambda<T>(name, type, lambda));
return *this;
}
- MT& Field(const lua_CFunction f, const char *name)
+ MT& Field(const lua_CFunction function, const char *name)
{
- arFields.insert(new CMTFieldFunction(name, f));
+ fields.insert(new CMTFieldFunction(name, function));
return *this;
}
- static void Set(lua_State *L, T *obj)
+ static void Apply(lua_State *L, T *obj)
{
- if (obj == NULL)
- {
+ if (obj == NULL) {
lua_pushnil(L);
return;
}
@@ -334,6 +339,17 @@ template<typename T> const char *MT<T>::name;
template<typename T>
-OBJLIST<CMTField> MT<T>::arFields(5, &CMTField::Compare);
+const luaL_Reg MT<T>::events[] = {
+ { "__index", lua__index },
+ { "__newindex", lua__newindex },
+ { "__bnot", lua__bnot },
+ { "__tostring", lua__tostring },
+ { "__gc", lua__gc },
+
+ { NULL, NULL },
+};
+
+template<typename T>
+OBJLIST<CMTField> MT<T>::fields(5, &CMTField::Compare);
#endif //_LUA_METATABLE_H_
diff --git a/plugins/MirLua/src/version.h b/plugins/MirLua/src/version.h index 89028c524c..6b783b7c7b 100644 --- a/plugins/MirLua/src/version.h +++ b/plugins/MirLua/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0
#define __MINOR_VERSION 11
#define __RELEASE_NUM 8
-#define __BUILD_NUM 2
+#define __BUILD_NUM 3
#include <stdver.h>
|