summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-05-23 10:50:59 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-05-23 10:50:59 (GMT)
commit9f3dfcd9982cff90cf0466413d17fc1061c43f00 (patch)
treee29d0f70ecdfb742e3bbbc522e87281c8bbd58e7
parent216e8efb0f1aff9afd3881ab89b49e017e255228 (diff)
downloaduscxml-9f3dfcd9982cff90cf0466413d17fc1061c43f00.zip
uscxml-9f3dfcd9982cff90cf0466413d17fc1061c43f00.tar.gz
uscxml-9f3dfcd9982cff90cf0466413d17fc1061c43f00.tar.bz2
Fixed the 100% CPU utilization bug and replaced the bool() cast operator for data by empty()
-rw-r--r--CMakeLists.txt37
-rwxr-xr-xcontrib/local/compress_and_upload_deps.sh1
-rw-r--r--src/uscxml/Message.cpp2
-rw-r--r--src/uscxml/Message.h19
-rw-r--r--src/uscxml/debug/DebuggerServlet.cpp8
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp4
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp4
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp4
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp4
-rw-r--r--src/uscxml/plugins/element/file/FileElement.cpp2
-rw-r--r--src/uscxml/plugins/invoker/CMakeLists.txt2
-rw-r--r--src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.cpp2
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp2
-rw-r--r--src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swpbin16384 -> 0 bytes
-rw-r--r--src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp4
-rw-r--r--src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp10
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp2
-rw-r--r--src/uscxml/plugins/ioprocessor/comet/CometIOProcessor.cpp2
-rw-r--r--src/uscxml/server/InterpreterServlet.cpp14
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/src/test-datamodel.cpp179
21 files changed, 255 insertions, 49 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3d4b2ea..909b167 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -370,21 +370,29 @@ elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
add_definitions("-D_SCL_SECURE_NO_WARNINGS")
add_definitions("-D_CRT_SECURE_NO_WARNINGS")
add_definitions("/bigobj")
-
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GL")
-
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LTCG")
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LTCG")
- set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /LTCG")
- set(STATIC_LIBRARY_FLAGS "${STATIC_LIBRARY_FLAGS} /LTCG")
- # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:LIBCMT")
- # set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:LIBCMT")
- # set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /NODEFAULTLIB:LIBCMT")
- # set(STATIC_LIBRARY_FLAGS "${STATIC_LIBRARY_FLAGS} /NODEFAULTLIB:LIBCMT")
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GL") # /LTCG is implied with /GL.
+
+ # be very clear about linking debug / non-debug C++ runtimes
+ foreach(FLAGS CMAKE_EXE_LINKER_FLAGS_RELEASE CMAKE_SHARED_LINKER_FLAGS_RELEASE CMAKE_MODULE_LINKER_FLAGS_RELEASE)
+ set(${FLAGS} "${${FLAGS}} /ignore:4099 /NODEFAULTLIB:MSVCRTD")
+ endforeach()
+
+ # use static MSVCRT
+ # foreach(FLAGS
+ # CMAKE_C_FLAGS_DEBUG
+ # CMAKE_C_FLAGS_MINSIZEREL
+ # CMAKE_C_FLAGS_RELEASE
+ # CMAKE_C_FLAGS_RELWITHDEBINFO
+ # CMAKE_CXX_FLAGS_DEBUG
+ # CMAKE_CXX_FLAGS_MINSIZEREL
+ # CMAKE_CXX_FLAGS_RELEASE
+ # CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ # if(${FLAGS} MATCHES "/MD")
+ # string(REGEX REPLACE "/MD" "/MT" ${FLAGS} "${${FLAGS}}")
+ # endif()
+ # endforeach()
- # SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB")
- # SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRTD.lib")
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-parentheses-equality")
@@ -796,7 +804,7 @@ find_package(MILES)
#set(JPEG_ROOT_PATH "" CACHE STRING "Where to find libjpeg")
if (MILES_FOUND)
- if (OFF)
+ if (NOT WIN32)
# openal is only needed for miles
find_package(OpenAL)
find_package(JPEG)
@@ -937,6 +945,7 @@ endif()
if (NOT CMAKE_CROSSCOMPILING)
add_executable(uscxml-browser apps/uscxml-browser.cpp)
target_link_libraries(uscxml-browser uscxml)
+
if (NOT CMAKE_CROSSCOMPILING)
set_target_properties(uscxml-browser PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
# cotire(uscxml-browser)
diff --git a/contrib/local/compress_and_upload_deps.sh b/contrib/local/compress_and_upload_deps.sh
index 5a2cea3..4abb4a9 100755
--- a/contrib/local/compress_and_upload_deps.sh
+++ b/contrib/local/compress_and_upload_deps.sh
@@ -33,6 +33,7 @@ ssh ${USCXML_PREBUILT_HOST} mkdir -p ${USCXML_PREBUILT_PATH}/${VERSION}
PLATFORMS=`find . -maxdepth 1 -type d -regex ./[^\.].*`
#PLATFORMS="linux-x86_64"
#PLATFORMS="darwin-i386"
+PLATFORMS="windows-x86"
for FILE in ${PLATFORMS}; do
PLATFORM=`basename $FILE`
echo $FILE
diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp
index 55be0e4..0a0eed0 100644
--- a/src/uscxml/Message.cpp
+++ b/src/uscxml/Message.cpp
@@ -488,7 +488,7 @@ Data Data::fromJSON(const std::string& jsonString) {
void Event::initContent(const std::string& content) {
// try to parse as JSON
Data json = Data::fromJSON(content);
- if (json) {
+ if (!json.empty()) {
data = json;
return;
}
diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h
index 57e8680..27b2ac5 100644
--- a/src/uscxml/Message.h
+++ b/src/uscxml/Message.h
@@ -106,8 +106,15 @@ public:
explicit Data(const Arabica::DOM::Node<std::string>& dom);
virtual ~Data() {}
- operator bool() const {
- return (atom.length() > 0 || !compound.empty() || !array.empty() || binary || node);
+ bool empty() const {
+ bool hasContent = (atom.length() > 0 || !compound.empty() || !array.empty() || binary || node);
+ return !hasContent;
+ }
+
+ bool operator<(const Data& other) const {
+ std::string thisJSON = Data::toJSON(*this);
+ std::string otherJSON = Data::toJSON(other);
+ return (thisJSON < otherJSON);
}
void merge(const Data& other);
@@ -120,10 +127,18 @@ public:
return operator[](key.c_str());
}
+ const Data& operator[](const std::string& key) const {
+ return operator[](key.c_str());
+ }
+
Data& operator[](const char* key) {
return compound[key];
}
+ const Data& operator[](const char* key) const {
+ return compound.at(key);
+ }
+
Data& operator[](const size_t index) {
while(array.size() < index) {
array.push_back(Data("", Data::VERBATIM));
diff --git a/src/uscxml/debug/DebuggerServlet.cpp b/src/uscxml/debug/DebuggerServlet.cpp
index a99aaf8..17c11d6 100644
--- a/src/uscxml/debug/DebuggerServlet.cpp
+++ b/src/uscxml/debug/DebuggerServlet.cpp
@@ -24,7 +24,7 @@
namespace uscxml {
void DebuggerServlet::pushData(boost::shared_ptr<DebugSession> session, Data pushData) {
- std::cout << "trying to push " << pushData["replyType"].atom << std::endl;
+ std::cout << "trying to push " << pushData.at("replyType").atom << std::endl;
if (!session) {
if (_sendQueues.size() > 0) // logging is not aware of its interpreter
@@ -44,7 +44,7 @@ void DebuggerServlet::serverPushData(boost::shared_ptr<DebugSession> session) {
return;
Data reply = _sendQueues[session].pop();
- std::cout << "pushing " << reply["replyType"].atom << std::endl;
+ std::cout << "pushing " << reply.at("replyType").atom << std::endl;
returnData(_clientConns[session], reply);
_clientConns[session] = HTTPServer::Request();
}
@@ -117,7 +117,7 @@ bool DebuggerServlet::httpRecvRequest(const HTTPServer::Request& request) {
replyData.compound["status"] = Data("failure", Data::VERBATIM);
replyData.compound["reason"] = Data("No such session", Data::VERBATIM);
}
- if (replyData) {
+ if (!replyData.empty()) {
returnData(request, replyData);
return true;
}
@@ -165,7 +165,7 @@ bool DebuggerServlet::httpRecvRequest(const HTTPServer::Request& request) {
replyData = session->debugEval(request.data["content"]);
}
- if (replyData) {
+ if (!replyData.empty()) {
returnData(request, replyData);
return true;
}
diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp
index 8be2634..12d6123 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.cpp
+++ b/src/uscxml/interpreter/InterpreterDraft6.cpp
@@ -121,7 +121,8 @@ NodeSet<std::string> InterpreterDraft6::getDocumentInitialTransitions() {
// a macrostep
InterpreterState InterpreterDraft6::step(bool blocking) {
try {
-
+ tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+
monIter_t monIter;
NodeSet<std::string> enabledTransitions;
@@ -147,6 +148,7 @@ InterpreterState InterpreterDraft6::step(bool blocking) {
// read an external event and react
if (blocking) {
+
// wait until an event becomes available
while(_externalQueue.isEmpty()) {
_condVar.wait(_mutex);
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index a064394..a6909b5 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -222,7 +222,7 @@ void JSCDataModel::setEvent(const Event& event) {
} else if (event.content.length() > 0) {
// _event.data is a string or JSON
Data json = Data::fromJSON(event.content);
- if (json) {
+ if (!json.empty()) {
JSStringRef propName = JSStringCreateWithUTF8CString("data");
JSObjectSetProperty(_ctx, eventObj, propName, getDataAsValue(json), 0, &exception);
JSStringRelease(propName);
@@ -255,7 +255,7 @@ void JSCDataModel::setEvent(const Event& event) {
nameListIter++;
}
}
- if (eventCopy.data > 0) {
+ if (!eventCopy.data.empty()) {
JSStringRef propName = JSStringCreateWithUTF8CString("data");
JSObjectSetProperty(_ctx, eventObj, propName, getDataAsValue(eventCopy.data), 0, &exception);
JSStringRelease(propName);
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
index ec9557e..2bdd796 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
@@ -233,7 +233,7 @@ void V8DataModel::setEvent(const Event& event) {
} else if (event.content.length() > 0) {
// _event.data is a string or JSON
Data json = Data::fromJSON(event.content);
- if (json) {
+ if (!json.empty()) {
eventObj->Set(v8::String::New("data"), getDataAsValue(json));
} else {
eventObj->Set(v8::String::New("data"), v8::String::New(InterpreterImpl::spaceNormalize(event.content).c_str()));
@@ -255,7 +255,7 @@ void V8DataModel::setEvent(const Event& event) {
nameListIter++;
}
}
- if (eventCopy.data) {
+ if (!eventCopy.data.empty()) {
// std::cout << Data::toJSON(eventCopy.data);
eventObj->Set(v8::String::New("data"), getDataAsValue(eventCopy.data)); // set data part of _event
} else {
diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
index 4cbe8f5..76c4373 100644
--- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
@@ -276,7 +276,7 @@ void SWIDataModel::setEvent(const Event& event) {
PlCall(dataInitStr.str().c_str());
} else if (event.content.size() > 0) {
PlCall("assert", PlCompound("event", PlCompound("data", PlString(InterpreterImpl::spaceNormalize(event.content).c_str()))));
- } else if (event.data) {
+ } else if (!event.data.empty()) {
assertFromData(event.data, "event(data(", 2);
}
@@ -817,7 +817,7 @@ void SWIDataModel::assign(const Element<std::string>& assignElem,
PlCall("retractall", PlCompound(predicate.c_str(), 1));
dataInitStr << "load_xml_file('" << domUrl.asLocalFile(".pl") << "', XML), copy_term(XML,DATA), " << callAssert << "(" << predicate << "(DATA))";
PlCall(dataInitStr.str().c_str());
- } else if (json) {
+ } else if (!json.empty()) {
std::stringstream dataInitStr;
if (iequals(type, "retract"))
PlCall("retractall", PlCompound(predicate.c_str(), 1));
diff --git a/src/uscxml/plugins/element/file/FileElement.cpp b/src/uscxml/plugins/element/file/FileElement.cpp
index aef63aa..899c2d6 100644
--- a/src/uscxml/plugins/element/file/FileElement.cpp
+++ b/src/uscxml/plugins/element/file/FileElement.cpp
@@ -223,7 +223,7 @@ void FileElement::enterElement(const Arabica::DOM::Node<std::string>& node) {
case JSON: {
Data json = Data::fromJSON(fileContents);
free(fileContents);
- if (!json) {
+ if (json.empty()) {
LOG(ERROR) << "Cannot parse contents of " << _filepath << " as JSON";
return;
}
diff --git a/src/uscxml/plugins/invoker/CMakeLists.txt b/src/uscxml/plugins/invoker/CMakeLists.txt
index 8ae4516..ceb9c90 100644
--- a/src/uscxml/plugins/invoker/CMakeLists.txt
+++ b/src/uscxml/plugins/invoker/CMakeLists.txt
@@ -109,7 +109,7 @@ if (EXPECT_FOUND AND TCL_FOUND)
invoker_expect SHARED
${EXPECT_INVOKER}
"../Plugins.cpp")
- target_link_libraries(invoker_expect uscxml)
+ target_link_libraries(invoker_expect uscxml ${EXPECT_LIBRARY} ${TCL_LIBRARY})
set_target_properties(invoker_expect PROPERTIES FOLDER "Plugin Invoker")
else()
list (APPEND USCXML_FILES ${EXPECT_INVOKER})
diff --git a/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.cpp b/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.cpp
index f43e406..b6203d4 100644
--- a/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.cpp
+++ b/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.cpp
@@ -250,7 +250,7 @@ void FFMPEGInvoker::process(const SendRequest& req) {
Data image;
Event::getParam(req.params, "frame", image);
- if (!image) {
+ if (image.empty()) {
return;
}
diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp
index bc747a1..0ebf9b8 100644
--- a/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp
+++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp
@@ -394,7 +394,7 @@ void OSGConverter::reportSuccess(const SendRequest& req, const Data& content) {
event.name = "convert";
event.name += ".success";
- if (content)
+ if (!content.empty())
event.data.compound["content"] = content;
returnEvent(event);
}
diff --git a/src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swp b/src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swp
deleted file mode 100644
index 368f327..0000000
--- a/src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swp
+++ /dev/null
Binary files differ
diff --git a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp
index c84fd8f..6ef1bd4 100644
--- a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp
+++ b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp
@@ -77,10 +77,10 @@ void UmundoInvoker::send(const SendRequest& req) {
try {
Data data = req.data;
- if (!data && req.content.length())
+ if (data.empty() && req.content.length())
data = _interpreter->getDataModel().getStringAsData(req.content);
- if (!data) {
+ if (data.empty()) {
LOG(ERROR) << "Cannot transform content to data object per datamodel or no data given";
return;
}
diff --git a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
index e607cf4..0418f8a 100644
--- a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
@@ -81,7 +81,7 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
} else {
// a POST request
Event ev(req);
- if (ev.data["header"]["X-SCXML-Name"]) {
+ if (ev.data["header"].hasKey("X-SCXML-Name")) {
ev.name = ev.data["header"]["X-SCXML-Name"].atom;
} else {
ev.name = req.data.at("type").atom;
@@ -101,7 +101,7 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
}
// initial request for a document
- if (!req.data["query"] && // no query parameters
+ if (!req.data.hasKey("query") && // no query parameters
iequals(req.data.at("type").atom, "get") && // request type is GET
req.content.length() == 0) { // no content
@@ -113,7 +113,7 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
// ss << _invokeReq.getFirstDOMElement();
ss << _invokeReq.dom;
content = ss.str();
- } else if(_invokeReq.data) {
+ } else if(!_invokeReq.data.empty()) {
ss << _invokeReq.data;
content = ss.str();
} else if (_invokeReq.content.length() > 0) {
@@ -163,7 +163,7 @@ void XHTMLInvoker::send(const SendRequest& req) {
SendRequest reqCopy(req);
_interpreter->getDataModel().replaceExpressions(reqCopy.content);
Data json = Data::fromJSON(reqCopy.content);
- if (json) {
+ if (!json.empty()) {
reqCopy.data = json;
}
@@ -195,7 +195,7 @@ void XHTMLInvoker::reply(const SendRequest& req, const HTTPServer::Request& long
ss << req.dom;
reply.content = ss.str();
reply.headers["Content-Type"] = "application/xml";
- } else if (req.data) {
+ } else if (!req.data.empty()) {
reply.content = Data::toJSON(req.data);
reply.headers["Content-Type"] = "application/json";
} else if (req.content.length() > 0) {
diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
index 9c1ba45..8489d60 100644
--- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
@@ -222,7 +222,7 @@ void BasicHTTPIOProcessor::send(const SendRequest& req) {
kvps << kvpSeperator << keyCStr << "=" << valueCStr;
free(valueCStr);
kvpSeperator = "&";
- } else if (req.data) {
+ } else if (!req.data.empty()) {
char* valueCStr = NULL;
if (req.data.atom.length() || req.data.array.size() || req.data.compound.size()) {
valueCStr = evhttp_encode_uri(Data::toJSON(req.data).c_str());
diff --git a/src/uscxml/plugins/ioprocessor/comet/CometIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/comet/CometIOProcessor.cpp
index 32052c7..cf11ec8 100644
--- a/src/uscxml/plugins/ioprocessor/comet/CometIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/comet/CometIOProcessor.cpp
@@ -82,7 +82,7 @@ void CometIOProcessor::reply(const SendRequest& req, const HTTPServer::Request&
ss << req.dom;
reply.content = ss.str();
reply.headers["Content-Type"] = "application/xml";
- } else if (req.data) {
+ } else if (!req.data.empty()) {
reply.content = Data::toJSON(req.data);
reply.headers["Content-Type"] = "application/json";
} else if (req.content.length() > 0) {
diff --git a/src/uscxml/server/InterpreterServlet.cpp b/src/uscxml/server/InterpreterServlet.cpp
index 303aad0..2bbb856 100644
--- a/src/uscxml/server/InterpreterServlet.cpp
+++ b/src/uscxml/server/InterpreterServlet.cpp
@@ -55,13 +55,13 @@ bool InterpreterHTTPServlet::httpRecvRequest(const HTTPServer::Request& req) {
event.name = "http." + event.data.compound["type"].atom;
event.origin = toStr((uintptr_t)req.evhttpReq);
- if (event.data.compound["content"]) {
+ if (!event.data.compound["content"].empty()) {
if (event.data.compound["content"].compound.size() > 0) {
std::map<std::string, Data>::iterator compoundIter = event.data.compound["content"].compound.begin();
while(compoundIter != event.data.compound["content"].compound.end()) {
// std::cout << compoundIter->second.atom << std::endl;
Data json = Data::fromJSON(compoundIter->second.atom);
- if (json) {
+ if (!json.empty()) {
// std::cout << Data::toJSON(json) << std::endl;
compoundIter->second = json;
}
@@ -119,12 +119,12 @@ bool InterpreterWebSocketServlet::wsRecvRequest(struct evws_connection *conn, co
event.name = "ws." + event.data.compound["type"].atom;
event.origin = toStr((uintptr_t)conn);
- if (event.data.compound["type"].atom.compare("text") == 0 && event.data.compound["content"]) {
+ if (event.data.compound["type"].atom.compare("text") == 0 && !event.data.compound["content"].empty()) {
if (event.data.compound["content"].compound.size() > 0) {
std::map<std::string, Data>::iterator compoundIter = event.data.compound["content"].compound.begin();
while(compoundIter != event.data.compound["content"].compound.end()) {
Data json = Data::fromJSON(compoundIter->second.atom);
- if (json) {
+ if (!json.empty()) {
compoundIter->second = json;
}
compoundIter++;
@@ -145,7 +145,7 @@ Data InterpreterWebSocketServlet::getDataModelVariables() {
void InterpreterWebSocketServlet::send(const SendRequest& req) {
- if (!req.data) {
+ if (req.data.empty()) {
LOG(WARNING) << "No content given to send on websocket!";
return;
}
@@ -166,7 +166,7 @@ void InterpreterWebSocketServlet::send(const SendRequest& req) {
EVWS_TEXT_FRAME,
data.c_str(),
data.length());
- } else if (req.data) {
+ } else if (!req.data.empty()) {
std::string data = Data::toJSON(req.data);
HTTPServer::wsSend(_requests[req.target],
EVWS_TEXT_FRAME,
@@ -191,7 +191,7 @@ void InterpreterWebSocketServlet::send(const SendRequest& req) {
EVWS_TEXT_FRAME,
data.c_str(),
data.length());
- } else if (req.data) {
+ } else if (!req.data.empty()) {
std::string data = Data::toJSON(req.data);
HTTPServer::wsBroadcast(req.target.c_str(),
EVWS_TEXT_FRAME,
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index f28633e..b655384 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -140,7 +140,7 @@ set_target_properties(test-datamodel PROPERTIES FOLDER "Tests")
if (EXPECT_FOUND AND TCL_FOUND)
add_executable(test-expect
src/test-expect.cpp)
- target_link_libraries(test-expect uscxml)
+ target_link_libraries(test-expect uscxml ${EXPECT_LIBRARY} ${TCL_LIBRARY})
set_target_properties(test-expect PROPERTIES FOLDER "Tests")
endif()
diff --git a/test/src/test-datamodel.cpp b/test/src/test-datamodel.cpp
index 452d2b9..58f7030 100644
--- a/test/src/test-datamodel.cpp
+++ b/test/src/test-datamodel.cpp
@@ -12,6 +12,177 @@
using namespace uscxml;
using namespace boost;
+class TestData {
+public:
+ enum Type {
+ VERBATIM,
+ INTERPRETED,
+ };
+
+ TestData() : type(INTERPRETED) {}
+
+ // TODO: default INTERPRETED is unfortunate
+ TestData(const std::string& atom_, Type type_ = INTERPRETED) : atom(atom_), type(type_) {}
+ TestData(const char* data, size_t size, const std::string& mimeType, bool adopt = false);
+
+ // convenience constructors
+ TestData(short atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ TestData(int atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ TestData(unsigned int atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ TestData(long atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ TestData(unsigned long atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ TestData(float atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ TestData(double atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ TestData(bool atom_) : type(INTERPRETED) {
+ if (atom_) {
+ atom = "true";
+ } else {
+ atom = "false";
+ }
+ }
+
+ template <typename T> TestData(T value, Type type_) : atom(toStr(value)), type(type_) {}
+
+#if 0
+ // constructor for arbitrary types, skip if type is subclass though (C++11)
+ // we will have to drop this constructor as it interferes with operator Data() and entails C++11
+ template <typename T>
+ Data(T value, typename std::enable_if<! std::is_base_of<Data, T>::value>::type* = nullptr)
+ : atom(toStr(value)), type(INTERPRETED) {}
+#endif
+
+
+ explicit TestData(const Arabica::DOM::Node<std::string>& dom);
+ virtual ~TestData() {}
+
+ explicit operator bool() const {
+ return (atom.length() > 0 || !compound.empty() || !array.empty() || binary || node);
+ }
+
+ bool hasKey(const std::string& key) const {
+ return (!compound.empty() && compound.find(key) != compound.end());
+ }
+
+ TestData& operator[](const std::string& key) {
+ return operator[](key.c_str());
+ }
+
+ TestData& operator[](const char* key) {
+ return compound[key];
+ }
+
+ TestData& operator[](const size_t index) {
+ while(array.size() < index) {
+ array.push_back(TestData("", TestData::VERBATIM));
+ }
+ std::list<TestData>::iterator arrayIter = array.begin();
+ for (int i = 0; i < index; i++, arrayIter++) {}
+ return *arrayIter;
+ }
+
+ const TestData at(const std::string& key) const {
+ return at(key.c_str());
+ }
+
+ const TestData at(const char* key) const {
+ if (hasKey(key))
+ return compound.at(key);
+ TestData data;
+ return data;
+ }
+
+ const TestData item(const size_t index) const {
+ if (array.size() < index) {
+ std::list<TestData>::const_iterator arrayIter;
+ for (int i = 0; i < index; i++, arrayIter++) {}
+ return *arrayIter;
+ }
+ TestData data;
+ return data;
+ }
+
+ bool operator==(const TestData &other) const {
+ if (other.atom.size() != atom.size())
+ return false;
+ if (other.type != type)
+ return false;
+ if (other.binary != binary)
+ return false;
+ if (other.array.size() != array.size())
+ return false;
+ if (other.compound.size() != compound.size())
+ return false;
+
+ if (other.atom != atom)
+ return false;
+ if (other.array != array)
+ return false;
+ if (other.compound != compound)
+ return false;
+ if (other.node != node)
+ return false;
+
+ return true;
+ }
+
+ bool operator!=(const TestData &other) const {
+ return !(*this == other);
+ }
+
+ operator std::string() const {
+ return atom;
+ }
+
+ operator std::map<std::string, TestData>() {
+ return compound;
+ }
+
+ operator std::list<TestData>() {
+ return array;
+ }
+
+ std::map<std::string, TestData> getCompound() {
+ return compound;
+ }
+ void setCompound(const std::map<std::string, TestData>& compound) {
+ this->compound = compound;
+ }
+
+ std::list<TestData> getArray() {
+ return array;
+ }
+ void setArray(const std::list<TestData>& array) {
+ this->array = array;
+ }
+
+ std::string getAtom() {
+ return atom;
+ }
+ void setAtom(const std::string& atom) {
+ this->atom = atom;
+ }
+
+ Type getType() {
+ return type;
+ }
+ void setType(const Type type) {
+ this->type = type;
+ }
+
+ Arabica::DOM::Node<std::string> node;
+ std::map<std::string, TestData> compound;
+ std::list<TestData> array;
+ std::string atom;
+ boost::shared_ptr<Blob> binary;
+ Type type;
+
+};
+
+
+
+void testConstData(const TestData& data) {
+// std::cout << data.at("foo") << std::endl;
+}
int main(int argc, char** argv) {
#ifdef _WIN32
@@ -19,6 +190,14 @@ int main(int argc, char** argv) {
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
+ {
+ TestData data;
+ data["foo"] = "bar";
+ testConstData(data);
+// std::cout << data << std::endl;
+ }
+ exit(0);
+
Interpreter interpreter = Interpreter::fromXML("<scxml></scxml>");
DataModel dm(Factory::getInstance()->createDataModel("ecmascript", interpreter.getImpl().get()));
dm.evalAsString("var foo = 12");