diff options
Diffstat (limited to 'src/uscxml/messages/Data.h')
-rw-r--r-- | src/uscxml/messages/Data.h | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/src/uscxml/messages/Data.h b/src/uscxml/messages/Data.h new file mode 100644 index 0000000..bf13409 --- /dev/null +++ b/src/uscxml/messages/Data.h @@ -0,0 +1,243 @@ +/** + * @file + * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#ifndef DATA_H_09E4D8E5 +#define DATA_H_09E4D8E5 + +#include <list> +#include <map> + +#include <boost/shared_ptr.hpp> + +#include "uscxml/Common.h" +#include "uscxml/Convenience.h" +#include <DOM/Document.hpp> + +namespace uscxml { + +class Blob; + +static int _dataIndentation = 1; + +class USCXML_API Data { +public: + enum Type { + VERBATIM, + INTERPRETED, + }; + + Data() : type(INTERPRETED) {} + + // TODO: default INTERPRETED is unfortunate + Data(const std::string& atom_, Type type_ = INTERPRETED) : atom(atom_), type(type_) {} + Data(const char* data, size_t size, const std::string& mimeType, bool adopt = false); + + // convenience constructors + Data(short atom_) : atom(toStr(atom_)), type(INTERPRETED) {} + Data(int atom_) : atom(toStr(atom_)), type(INTERPRETED) {} + Data(unsigned int atom_) : atom(toStr(atom_)), type(INTERPRETED) {} + Data(long atom_) : atom(toStr(atom_)), type(INTERPRETED) {} + Data(unsigned long atom_) : atom(toStr(atom_)), type(INTERPRETED) {} + Data(float atom_) : atom(toStr(atom_)), type(INTERPRETED) {} + Data(double atom_) : atom(toStr(atom_)), type(INTERPRETED) {} + Data(bool atom_) : type(INTERPRETED) { + if (atom_) { + atom = "true"; + } else { + atom = "false"; + } + } + + template <typename T> Data(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 Data(const Arabica::DOM::Node<std::string>& dom); + virtual ~Data() {} + + 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); + + bool hasKey(const std::string& key) const { + return (!compound.empty() && compound.find(key) != compound.end()); + } + + Data& operator[](const std::string& key) { + 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)); + } + std::list<Data>::iterator arrayIter = array.begin(); + for (int i = 0; i < index; i++, arrayIter++) {} + return *arrayIter; + } + + const Data at(const std::string& key) const { + return at(key.c_str()); + } + + const Data at(const char* key) const { + if (hasKey(key)) + return compound.at(key); + Data data; + return data; + } + + const Data item(const size_t index) const { + if (array.size() < index) { + std::list<Data>::const_iterator arrayIter; + for (int i = 0; i < index; i++, arrayIter++) {} + return *arrayIter; + } + Data data; + return data; + } + + bool operator==(const Data &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 Data &other) const { + return !(*this == other); + } + + operator std::string() const { + return atom; + } + + operator std::map<std::string, Data>() { + return compound; + } + + operator std::list<Data>() { + return array; + } + + static Data fromJSON(const std::string& jsonString); + static std::string toJSON(const Data& data); + static Data fromXML(const std::string& xmlString); + Arabica::DOM::Document<std::string> toDocument(); + std::string toXMLString() { + std::stringstream ss; + ss << toDocument(); + return ss.str(); + } + + std::map<std::string, Data> getCompound() { + return compound; + } + void setCompound(const std::map<std::string, Data>& compound) { + this->compound = compound; + } + + std::list<Data> getArray() { + return array; + } + void setArray(const std::list<Data>& 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; + } + + +#ifdef SWIGIMPORTED +protected: +#endif + + Arabica::DOM::Node<std::string> node; + std::map<std::string, Data> compound; + std::list<Data> array; + std::string atom; + boost::shared_ptr<Blob> binary; + Type type; + +protected: + Arabica::DOM::Document<std::string> toNode(const Arabica::DOM::Document<std::string>& factory, const Data& data); + friend USCXML_API std::ostream& operator<< (std::ostream& os, const Data& data); +}; + +USCXML_API std::ostream& operator<< (std::ostream& os, const Data& data); + +} + +#endif /* end of include guard: DATA_H_09E4D8E5 */ |