summaryrefslogtreecommitdiffstats
path: root/src/uscxml/messages
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2017-01-13 16:47:44 (GMT)
committerStefan Radomski <github@mintwerk.de>2017-01-13 16:47:44 (GMT)
commit4f6cbe9e7aec2b4a6c8f286f9097abfb011a6235 (patch)
tree8c023473bb342780ddf51a893d18369f1319bb5c /src/uscxml/messages
parent0aa0fe08dc308c94379c47d0bf9745e341cb4c81 (diff)
downloaduscxml-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.cpp143
-rw-r--r--src/uscxml/messages/Data.h10
-rw-r--r--src/uscxml/messages/Event.cpp58
-rw-r--r--src/uscxml/messages/Event.h18
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;