summaryrefslogtreecommitdiff
path: root/plugins/MirLua/src/mlua_metatable.h
diff options
context:
space:
mode:
authoraunsane <aunsane@gmail.com>2017-09-26 23:32:12 +0300
committeraunsane <aunsane@gmail.com>2017-09-26 23:34:06 +0300
commit2258b1b2cf951347d167d01201f0dc4bbf9a4428 (patch)
tree1632e76ea7b29da80a24a1c204d5fce932ec5e15 /plugins/MirLua/src/mlua_metatable.h
parent8756de2ffe2d86c34c8a37f08d68aeeb51b487c3 (diff)
MirLua: refactoring
- respect metatables in print function - srmm module functions now return metatable - version bump
Diffstat (limited to 'plugins/MirLua/src/mlua_metatable.h')
-rw-r--r--plugins/MirLua/src/mlua_metatable.h232
1 files changed, 124 insertions, 108 deletions
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_