diff options
Diffstat (limited to 'src/Common/XmlPacket.h')
-rw-r--r-- | src/Common/XmlPacket.h | 437 |
1 files changed, 437 insertions, 0 deletions
diff --git a/src/Common/XmlPacket.h b/src/Common/XmlPacket.h new file mode 100644 index 0000000..007404a --- /dev/null +++ b/src/Common/XmlPacket.h @@ -0,0 +1,437 @@ +/* + * XmlProcessor.h + * + * Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MAD_COMMON_XMLPACKET_H_ +#define MAD_COMMON_XMLPACKET_H_ + +#include <Net/Packet.h> + +#include <map> +#include <string> +#include <sstream> +#include <vector> + +#include <libxml/parser.h> + +namespace Mad { +namespace Common { + +class XmlPacket { + public: + class Entry; + class List; + + private: + xmlDocPtr doc; + xmlNodePtr packetNode; + Entry *entry; + + public: + + class Element { + public: + enum Type { + NONE, LIST, + INT, UINT, INT64, UINT64, + FLOAT, DOUBLE, LONGDOUBLE, STRING + }; + + protected: + friend class Entry; + + xmlNodePtr elementNode; + + private: + std::string str; + + Type type; + union Variant { + int var_int; + unsigned int var_uint; + + long long var_int64; + unsigned long long var_uint64; + + float var_float; + double var_double; + long double var_ldouble; + } value; + + static Entry nilEntry; + + template<typename T> + void set(T val) { + switch(type) { + case INT: + value.var_int = static_cast<int>(val); + break; + case UINT: + value.var_uint = static_cast<unsigned int>(val); + break; + case INT64: + value.var_int64 = static_cast<long long>(val); + break; + case UINT64: + value.var_uint64 = static_cast<unsigned long long>(val); + break; + case FLOAT: + value.var_float = static_cast<float>(val); + break; + case DOUBLE: + value.var_double = static_cast<double>(val); + break; + case LONGDOUBLE: + value.var_ldouble = static_cast<long double>(val); + break; + default: + break; + } + + updateStr(); + } + + void updateStr(); + + protected: + Element(xmlNodePtr node, Type type0) : elementNode(node), type(type0) {} + + public: + Element(xmlNodePtr node); + + Type getType() const { + return type; + } + + virtual size_t getSize() const { + return 0; + } + + virtual Entry& operator[](size_t) { + return nilEntry; + } + + virtual const Entry& operator[](size_t) const { + return nilEntry; + } + + virtual bool insertEntry(size_t) {return false;} + virtual bool addEntry() {return false;} + virtual bool removeEntry(size_t) {return false;} + + template<typename T> + operator T() { + switch(type) { + case INT: + return static_cast<T>(value.var_int); + case UINT: + return static_cast<T>(value.var_uint); + case INT64: + return static_cast<T>(value.var_int64); + case UINT64: + return static_cast<T>(value.var_uint64); + case FLOAT: + return static_cast<T>(value.var_float); + case DOUBLE: + return static_cast<T>(value.var_double); + case LONGDOUBLE: + return static_cast<T>(value.var_ldouble); + default: + return static_cast<T>(0); + } + } + + operator std::string() { + return str; + } + + const Element& operator=(int val) { + set(val); + return *this; + } + + const Element& operator=(unsigned int val) { + set(val); + return *this; + } + + const Element& operator=(long long val) { + set(val); + return *this; + } + + const Element& operator=(unsigned long long val) { + set(val); + return *this; + } + + const Element& operator=(float val) { + set(val); + return *this; + } + + const Element& operator=(double val) { + set(val); + return *this; + } + + const Element& operator=(long double val) { + set(val); + return *this; + } + + const Element& operator=(const std::string &val) { + if(type == STRING) { + str = val; + updateStr(); + } + + return *this; + } + }; + + class Entry { + private: + friend class List; + + xmlNodePtr entryNode; + + std::map<std::string, Element> elements; + std::map<std::string, List> lists; + + static Element nilElement; + + private: + bool add(const std::string &name, const std::string &value, const char *type) { + if(!entryNode) + return false; + + if(lists.find(name) != lists.end() || elements.find(name) != elements.end()) + return false; + + xmlNodePtr newNode = xmlNewTextChild(entryNode, 0, (xmlChar*)"value", (xmlChar*)value.c_str()); + xmlSetProp(newNode, (xmlChar*)"name", (xmlChar*)name.c_str()); + xmlSetProp(newNode, (xmlChar*)"type", (xmlChar*)type); + + if(!elements.insert(std::make_pair(name, Element(newNode))).second) { + xmlUnlinkNode(newNode); + xmlFreeNode(newNode); + + return false; + } + + return true; + } + + public: + Entry(xmlNodePtr node); + + Element& operator[](const std::string &name); + const Element& operator[](const std::string &name) const; + + bool add(const std::string &name, int val) { + std::ostringstream buf; + buf << val; + + return add(name, buf.str(), "int"); + } + + bool add(const std::string &name, unsigned int val) { + std::ostringstream buf; + buf << val; + + return add(name, buf.str(), "uint"); + } + + bool add(const std::string &name, long long val) { + std::ostringstream buf; + buf << val; + + return add(name, buf.str(), "int64"); + } + + bool add(const std::string &name, unsigned long long val) { + std::ostringstream buf; + buf << val; + + return add(name, buf.str(), "uint64"); + } + + bool add(const std::string &name, float val) { + std::ostringstream buf; + buf << val; + + return add(name, buf.str(), "float"); + } + + bool add(const std::string &name, double val) { + std::ostringstream buf; + buf << val; + + return add(name, buf.str(), "double"); + } + + bool add(const std::string &name, long double val) { + std::ostringstream buf; + buf << val; + + return add(name, buf.str(), "longdouble"); + } + + bool add(const std::string &name, const std::string &val) { + return add(name, val, "string"); + } + + bool addList(const std::string &name) { + if(!entryNode) + return false; + + if(elements.find(name) != elements.end() || lists.find(name) != lists.end()) + return false; + + xmlNodePtr newNode = xmlNewChild(entryNode, 0, (xmlChar*)"list", 0); + xmlSetProp(newNode, (xmlChar*)"name", (xmlChar*)name.c_str()); + + if(!lists.insert(std::make_pair(name, List(newNode))).second) { + xmlUnlinkNode(newNode); + xmlFreeNode(newNode); + + return false; + } + + return true; + } + + bool remove(const std::string &name) { + std::map<std::string, Element>::iterator element = elements.find(name); + + if(element != elements.end()) { + xmlUnlinkNode(element->second.elementNode); + xmlFreeNode(element->second.elementNode); + + elements.erase(element); + + return true; + } + + std::map<std::string, List>::iterator list = lists.find(name); + + if(list != lists.end()) { + xmlUnlinkNode(list->second.elementNode); + xmlFreeNode(list->second.elementNode); + + lists.erase(list); + + return true; + } + + return false; + } + }; + + class List : public Element { + private: + std::vector<Entry> entries; + + public: + List(xmlNodePtr node); + + virtual size_t getSize() const { + return entries.size(); + } + + virtual Entry& operator[](size_t i) { + return entries[i]; + } + + virtual const Entry& operator[](size_t i) const { + return entries[i]; + } + + virtual bool insertEntry(size_t i) { + if(i > getSize()) + return false; + + xmlNodePtr newNode = xmlNewNode(0, (xmlChar*)"entry"); + xmlAddChild(elementNode, newNode); + + entries.insert(entries.begin()+i, Entry(newNode)); + + return true; + } + + virtual bool addEntry() { + return insertEntry(getSize()); + } + + virtual bool removeEntry(size_t i) { + if(i >= getSize()) + return false; + + xmlUnlinkNode(entries[i].entryNode); + xmlFreeNode(entries[i].entryNode); + + entries.erase(entries.begin()+i); + + return true; + } + }; + + XmlPacket(); + XmlPacket(const XmlPacket &o); + XmlPacket(const Net::Packet &packet); + + XmlPacket& operator=(const XmlPacket &o); + + virtual ~XmlPacket() { + delete entry; + + xmlFreeDoc(doc); + } + + std::string getType() const; + void setType(const std::string &type); + + Element& operator[](const std::string &name) { + return entry->operator[](name); + } + + const Element& operator[](const std::string &name) const { + return entry->operator[](name); + } + + template <typename T> + bool add(const std::string &name, T val) { + return entry->add(name, val); + } + + bool addList(const std::string &name) { + return entry->addList(name); + } + + bool remove(const std::string &name) { + return entry->remove(name); + } + + Net::Packet encode(uint16_t requestId); +}; + +} +} + +#endif /* MAD_COMMON_XMLPACKET_H_ */ |