diff options
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 Binary files differdeleted file mode 100644 index 368f327..0000000 --- a/src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swp +++ /dev/null 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"); |