diff options
author | Stefan Radomski <github@mintwerk.de> | 2017-01-13 16:47:44 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2017-01-13 16:47:44 (GMT) |
commit | 4f6cbe9e7aec2b4a6c8f286f9097abfb011a6235 (patch) | |
tree | 8c023473bb342780ddf51a893d18369f1319bb5c /src/uscxml/messages | |
parent | 0aa0fe08dc308c94379c47d0bf9745e341cb4c81 (diff) | |
download | uscxml-4f6cbe9e7aec2b4a6c8f286f9097abfb011a6235.zip uscxml-4f6cbe9e7aec2b4a6c8f286f9097abfb011a6235.tar.gz uscxml-4f6cbe9e7aec2b4a6c8f286f9097abfb011a6235.tar.bz2 |
First support for serialization and some bug fixes for DOM per data.src
Diffstat (limited to 'src/uscxml/messages')
-rw-r--r-- | src/uscxml/messages/Data.cpp | 143 | ||||
-rw-r--r-- | src/uscxml/messages/Data.h | 10 | ||||
-rw-r--r-- | src/uscxml/messages/Event.cpp | 58 | ||||
-rw-r--r-- | src/uscxml/messages/Event.h | 18 |
4 files changed, 189 insertions, 40 deletions
diff --git a/src/uscxml/messages/Data.cpp b/src/uscxml/messages/Data.cpp index de9644b..277b7d8 100644 --- a/src/uscxml/messages/Data.cpp +++ b/src/uscxml/messages/Data.cpp @@ -101,8 +101,7 @@ Data Data::fromJSON(const std::string& jsonString) { } t = (jsmntok_t*)malloc((nrTokens + 1) * sizeof(jsmntok_t)); if (t == NULL) { - throw ErrorEvent("Cannot parse JSON, ran out of memory!"); - return data; + ERROR_PLATFORM_THROW("Cannot parse JSON, ran out of memory!"); } memset(t, 0, (nrTokens + 1) * sizeof(jsmntok_t)); @@ -111,15 +110,18 @@ Data Data::fromJSON(const std::string& jsonString) { if (rv != 0) { switch (rv) { - case JSMN_ERROR_NOMEM: - throw ErrorEvent("Cannot parse JSON, not enough tokens were provided!"); + case JSMN_ERROR_NOMEM: { + ERROR_PLATFORM_THROW("Cannot parse JSON, not enough tokens were provided!"); break; - case JSMN_ERROR_INVAL: - throw ErrorEvent("Cannot parse JSON, invalid character inside JSON string!"); + } + case JSMN_ERROR_INVAL: { + ERROR_PLATFORM_THROW("Cannot parse JSON, invalid character inside JSON string!"); break; - case JSMN_ERROR_PART: - throw ErrorEvent("Cannot parse JSON, the string is not a full JSON packet, more bytes expected!"); + } + case JSMN_ERROR_PART: { + ERROR_PLATFORM_THROW("Cannot parse JSON, the string is not a full JSON packet, more bytes expected!"); break; + } default: break; } @@ -151,10 +153,11 @@ Data Data::fromJSON(const std::string& jsonString) { dataStack.back()->type = Data::VERBATIM; case JSMN_PRIMITIVE: { std::string value = trimmed.substr(t[currTok].start, t[currTok].end - t[currTok].start); - if (dataStack.back()->type == Data::VERBATIM) { - boost::replace_all(value, "\\\"", "\""); - boost::replace_all(value, "\\n", "\n"); - } +// if (dataStack.back()->type == Data::VERBATIM) { +// boost::replace_all(value, "\\\"", "\""); +// boost::replace_all(value, "\\n", "\n"); +// } + value = jsonUnescape(value); dataStack.back()->atom = value; dataStack.pop_back(); currTok++; @@ -182,7 +185,7 @@ Data Data::fromJSON(const std::string& jsonString) { if (tokenStack.back().type == JSMN_OBJECT && (t[currTok].type == JSMN_PRIMITIVE || t[currTok].type == JSMN_STRING)) { // grab key and push new data - std::string value = trimmed.substr(t[currTok].start, t[currTok].end - t[currTok].start); + std::string value = jsonUnescape(trimmed.substr(t[currTok].start, t[currTok].end - t[currTok].start)); dataStack.push_back(&(dataStack.back()->compound[value])); currTok++; } @@ -230,7 +233,7 @@ std::string Data::toJSON(const Data& data) { os << std::endl << indent << "{"; compoundIter = data.compound.begin(); while(compoundIter != data.compound.end()) { - os << seperator << std::endl << indent << " \"" << compoundIter->first << "\": " << keyPadding.substr(0, longestKey - compoundIter->first.size()); + os << seperator << std::endl << indent << " \"" << jsonEscape(compoundIter->first) << "\": " << keyPadding.substr(0, longestKey - compoundIter->first.size()); _dataIndentation += 1; os << compoundIter->second; _dataIndentation -= 1; @@ -254,38 +257,110 @@ std::string Data::toJSON(const Data& data) { } else if (data.atom.size() > 0) { // empty string is handled below if (data.type == Data::VERBATIM) { - os << "\""; - for (size_t i = 0; i < data.atom.size(); i++) { - // escape string - if (false) { - } else if (data.atom[i] == '"') { - os << "\\\""; - } else if (data.atom[i] == '\n') { - os << "\\n"; - } else if (data.atom[i] == '\t') { - os << "\\t"; - } else { - os << data.atom[i]; - } - } - os << "\""; + os << "\"" << jsonEscape(data.atom) << "\""; } else { os << data.atom; } } else if (data.node) { std::ostringstream xmlSerSS; - xmlSerSS << data.node; + xmlSerSS << *data.node; std::string xmlSer = xmlSerSS.str(); - boost::replace_all(xmlSer, "\"", "\\\""); - boost::replace_all(xmlSer, "\n", "\\n"); - boost::replace_all(xmlSer, "\t", "\\t"); - os << "\"" << xmlSer << "\""; +// boost::replace_all(xmlSer, "\"", "\\\""); +// boost::replace_all(xmlSer, "\n", "\\n"); +// boost::replace_all(xmlSer, "\t", "\\t"); + os << "\"" << jsonEscape(xmlSer) << "\""; } else { if (data.type == Data::VERBATIM) { os << "\"\""; // empty string + } else { + os << "null"; // non object } } return os.str(); } +std::string Data::jsonUnescape(const std::string& expr) { + + // http://stackoverflow.com/a/19636328/990120 + bool escape = false; + std::string output; + output.reserve(expr.length()); + + for (std::string::size_type i = 0; i < expr.length(); ++i) { + if (escape) { + switch(expr[i]) { + case '"': + output += '\"'; + break; + case '/': + output += '/'; + break; + case 'b': + output += '\b'; + break; + case 'f': + output += '\f'; + break; + case 'n': + output += '\n'; + break; + case 'r': + output += '\r'; + break; + case 't': + output += '\t'; + break; + case '\\': + output += '\\'; + break; + default: + output += expr[i]; + break; + } + escape = false; + } else { + switch(expr[i]) { + case '\\': + escape = true; + break; + default: + output += expr[i]; + break; + } + } + } + return output; + +} + +std::string Data::jsonEscape(const std::string& expr) { + std::stringstream os; + for (size_t i = 0; i < expr.size(); i++) { + // escape string + if (false) { + } else if (expr[i] == '\t') { + os << "\\t"; + } else if (expr[i] == '\v') { + os << "\\v"; + } else if (expr[i] == '\b') { + os << "\\b"; + } else if (expr[i] == '\f') { + os << "\\f"; + } else if (expr[i] == '\n') { + os << "\\n"; + } else if (expr[i] == '\r') { + os << "\\r"; + } else if (expr[i] == '\'') { + os << "\\'"; + } else if (expr[i] == '\"') { + os << "\\\""; + } else if (expr[i] == '\\') { + os << "\\\\"; + } else { + os << expr[i]; + } + } + + return os.str(); +} } diff --git a/src/uscxml/messages/Data.h b/src/uscxml/messages/Data.h index 17d37cb..19134dd 100644 --- a/src/uscxml/messages/Data.h +++ b/src/uscxml/messages/Data.h @@ -71,14 +71,15 @@ public: explicit Data(T value, Type type, typename std::enable_if<! std::is_base_of<Data, T>::value>::type* = nullptr) : node(NULL), atom(toStr(value)), type(type) {} - ~Data() {} + ~Data() { + } void clear() { type = VERBATIM; compound.clear(); array.clear(); atom.clear(); - adoptedDoc.reset(); +// adoptedDoc.reset(); binary = Blob(); node = NULL; } @@ -234,7 +235,7 @@ protected: #endif XERCESC_NS::DOMNode* node; - std::shared_ptr<XERCESC_NS::DOMDocument> adoptedDoc; +// std::shared_ptr<XERCESC_NS::DOMDocument> adoptedDoc; std::map<std::string, Data> compound; std::list<Data> array; std::string atom; @@ -242,7 +243,10 @@ protected: Type type; protected: + static std::string jsonEscape(const std::string& expr); + static std::string jsonUnescape(const std::string& expr); friend USCXML_API std::ostream& operator<< (std::ostream& os, const Data& data); + }; USCXML_API std::ostream& operator<< (std::ostream& os, const Data& data); diff --git a/src/uscxml/messages/Event.cpp b/src/uscxml/messages/Event.cpp index c4aa642..f372798 100644 --- a/src/uscxml/messages/Event.cpp +++ b/src/uscxml/messages/Event.cpp @@ -22,6 +22,62 @@ namespace uscxml { +Event Event::fromData(const Data& data) { + Event e; + if (data.hasKey("data")) + e.data = Data(data["data"]); + if (data.hasKey("raw")) + e.raw = data["raw"].atom; + if (data.hasKey("name")) + e.name = data["name"].atom; + if (data.hasKey("eventType")) + e.eventType = (Type)strTo<size_t>(data["eventType"].atom); + if (data.hasKey("origin")) + e.origin = data["origin"].atom; + if (data.hasKey("origintype")) + e.origintype = data["origintype"].atom; + if (data.hasKey("sendid")) + e.sendid = data["sendid"].atom; + if (data.hasKey("hideSendId")) + e.hideSendId = strTo<bool>(data["hideSendId"].atom); + if (data.hasKey("invokeid")) + e.invokeid = data["invokeid"].atom; + if (data.hasKey("uuid")) + e.uuid = data["uuid"].atom; + if (data.hasKey("namelist")) + e.namelist = data["namelist"].compound; + + if (data.hasKey("params")) { + for (auto param : data["params"].array) { + e.params.insert(std::make_pair(param.compound.begin()->first, param.compound.begin()->second)); + } + } + return e; +} + +Event::operator Data() { + Data data; + data["data"] = data; + data["raw"] = Data(raw, Data::VERBATIM); + data["name"] = Data(name, Data::VERBATIM); + data["eventType"] = Data(eventType, Data::VERBATIM); + data["origin"] = Data(origin, Data::VERBATIM); + data["origintype"] = Data(origintype, Data::VERBATIM); + data["sendid"] = Data(sendid, Data::VERBATIM); + data["hideSendId"] = Data(hideSendId, Data::VERBATIM); + data["invokeid"] = Data(invokeid, Data::VERBATIM); + data["uuid"] = Data(uuid, Data::VERBATIM); + data["namelist"].compound = namelist; + + for (auto param : params) { + Data entry; + entry.compound[param.first] = param.second; + data["params"].array.push_back(entry); + } + + return data; +} + std::ostream& operator<< (std::ostream& os, const Event& event) { std::string indent; for (size_t i = 0; i < _dataIndentation; i++) { @@ -67,4 +123,4 @@ std::ostream& operator<< (std::ostream& os, const Event& event) { return os; } -}
\ No newline at end of file +} diff --git a/src/uscxml/messages/Event.h b/src/uscxml/messages/Event.h index 59b2690..b774f8a 100644 --- a/src/uscxml/messages/Event.h +++ b/src/uscxml/messages/Event.h @@ -24,20 +24,26 @@ #include "uscxml/util/UUID.h" #define ERROR_PLATFORM_THROW(msg) \ - ErrorEvent e; \ + uscxml::ErrorEvent e; \ e.name = "error.platform"; \ - e.data.compound["cause"] = Data(msg, Data::VERBATIM); \ + e.data.compound["cause"] = uscxml::Data(msg, uscxml::Data::VERBATIM); \ + e.data.compound["file"] = uscxml::Data(uscxml::toStr(__FILE__), uscxml::Data::VERBATIM); \ + e.data.compound["line"] = uscxml::Data(uscxml::toStr(__LINE__), uscxml::Data::INTERPRETED); \ throw e; \ #define ERROR_EXECUTION(identifier, cause) \ uscxml::ErrorEvent identifier; \ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \ + identifier.data.compound["file"] = uscxml::Data(uscxml::toStr(__FILE__), uscxml::Data::VERBATIM); \ + identifier.data.compound["line"] = uscxml::Data(uscxml::toStr(__LINE__), uscxml::Data::INTERPRETED); \ identifier.name = "error.execution"; \ identifier.eventType = uscxml::Event::PLATFORM; #define ERROR_EXECUTION2(identifier, cause, node) \ uscxml::ErrorEvent identifier; \ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \ + identifier.data.compound["file"] = uscxml::Data(uscxml::toStr(__FILE__), uscxml::Data::VERBATIM); \ + identifier.data.compound["line"] = uscxml::Data(uscxml::toStr(__LINE__), uscxml::Data::INTERPRETED); \ identifier.name = "error.execution"; \ identifier.data.compound["xpath"] = uscxml::Data(DOMUtils::xPathForNode(node), uscxml::Data::VERBATIM); \ identifier.eventType = uscxml::Event::PLATFORM; @@ -45,12 +51,16 @@ #define ERROR_COMMUNICATION(identifier, cause) \ uscxml::ErrorEvent identifier; \ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \ + identifier.data.compound["file"] = uscxml::Data(uscxml::toStr(__FILE__), uscxml::Data::VERBATIM); \ + identifier.data.compound["line"] = uscxml::Data(uscxml::toStr(__LINE__), uscxml::Data::INTERPRETED); \ identifier.name = "error.communication"; \ identifier.eventType = uscxml::Event::PLATFORM; #define ERROR_COMMUNICATION2(identifier, cause, node) \ uscxml::ErrorEvent identifier; \ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \ + identifier.data.compound["file"] = uscxml::Data(uscxml::toStr(__FILE__), uscxml::Data::VERBATIM); \ + identifier.data.compound["line"] = uscxml::Data(uscxml::toStr(__LINE__), uscxml::Data::INTERPRETED); \ identifier.name = "error.communication"; \ identifier.data.compound["xpath"] = uscxml::Data(DOMUtils::xPathForNode(node), uscxml::Data::VERBATIM); \ identifier.eventType = uscxml::Event::PLATFORM; @@ -91,6 +101,8 @@ public: Event() : eventType(INTERNAL), hideSendId(false), uuid(UUID::getUUID()) {} explicit Event(const std::string& name, Type type = INTERNAL) : name(name), eventType(type), hideSendId(false) {} + static Event fromData(const Data& data); + bool operator< (const Event& other) const { return this < &other; } @@ -109,6 +121,8 @@ public: return name.size() > 0; } + operator Data(); + operator std::string() { std::stringstream ss; ss << *this; |