diff options
author | aunsane <aunsane@gmail.com> | 2017-10-10 21:55:12 +0300 |
---|---|---|
committer | aunsane <aunsane@gmail.com> | 2017-10-10 21:55:26 +0300 |
commit | 39e461bb614d75a6f23511a016afaeb3aba35f1a (patch) | |
tree | b61e3b3571bec7cb072abf91b512d0c398ee9195 /plugins/MirLua/src/m_json.cpp | |
parent | d3387c7307fa3f883e77c17e443874b3a085ded5 (diff) |
MirLua:
- m_json moved into base plugin
- added m_http module
-version bump
Diffstat (limited to 'plugins/MirLua/src/m_json.cpp')
-rw-r--r-- | plugins/MirLua/src/m_json.cpp | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/plugins/MirLua/src/m_json.cpp b/plugins/MirLua/src/m_json.cpp new file mode 100644 index 0000000000..e4bbf233ef --- /dev/null +++ b/plugins/MirLua/src/m_json.cpp @@ -0,0 +1,227 @@ +#include "stdafx.h" + +static void lua2json(lua_State *L, JSONNode &node) +{ + switch (lua_type(L, -1)) + { + case LUA_TNIL: + node.nullify(); + break; + case LUA_TSTRING: + node = lua_tostring(L, -1); + break; + case LUA_TBOOLEAN: + node = lua_toboolean(L, -1) != 0; + break; + case LUA_TNUMBER: + { + lua_Integer val = lua_tointeger(L, -1); + if (lua_isinteger(L, -1) && val >= LONG_MIN && val <= LONG_MIN) + node = (long)val; + else + node = lua_tonumber(L, -1); + break; + } + case LUA_TTABLE: + { + ptrA name(mir_strdup(node.name())); + node.cast(JSON_ARRAY); + node.set_name((char*)name); + + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + JSONNode child; + if (!lua_isnumber(L, -2)) { + if (node.type() == JSON_ARRAY) { + node.cast(JSON_NODE); + node.set_name((char*)name); + } + const char *key = lua_tostring(L, -2); + child.set_name(key); + } + lua2json(L, child); + node << child; + + lua_pop(L, 1); + } + + break; + } + } +} + +/***********************************************/ + +static int json__index(lua_State *L) +{ + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->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_NODE: + case JSON_ARRAY: + new (L) JSONNode(node); + luaL_setmetatable(L, MT_JSON); + } + + return 1; +} + +static int json__newindex(lua_State *L) +{ + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + const char *key = lua_tostring(L, 2); + + JSONNode child = node[key]; + if (child.isnull()) { + child.set_name(key); + lua2json(L, child); + node << child; + return 0; + } + + lua2json(L, child); + node[key] = child; + + return 0; +} + +static int json__len(lua_State *L) +{ + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + + lua_pushnumber(L, node.size()); + + return 1; +} + +static int json__tostring(lua_State *L) +{ + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + + lua_pushstring(L, node.write().c_str()); + + return 1; +} + +static int json__gc(lua_State *L) +{ + JSON *json = (JSON*)luaL_checkudata(L, 1, MT_JSON); + + delete json; + + return 0; +} + +const struct luaL_Reg jsonApi[] = +{ + { "__index", json__index }, + { "__newindex", json__newindex }, + { "__len", json__len }, + { "__tostring", json__tostring }, + { "__gc", json__gc }, + + { NULL, NULL } +}; + + +/***********************************************/ + +static int lua_Decode(lua_State *L) +{ + const char *string = luaL_checkstring(L, 1); + + JSONNode *node = json_parse(string); + new (L) JSON(node); + luaL_setmetatable(L, MT_JSON); + + return 1; +} + +static int lua_Encode(lua_State *L) +{ + switch (lua_type(L, 1)) + { + case LUA_TNIL: + lua_pushliteral(L, "null"); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, lua_toboolean(L, 1) ? "true" : "false"); + break; + case LUA_TNUMBER: + { + if (lua_isinteger(L, 1)) { + lua_pushfstring(L, "%I", lua_tointeger(L, 1)); + break; + } + char decpoint = lua_getlocaledecpoint(); + if (decpoint != '.') { + char p[2] = { decpoint }; + luaL_gsub(L, lua_tostring(L, 1), p, "."); + } + else + lua_pushfstring(L, "%f", lua_tonumber(L, 1)); + break; + } + case LUA_TSTRING: + lua_pushfstring(L, "\"%s\"", lua_tostring(L, 1)); + break; + case LUA_TTABLE: + { + JSONNode node; + lua_pushnil(L); + lua_pushvalue(L, 1); + lua2json(L, node); + lua_pop(L, 2); + lua_pushstring(L, node.write().c_str()); + break; + } + case LUA_TUSERDATA: + { + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + lua_pushstring(L, node.write().c_str()); + break; + } + case LUA_TLIGHTUSERDATA: + if (lua_touserdata(L, 1) == NULL) + { + lua_pushliteral(L, "null"); + break; + } + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + return 1; +} + +static const luaL_Reg methods[] = +{ + { "Decode", lua_Decode }, + { "Encode", lua_Encode }, + + { NULL, NULL } +}; + +LUAMOD_API int luaopen_m_json(lua_State *L) +{ + luaL_newlib(L, methods); + + luaL_newmetatable(L, MT_JSON); + luaL_setfuncs(L, jsonApi, 0); + lua_pop(L, 1); + + return 1; +}
\ No newline at end of file |