diff options
author | aunsane <aunsane@gmail.com> | 2018-06-06 00:34:46 +0300 |
---|---|---|
committer | aunsane <aunsane@gmail.com> | 2018-06-06 00:35:01 +0300 |
commit | a7034dc19a8849bf82d2eb420b150ac54dc079d8 (patch) | |
tree | 75eb7818df9cc9d707bf2c5a010b31ae2340f971 /plugins/MirLua/src/Modules | |
parent | 3c13c94d636ce2c38ca64bbe3febbad68296c661 (diff) |
MirLua:
- add new helper function luaM_isarray
- fix print of decimal point
m_json module
- add __pairs metamethod support
- simplify code
m_http module
- send function should create copy of request object to prevent side effects in async calls
- fix lua functions call
- fix memory leaks
Diffstat (limited to 'plugins/MirLua/src/Modules')
-rw-r--r-- | plugins/MirLua/src/Modules/m_http.cpp | 74 | ||||
-rw-r--r-- | plugins/MirLua/src/Modules/m_json.cpp | 218 |
2 files changed, 152 insertions, 140 deletions
diff --git a/plugins/MirLua/src/Modules/m_http.cpp b/plugins/MirLua/src/Modules/m_http.cpp index f15ebd7fd7..006c7e9876 100644 --- a/plugins/MirLua/src/Modules/m_http.cpp +++ b/plugins/MirLua/src/Modules/m_http.cpp @@ -277,10 +277,11 @@ static void __cdecl SendHttpRequestThread(HttpRequestParam *param) lua_rawgeti(param->L, LUA_REGISTRYINDEX, param->callbackRef); response_Create(param->L, param->request); - luaM_pcall(param->L, 0, 1); + luaM_pcall(param->L, 1, 0); luaL_unref(param->L, LUA_REGISTRYINDEX, param->callbackRef); luaL_unref(param->L, LUA_REGISTRYINDEX, param->threadRef); + Netlib_FreeHttpRequest(param->request); delete param; } @@ -401,12 +402,30 @@ static int request_Send(lua_State *L) { NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + NETLIBHTTPREQUEST *newRequest = (NETLIBHTTPREQUEST*)mir_calloc(sizeof(NETLIBHTTPREQUEST)); + newRequest->cbSize = sizeof(NETLIBHTTPREQUEST); + newRequest->flags = request->flags; + newRequest->requestType = request->requestType; + newRequest->szUrl = mir_strdup(request->szUrl); + newRequest->headersCount = request->headersCount; + newRequest->headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER)*(request->headersCount + 1)); + for (int i = 0; i < request->headersCount; i++) { + newRequest->headers[i].szName = mir_strdup(request->headers[i].szName); + newRequest->headers[i].szValue = mir_strdup(request->headers[i].szValue); + } + newRequest->dataLength = request->dataLength; + newRequest->pData = (char*)mir_calloc(request->dataLength + 1); + memcpy(newRequest->pData, request->pData, request->dataLength); + newRequest->timeout = request->timeout; + if (lua_isfunction(L, 2)) { - SendRequestAsync(L, 2, request); + SendRequestAsync(L, 2, newRequest); return 0; } - response_Create(L, request); + response_Create(L, newRequest); + Netlib_FreeHttpRequest(newRequest); + return 1; } @@ -437,16 +456,8 @@ static int request__index(lua_State *L) static int request__gc(lua_State *L) { - NETLIBHTTPREQUEST **request = (NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); - - mir_free((*request)->szUrl); - for (int i = 0; i < (*request)->headersCount; i++) { - mir_free((*request)->headers[i].szName); - mir_free((*request)->headers[i].szValue); - } - mir_free((*request)->headers); - mir_free((*request)->pData); - + NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + Netlib_FreeHttpRequest(request); return 0; } @@ -486,6 +497,8 @@ static int http_Get(lua_State *L) } response_Create(L, request); + Netlib_FreeHttpRequest(request); + return 1; } @@ -497,20 +510,24 @@ static int http_Post(lua_State *L) const char *url = luaL_checkstring(L, 1); SetUrl(request, url); - lua_pushvalue(L, 2); lua_pushcfunction(L, request_SetContent); + lua_pushvalue(L, -1); + lua_pushvalue(L, 2); luaM_pcall(L, 2, 1); - lua_pushvalue(L, 3); lua_pushcfunction(L, request_SetContentType); + lua_pushvalue(L, -1); + lua_pushvalue(L, 3); luaM_pcall(L, 2, 1); - if (lua_isfunction(L, 2)) { - SendRequestAsync(L, 2, request); + if (lua_isfunction(L, 4)) { + SendRequestAsync(L, 4, request); return 0; } response_Create(L, request); + Netlib_FreeHttpRequest(request); + return 1; } @@ -522,20 +539,24 @@ static int http_Put(lua_State *L) const char *url = luaL_checkstring(L, 1); SetUrl(request, url); - lua_pushvalue(L, 2); lua_pushcfunction(L, request_SetContent); + lua_pushvalue(L, -1); + lua_pushvalue(L, 2); luaM_pcall(L, 2, 1); - lua_pushvalue(L, 3); lua_pushcfunction(L, request_SetContentType); + lua_pushvalue(L, -1); + lua_pushvalue(L, 3); luaM_pcall(L, 2, 1); - if (lua_isfunction(L, 2)) { - SendRequestAsync(L, 2, request); + if (lua_isfunction(L, 4)) { + SendRequestAsync(L, 4, request); return 0; } response_Create(L, request); + Netlib_FreeHttpRequest(request); + return 1; } @@ -547,20 +568,23 @@ static int http_Delete(lua_State *L) const char *url = luaL_checkstring(L, 1); SetUrl(request, url); - lua_pushvalue(L, 2); lua_pushcfunction(L, request_SetContent); + lua_pushvalue(L, -1); + lua_pushvalue(L, 2); luaM_pcall(L, 2, 1); - lua_pushvalue(L, 3); lua_pushcfunction(L, request_SetContentType); + lua_pushvalue(L, -1); + lua_pushvalue(L, 3); luaM_pcall(L, 2, 1); - if (lua_isfunction(L, 2)) { - SendRequestAsync(L, 2, request); + if (lua_isfunction(L, 4)) { + SendRequestAsync(L, 4, request); return 0; } response_Create(L, request); + return 1; } diff --git a/plugins/MirLua/src/Modules/m_json.cpp b/plugins/MirLua/src/Modules/m_json.cpp index 907e0f582b..db45f77065 100644 --- a/plugins/MirLua/src/Modules/m_json.cpp +++ b/plugins/MirLua/src/Modules/m_json.cpp @@ -2,67 +2,92 @@ #define MT_JSON "JSON" -static void lua2json(lua_State *L, JSONNode &node) +static void json2lua(lua_State *L, const JSONNode &node) { - switch (lua_type(L, -1)) { + 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_getglobal(L, "tonumber"); + lua_pushstring(L, node.as_string().c_str()); + luaM_pcall(L, 1, 1); + break; + } + case JSON_BOOL: + lua_pushboolean(L, node.as_bool()); + break; + case JSON_ARRAY: + case JSON_NODE: + JSONNode * *udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); + *udata = json_copy(&node); + luaL_setmetatable(L, MT_JSON); + } +} + +static void lua2json(lua_State *L, int idx, JSONNode &node) +{ + switch (lua_type(L, idx)) { case LUA_TNIL: node.nullify(); break; case LUA_TSTRING: - node = lua_tostring(L, -1); + node = lua_tostring(L, idx); break; case LUA_TBOOLEAN: - node = lua_toboolean(L, -1) != 0; + node = lua_toboolean(L, idx) != 0; break; case LUA_TNUMBER: { - lua_Integer val = lua_tointeger(L, -1); - if (lua_isinteger(L, -1) && val >= LONG_MIN && val <= LONG_MAX) - node = (long)val; - else - node = lua_tonumber(L, -1); + if (!lua_isinteger(L, idx)) { + node = lua_tonumber(L, idx); + break; + } + lua_Integer val = lua_tointeger(L, idx); + node = val >= LONG_MIN && val <= LONG_MAX + ? (long)val + : lua_tonumber(L, idx); break; } case LUA_TTABLE: { ptrA name(mir_strdup(node.name())); - node.cast(JSON_ARRAY); - node.set_name((char*)name); + if (luaM_isarray(L, idx)) { + node.cast(JSON_ARRAY); + node.set_name((char*)name); + } - lua_pushnil(L); - while (lua_next(L, -2) != 0) { + for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) { JSONNode child; - if (!lua_isnumber(L, -2)) { - if (node.type() == JSON_ARRAY) { - node.cast(JSON_NODE); - node.set_name((char*)name); - } + if (node.type() != JSON_ARRAY) { const char *key = lua_tostring(L, -2); child.set_name(key); } - lua2json(L, child); + lua2json(L, lua_absindex(L, -1), child); node << child; - - lua_pop(L, 1); } break; } case LUA_TLIGHTUSERDATA: - if (lua_touserdata(L, -1)) - luaL_argerror(L, -1, luaL_typename(L, -1)); + if (lua_touserdata(L, idx)) + luaL_argerror(L, idx, luaL_typename(L, idx)); node.nullify(); break; case LUA_TUSERDATA: { ptrA name(mir_strdup(node.name())); - JSONNode *other = *(JSONNode**)luaL_checkudata(L, -1, MT_JSON); + JSONNode *other = *(JSONNode**)luaL_checkudata(L, idx, MT_JSON); node = other->duplicate(); node.set_name((char*)name); break; } default: - luaL_argerror(L, -1, luaL_typename(L, -1)); + luaL_argerror(L, idx, luaL_typename(L, idx)); } } @@ -73,7 +98,7 @@ static int json__index(lua_State *L) JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); JSONNode *child; - if (node->type() == JSON_ARRAY) { + if (node->type() == JSON_ARRAY || lua_isinteger(L, 2)) { int idx = lua_tointeger(L, 2); child = &node->at(idx - 1); } @@ -82,26 +107,7 @@ static int json__index(lua_State *L) child = &node->at(key); } - switch (child->type()) - { - case JSON_NULL: - lua_pushnil(L); - break; - case JSON_STRING: - lua_pushstring(L, child->as_string().c_str()); - break; - case JSON_NUMBER: - lua_pushnumber(L, child->as_int()); - break; - case JSON_BOOL: - lua_pushboolean(L, child->as_bool()); - break; - case JSON_ARRAY: - case JSON_NODE: - JSONNode **udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); - *udata = child; - luaL_setmetatable(L, MT_JSON); - } + json2lua(L, *child); return 1; } @@ -109,28 +115,68 @@ static int json__index(lua_State *L) static int json__newindex(lua_State *L) { JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - const char *key = lua_tostring(L, 2); - if (json_type(node) == JSON_ARRAY) { + if (json_type(node) == JSON_ARRAY || lua_isinteger(L, 2)) { int idx = lua_tointeger(L, 2); JSONNode *child = json_at(node, idx - 1); - lua2json(L, *child); + lua2json(L, 3, *child); return 0; } + const char *key = lua_tostring(L, 2); JSONNode *child = json_get(node, key); if (json_type(child) == JSON_NULL) { json_set_name(child, key); - lua2json(L, *child); + lua2json(L, 3, *child); json_push_back(node, child); return 0; } - lua2json(L, *child); + lua2json(L, 3, *child); return 0; } +static int json__pairsIterator(lua_State *L) +{ + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + int i = lua_tointeger(L, lua_upvalueindex(1)); + + setlocale(LC_NUMERIC, "C"); + + if (i < node->size()) { + JSONNode *child = json_at(node, i); + if (json_type(node) == JSON_ARRAY) + lua_pushinteger(L, i + 1); + else + lua_pushstring(L, child->name()); + + json2lua(L, *child); + setlocale(LC_NUMERIC, ""); + + lua_pushinteger(L, (i + 1)); + lua_replace(L, lua_upvalueindex(1)); + + return 2; + } + + setlocale(LC_NUMERIC, ""); + lua_pushnil(L); + + return 1; +} + +static int json__pairs(lua_State *L) +{ + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + + lua_pushinteger(L, 0); + lua_pushcclosure(L, json__pairsIterator, 1); + lua_pushvalue(L, 1); + + return 2; +} + static int json__len(lua_State *L) { JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); @@ -142,9 +188,7 @@ static int json__len(lua_State *L) static int json__tostring(lua_State *L) { JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - lua_pushstring(L, node->write().c_str()); - return 1; } @@ -161,6 +205,7 @@ const struct luaL_Reg jsonApi[] = { { "__index", json__index }, { "__newindex", json__newindex }, + { "__pairs", json__pairs }, { "__len", json__len }, { "__tostring", json__tostring }, { "__gc", json__gc }, @@ -182,70 +227,13 @@ static int lua_Decode(lua_State *L) return 1; } -/***********************************************/ - static int lua_Encode(lua_State *L) { - //JSONNode node; - //lua_pushnil(L); - //lua_pushvalue(L, 1); - //lua2json(L, node); - //lua_pop(L, 2); - //lua_pushstring(L, node.write().c_str()); - - 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 = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - lua_pushstring(L, node->write().c_str()); - break; - } - case LUA_TLIGHTUSERDATA: - if (lua_touserdata(L, 1) == nullptr) - { - lua_pushliteral(L, "null"); - break; - } - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - return 1; - } + JSONNode node; + lua2json(L, 1, node); + lua_pushstring(L, node.write().c_str()); + return 1; +} static const luaL_Reg methods[] = { |