diff options
Diffstat (limited to 'plugins/MirLua/Modules/JSON/src/metatable.cpp')
-rw-r--r-- | plugins/MirLua/Modules/JSON/src/metatable.cpp | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/plugins/MirLua/Modules/JSON/src/metatable.cpp b/plugins/MirLua/Modules/JSON/src/metatable.cpp new file mode 100644 index 0000000000..2c6ce9b1d6 --- /dev/null +++ b/plugins/MirLua/Modules/JSON/src/metatable.cpp @@ -0,0 +1,160 @@ +#include "stdafx.h"
+
+void table2json(lua_State *L, int idx, JSONNode &node)
+{
+ lua_pushnil(L);
+ while (lua_next(L, idx) != 0)
+ {
+ JSONNode &nnode = (lua_type(L, -2) == LUA_TNUMBER ? (node)[(size_t)lua_tonumber(L, -2) - 1] : (node)[lua_tostring(L, -2)]);
+
+ switch (lua_type(L, -1))
+ {
+ case LUA_TSTRING:
+ nnode = lua_tostring(L, -1);
+ break;
+ case LUA_TBOOLEAN:
+ nnode = lua_toboolean(L, -1) != 0;
+ break;
+ case LUA_TNUMBER:
+ nnode = lua_tonumber(L, -1);
+ break;
+ case LUA_TNIL:
+ nnode.nullify();
+ break;
+ case LUA_TTABLE:
+ nnode = JSONNode(nnode.name(), NULL);
+ table2json(L, -1, nnode);
+ }
+
+ lua_pop(L, 1);
+ }
+}
+
+int json_pushvalue(lua_State *L, JSONNode &node)
+{
+ switch (node.type())
+ {
+ case JSON_NULL:
+ lua_pushnil(L);
+ break;
+ case JSON_STRING:
+ lua_pushstring(L, node.as_string().c_str());
+ break;
+ case JSON_NUMBER:
+ lua_pushnumber(L, node.as_int());
+ break;
+ case JSON_BOOL:
+ lua_pushboolean(L, node.as_bool());
+ break;
+ case JSON_ARRAY:
+ case JSON_NODE:
+ MT *udata = (MT*)lua_newuserdata(L, sizeof(MT));
+ udata->node = &node;
+ udata->bDelete = false;
+ luaL_setmetatable(L, MT_JSON);
+ }
+ return 1;
+}
+
+int json_setvalue(lua_State *L, JSONNode &node)
+{
+ switch (lua_type(L, 3))
+ {
+ case LUA_TSTRING:
+ node = lua_tostring(L, 3);
+ break;
+ case LUA_TBOOLEAN:
+ node = lua_toboolean(L, 3) != 0;
+ break;
+ case LUA_TNUMBER:
+ node = lua_tonumber(L, 3);
+ break;
+ case LUA_TNIL:
+ node.nullify();
+ break;
+ //case LUA_TTABLE:
+ //node = JSONNode(node.name(), JSONNode());
+ //table2json(L, 3, node);
+ }
+
+ return 0;
+}
+
+static int json__call(lua_State *L)
+{
+ if (lua_istable(L, 1))
+ {
+/* MT *udata = (MT*)lua_newuserdata(L, sizeof(MT));
+ udata->node = json_new(JSON_NODE);
+ table2json(L, 1, *udata->node);
+ udata->bDelete = true;
+ luaL_setmetatable(L, MT_JSON);
+ return 1;
+*/
+ }
+ return 0;
+}
+
+static int json__index(lua_State *L)
+{
+ JSONNode *node = ((MT*)luaL_checkudata(L, 1, MT_JSON))->node;
+ switch (lua_type(L, 2))
+ {
+ case LUA_TNUMBER:
+ return json_pushvalue(L, (*node)[(size_t)lua_tonumber(L, 2) - 1]);
+ case LUA_TSTRING:
+ return json_pushvalue(L, (*node)[lua_tostring(L, 2)]);
+ }
+ return 0;
+}
+
+static int json__newindex(lua_State *L)
+{
+ JSONNode *node = ((MT*)luaL_checkudata(L, 1, MT_JSON))->node;
+ switch (lua_type(L, 2))
+ {
+ case LUA_TNUMBER:
+ json_setvalue(L, (*node)[(size_t)lua_tonumber(L, 2) - 1]);
+ break;
+ case LUA_TSTRING:
+ json_setvalue(L, (*node)[lua_tostring(L, 2)]);
+ break;
+ }
+ return 0;
+}
+
+static int json__len(lua_State *L)
+{
+ JSONNode *node = ((MT*)luaL_checkudata(L, 1, MT_JSON))->node;
+ lua_pushnumber(L, (*node).size());
+ return 1;
+}
+
+static int json__tostring(lua_State *L)
+{
+ JSONNode *node = ((MT*)luaL_checkudata(L, 1, MT_JSON))->node;
+ lua_pushstring(L, (*node).write().c_str());
+ return 1;
+}
+
+static int json__gc(lua_State *L)
+{
+ MT *mt = (MT*)luaL_checkudata(L, 1, MT_JSON);
+ if (mt->bDelete)
+ {
+ json_delete(mt->node);
+ mt->node = nullptr;
+ }
+ return 0;
+}
+
+static const struct luaL_Reg jsonApi[] =
+{
+ { "__call", json__call },
+ { "__index", json__index },
+ { "__newindex", json__newindex },
+ { "__len", json__len },
+ { "__tostring", json__tostring },
+ { "__gc", json__gc },
+ { NULL, NULL }
+};
|