Mercurial > hg > orthanc
diff Core/Lua/LuaContext.cpp @ 1447:5ba7471780ae
refactoring: HttpToolbox, DumpJson in Lua
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 01 Jul 2015 17:42:06 +0200 |
parents | af112b7d9cba |
children | 3f7722179467 |
line wrap: on
line diff
--- a/Core/Lua/LuaContext.cpp Wed Jul 01 13:16:12 2015 +0200 +++ b/Core/Lua/LuaContext.cpp Wed Jul 01 17:42:06 2015 +0200 @@ -33,8 +33,10 @@ #include "../PrecompiledHeaders.h" #include "LuaContext.h" +#include <set> #include <glog/logging.h> #include <cassert> +#include <boost/lexical_cast.hpp> extern "C" { @@ -90,7 +92,7 @@ } - int LuaContext::ParseJsonString(lua_State *state) + int LuaContext::ParseJson(lua_State *state) { LuaContext& that = GetLuaContext(state); @@ -119,6 +121,32 @@ } + int LuaContext::DumpJson(lua_State *state) + { + int nArgs = lua_gettop(state); + if (nArgs != 1) + { + lua_pushnil(state); + return 1; + } + + Json::Value json; + if (GetJson(json, state, 1)) + { + Json::FastWriter writer; + std::string s = writer.write(json); + lua_pushstring(state, s.c_str()); + } + else + { + LOG(ERROR) << "Lua: Unable to convert a JSON variable to a string"; + lua_pushnil(state); + } + + return 1; + } + + int LuaContext::SetHttpCredentials(lua_State *state) { LuaContext& that = GetLuaContext(state); @@ -348,6 +376,135 @@ } + static bool CompactObjectToArray(Json::Value& result, + const Json::Value& source) + { + Json::Value::Members members = source.getMemberNames(); + + std::set<size_t> keys; + for (Json::Value::ArrayIndex i = 0; i < members.size(); i++) + { + try + { + size_t key = boost::lexical_cast<size_t>(members[i]); + keys.insert(key); + } + catch (boost::bad_lexical_cast&) + { + return false; + } + } + + if (keys.size() != members.size()) + { + return false; + } + + for (size_t i = 1; i <= members.size(); i++) + { + if (keys.find(i) == keys.end()) + { + return false; + } + } + + result = Json::arrayValue; + result.resize(members.size()); + for (size_t i = 0; i < members.size(); i++) + { + Json::Value::ArrayIndex key = boost::lexical_cast<Json::Value::ArrayIndex>(members[i]); + assert(key > 0); + result[key - 1] = source[members[i]]; + } + + return true; + } + + + bool LuaContext::GetJson(Json::Value& result, + lua_State *state, + int i) + { + // Caution: The order of the calls below is important, otherwise + // Lua considers everything as a string. + + if (lua_isnil(state, i)) + { + result = Json::nullValue; + return true; + } + + if (lua_isboolean(state, i)) + { + result = lua_toboolean(state, i) ? true : false; + return true; + } + + if (lua_isnumber(state, i)) + { + result = lua_tonumber(state, i); + return true; + } + + if (lua_isstring(state, i)) + { + result = lua_tostring(state, i); + return true; + } + + if (lua_istable(state, i)) + { + result = Json::objectValue; + + // http://stackoverflow.com/a/6142700/881731 + // Push another reference to the table on top of the stack (so we know + // where it is, and this function can work for negative, positive and + // pseudo indices + lua_pushvalue(state, i); + // stack now contains: -1 => table + lua_pushnil(state); + // stack now contains: -1 => nil; -2 => table + while (lua_next(state, -2)) + { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(state, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + const char *key = lua_tostring(state, -1); + + Json::Value item; + if (!GetJson(item, state, -2)) + { + lua_pop(state, 3); // TODO IS THIS CORRECT? + return false; + } + + result[key] = item; + + // pop value + copy of key, leaving original key + lua_pop(state, 2); + // stack now contains: -1 => key; -2 => table + } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key + // but does not push anything.) + // Pop table + lua_pop(state, 1); + + // Stack is now the same as it was on entry to this function + + Json::Value array; + if (CompactObjectToArray(array, result)) + { + result = array; + } + + return true; + } + + return false; + } + + LuaContext::LuaContext() { lua_ = luaL_newstate(); @@ -358,7 +515,8 @@ luaL_openlibs(lua_); lua_register(lua_, "print", PrintToLog); - lua_register(lua_, "ParseJson", ParseJsonString); + lua_register(lua_, "ParseJson", ParseJson); + lua_register(lua_, "DumpJson", DumpJson); lua_register(lua_, "HttpGet", CallHttpGet); lua_register(lua_, "HttpPost", CallHttpPost); lua_register(lua_, "HttpPut", CallHttpPut);