summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2017-05-29 12:21:44 (GMT)
committerStefan Radomski <github@mintwerk.de>2017-05-29 12:21:44 (GMT)
commit4799b35d2457f1cfc746701ea347c89ae9887ca9 (patch)
tree9501ae8cd763b8e5270cc9eeab9fbf7f0527d8a2
parent361ce4a22955490e13adbd40eb594808142169a6 (diff)
downloaduscxml-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.cpp51
-rw-r--r--test/CMakeLists.txt9
-rw-r--r--test/issues/test-issue140.scxml70
-rw-r--r--test/src/test-lua-tables.cpp115
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,&quot;different types&quot;,
+ [[bbbbbbb\nbbbbbb]],
+ qq = &quot;asdf 'asdf' [[asdf]]&quot;
+ }
+}
+ </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)==&quot;table&quot; then
+ for k,v in pairs(t_val) do
+ print(string.format(&quot;%sk=%s[%s],v=%s[%s]&quot;,s_tab,tostring(k),type(k),tostring(v),type(v)))
+ PrintTable(v,s_tab .. &quot;\t&quot;)
+ end
+ end
+end
+
+PrintTable(t_DifficultTable,&quot;&quot;)
+ </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==&quot;asdf&quot; and
+t_DifficultTable.zzz.qq==&quot;asdf 'asdf' [[asdf]]&quot; and
+t_DifficultTable.zzz[1]==1 and
+t_DifficultTable.zzz[2]==2 and
+t_DifficultTable.zzz[3]==3 and
+t_DifficultTable.zzz[4]==&quot;different types&quot; 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;
+ }
+}