diff options
author | Stefan Radomski <github@mintwerk.de> | 2017-05-29 12:21:44 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2017-05-29 12:21:44 (GMT) |
commit | 4799b35d2457f1cfc746701ea347c89ae9887ca9 (patch) | |
tree | 9501ae8cd763b8e5270cc9eeab9fbf7f0527d8a2 | |
parent | 361ce4a22955490e13adbd40eb594808142169a6 (diff) | |
download | uscxml-4799b35d2457f1cfc746701ea347c89ae9887ca9.zip uscxml-4799b35d2457f1cfc746701ea347c89ae9887ca9.tar.gz uscxml-4799b35d2457f1cfc746701ea347c89ae9887ca9.tar.bz2 |
Fixed issue 140
Lua table madness
-rw-r--r-- | src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp | 51 | ||||
-rw-r--r-- | test/CMakeLists.txt | 9 | ||||
-rw-r--r-- | test/issues/test-issue140.scxml | 70 | ||||
-rw-r--r-- | test/src/test-lua-tables.cpp | 115 |
4 files changed, 231 insertions, 14 deletions
diff --git a/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp index 9dcbc17..de3078b 100644 --- a/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp +++ b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp @@ -89,6 +89,14 @@ static Data getLuaAsData(lua_State* _luaState, const luabridge::LuaRef& lua) { // not sure what to do } else if(lua.isThread()) { // not sure what to do + } else if(lua.type() == LUA_TBOOLEAN) { + // why is there no isBoolean in luabridge? + if (lua) { + data.atom = "true"; + } else { + data.atom = "false"; + } + data.type = Data::INTERPRETED; } else if(lua.isNil()) { data.atom = "nil"; data.type = Data::INTERPRETED; @@ -99,20 +107,34 @@ static Data getLuaAsData(lua_State* _luaState, const luabridge::LuaRef& lua) { data.atom = lua.cast<std::string>(); data.type = Data::VERBATIM; } else if(lua.isTable()) { -// bool isArray = false; -// bool isMap = false; + // check whether it is to be interpreted as a map or an array + bool isArray = true; + std::map<std::string, luabridge::LuaRef> luaItems; for (luabridge::Iterator iter (lua); !iter.isNil(); ++iter) { luabridge::LuaRef luaKey = iter.key(); luabridge::LuaRef luaVal = *iter; - if (luaKey.isString()) { -// assert(!isArray); -// isMap = true; - // luaKey.tostring() is not working?! see issue84 - data.compound[luaKey.cast<std::string>()] = getLuaAsData(_luaState, luaVal); + + if (!luaKey.isNumber() || luaKey.cast<long>() <= 0) + isArray = false; + // this will implicitly sort the items + luaItems.insert(std::make_pair(luaKey.cast<std::string>(), luaVal)); + } + + size_t lastIndex = 0; + for (auto item : luaItems) { + if (isArray) { + // all indices are numeric -> array + size_t currIndex = strTo<size_t>(item.first); + while (currIndex > lastIndex + 1) { + data.array.push_back(Data("nil", Data::INTERPRETED)); + lastIndex++; + } + data.array.push_back(getLuaAsData(_luaState, item.second)); + lastIndex++; } else { -// assert(!isMap); -// isArray = true; - data.array.push_back(getLuaAsData(_luaState, luaVal)); + // there are some non-numeric indices -> map + data.compound[item.first] = getLuaAsData(_luaState, item.second); + } } } @@ -141,7 +163,12 @@ static luabridge::LuaRef getDataAsLua(lua_State* _luaState, const Data& data) { luaData = luabridge::newTable(_luaState); std::map<std::string, Data>::const_iterator compoundIter = data.compound.begin(); while(compoundIter != data.compound.end()) { - luaData[compoundIter->first] = getDataAsLua(_luaState, compoundIter->second); + if (isNumeric(compoundIter->first.c_str(), 10) && strTo<size_t>(compoundIter->first) > 0) { + // it makes a difference whether we pass a numeric string or a proper number! + luaData[strTo<size_t>(compoundIter->first)] = getDataAsLua(_luaState, compoundIter->second); + } else { + luaData[compoundIter->first] = getDataAsLua(_luaState, compoundIter->second); + } compoundIter++; } // luaData["inspect"] = luaInspect; @@ -492,7 +519,7 @@ void LuaDataModel::assign(const std::string& location, const Data& data, const s eval(location + "= __tmpAssign"); -// std::cout << Data::toJSON(evalAsData(location)) << std::endl; +// LOG(_callbacks->getLogger(), USCXML_INFO) << Data::toJSON(evalAsData(location)) << std::endl; } } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index efbc2fa..e76e249 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -64,6 +64,10 @@ USCXML_TEST_COMPILE(NAME test-lifecycle LABEL general/test-lifecycle FILES src/t USCXML_TEST_COMPILE(NAME test-validating LABEL general/test-validating FILES src/test-validating.cpp) USCXML_TEST_COMPILE(NAME test-snippets LABEL general/test-snippets FILES src/test-snippets.cpp) +if(WITH_DM_LUA) + USCXML_TEST_COMPILE(NAME test-lua-tables LABEL general/test-lua-tables FILES src/test-lua-tables.cpp) +endif() + if (NOT BUILD_AS_PLUGINS) USCXML_TEST_COMPILE( NAME test-serialization @@ -109,7 +113,6 @@ if (TARGET csharp) WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin COMMENT "Compiling C# TestStatePass" ) - add_dependencies(testStatePassCSharp csharp) else() ADD_CUSTOM_TARGET(testStatePassCSharp ALL COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/bin/csharp @@ -123,8 +126,10 @@ if (TARGET csharp) WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin COMMENT "Compiling C# TestStatePass" ) - add_dependencies(testStatePassCSharp csharp) endif() + add_dependencies(testStatePassCSharp csharp) + set_target_properties(testStatePassCSharp PROPERTIES FOLDER "Tests") + endif() if (WIN32 AND BUILD_SHARED_LIBS) diff --git a/test/issues/test-issue140.scxml b/test/issues/test-issue140.scxml new file mode 100644 index 0000000..6443344 --- /dev/null +++ b/test/issues/test-issue140.scxml @@ -0,0 +1,70 @@ + +<scxml datamodel="lua" initial="StateShape1" name="ScxmlShape1" version="1.0" xmlns="http://www.w3.org/2005/07/scxml"> + <datamodel> + <data id="t_DifficultTable">{ + [2] = { + [1]={ 5,5,5,5 }, + [2]={ 5,5,5,5 }, + [3]= { 10,10 } + }, + [1] = { + [1]= { 4,4,4,4,4,4,4,4 }, + [2]= { 8,8,8,8 }, + [3]= { 16,16 } + }, + [3] = { + [1]={ 2,2,2 }, + test = false, + good = true, + xxx = 'asdf' + }, + zzz = { + 1,2,3,"different types", + [[bbbbbbb\nbbbbbb]], + qq = "asdf 'asdf' [[asdf]]" + } +} + </data> + <data expr="{ + [3]=3, + [2]=2, + [1]=1 +}" id="t_mixed"/> + </datamodel> + <state id="StateShape1"> + <onentry> + <script>function PrintTable(t_val, s_tab) + if type(t_val)=="table" then + for k,v in pairs(t_val) do + print(string.format("%sk=%s[%s],v=%s[%s]",s_tab,tostring(k),type(k),tostring(v),type(v))) + PrintTable(v,s_tab .. "\t") + end + end +end + +PrintTable(t_DifficultTable,"") + </script> + <foreach array="t_mixed" index="s_index" item="s_item"> + <log expr="s_item" label="s_item"/> + <log expr="s_index" label="s_index"/> + </foreach> + </onentry> + <transition cond="t_DifficultTable[2][3][1]==10 and +#t_DifficultTable[1]==3 and +t_DifficultTable[3][1][2]==2 and +t_DifficultTable[3].test==false and +t_DifficultTable[3].xxx=="asdf" and +t_DifficultTable.zzz.qq=="asdf 'asdf' [[asdf]]" and +t_DifficultTable.zzz[1]==1 and +t_DifficultTable.zzz[2]==2 and +t_DifficultTable.zzz[3]==3 and +t_DifficultTable.zzz[4]=="different types" and +t_DifficultTable.zzz[5]==[[bbbbbbb\nbbbbbb]]" target="pass"/> + <transition event="error.*" target="fail"/> + <transition target="fail"/> + </state> + <final id="pass"/> + <final id="fail"> + <onentry/> + </final> +</scxml>
\ No newline at end of file diff --git a/test/src/test-lua-tables.cpp b/test/src/test-lua-tables.cpp new file mode 100644 index 0000000..3adea2d --- /dev/null +++ b/test/src/test-lua-tables.cpp @@ -0,0 +1,115 @@ +#include "uscxml/plugins/DataModel.h" +#include "uscxml/plugins/datamodel/lua/LuaDataModel.h" +#include "uscxml/plugins/Factory.h" +#include "uscxml/interpreter/Logging.h" + +#include <iostream> + +using namespace std; +using namespace uscxml; + +std::string test1 = "\ +{ \n\ + [1] = { 1, 1, 1, 1 }, \n\ + [2] = { 2, 2, 2, 2 }, \n\ + [3] = { 3, 3 }, \n\ + [7] = false, \n\ + [8] = true \n\ +}\ +"; + +std::string test2 = "\ +{ \ + zzz = { \ + [0] = { 1, 1, 1, 1 }, \ + [2] = { 5, 5, 5, 5 }, \ + [3] = { 10, 10 }, \ + [8] = { 80, 80 } \ + }, \ + bb = { \ + [3] = { 3, 3 }, \ + [2] = { 2, 2 } \ + } \ +}\ +"; + +std::string test3 = "\ +{ \n\ + [2] = { \n\ + [1]={ 5,5,5,5 }, \n\ + [2]={ 5,5,5,5 }, \n\ + [3]= { 10,10 } \n\ + }, \n\ + [1] = { \n\ + [1]= { 4,4,4,4,4,4,4,4 }, \n\ + [2]= { 8,8,8,8 }, \n\ + [3]= { 16,16 } \n\ + }, \n\ + [3] = { \n\ + [1]={ 2,2,2 }, \n\ + test = false, \n\ + good = true, \n\ + xxx = 'asdf' \n\ + }, \n\ + zzz = { \n\ + 1,2,3,\"different types\", \n\ + [[bbbbbbb\nbbbbbb]], \n\ + qq = \"asdf 'asdf' [[asdf]]\" \n\ + }\ +}\ +"; + +class DMCallbacks : public DataModelCallbacks { +public: + std::string name = "asdf"; + std::string sessionId = "asdf"; + std::map<std::string, IOProcessor> ioProcs; + std::map<std::string, Invoker> invokers; + + virtual ~DMCallbacks() {} + const std::string& getName() { + return name; + } + const std::string& getSessionId() { + return sessionId; + } + const std::map<std::string, IOProcessor>& getIOProcessors() { + return ioProcs; + } + virtual bool isInState(const std::string& stateId) { + return false; + } + virtual XERCESC_NS::DOMDocument* getDocument() const { + return nullptr; + } + virtual const std::map<std::string, Invoker>& getInvokers() { + return invokers; + } + virtual Logger getLogger() { + return Logger::getDefault(); + } + +}; + +int main(int argc, char** argv) { + try { + DataModel lua = Factory::getInstance()->createDataModel("lua", new DMCallbacks()); + std::cout << "TEST1:" << lua.evalAsData(test1).asJSON() << std::endl << std::endl; + std::cout << "TEST2:" << lua.evalAsData(test2).asJSON() << std::endl << std::endl; + std::cout << "TEST3:" << lua.evalAsData(test3).asJSON() << std::endl << std::endl; + + { + Data d1 = lua.evalAsData(test3); + lua.assign("mixedTable", d1); + Data d2 = lua.evalAsData("mixedTable"); + std::cout << "TEST3.2:" << d2.asJSON() << std::endl << std::endl; + Data d3 = lua.evalAsData("mixedTable.zzz"); + std::cout << "TEST3.3:" << d3.asJSON() << std::endl << std::endl; + Data d4 = lua.evalAsData("mixedTable[1]"); + std::cout << "TEST3.4:" << d4.asJSON() << std::endl << std::endl; + + } + } catch (Event e) { + std::cout << e << std::endl; + } +} |