/* * XmlProcessor.h * * Copyright (C) 2009 Matthias Schiffer * * 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 . */ #ifndef MAD_COMMON_XMLPACKET_H_ #define MAD_COMMON_XMLPACKET_H_ #include #include #include #include #include #include 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, BINARY, INT, UINT, INT64, UINT64, FLOAT, DOUBLE, LONGDOUBLE, STRING }; protected: friend class Entry; xmlNodePtr elementNode; private: // Prevent shallow copy Element(const Element &o); Element& operator=(const Element &o); std::string str; void *binData; 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; size_t var_size; } value; static Entry nilEntry; template void set(T val) { switch(type) { case INT: value.var_int = static_cast(val); break; case UINT: value.var_uint = static_cast(val); break; case INT64: value.var_int64 = static_cast(val); break; case UINT64: value.var_uint64 = static_cast(val); break; case FLOAT: value.var_float = static_cast(val); break; case DOUBLE: value.var_double = static_cast(val); break; case LONGDOUBLE: value.var_ldouble = static_cast(val); break; default: break; } updateStr(); } void updateStr(); protected: Element(xmlNodePtr node, Type type0) : elementNode(node), binData(0), type(type0) {} public: Element(xmlNodePtr node); virtual ~Element(); Type getType() const { return type; } virtual size_t getSize() const { return 0; } bool isEmpty() const { return (getSize() == 0); } virtual Entry& operator[](size_t) { return nilEntry; } virtual const Entry& operator[](size_t) const { return nilEntry; } Entry& back() { if(isEmpty()) return nilEntry; return operator[](getSize()-1); } const Entry& back() const { if(isEmpty()) return nilEntry; return operator[](getSize()-1); } virtual bool insertEntry(size_t) {return false;} virtual bool addEntry() {return false;} virtual bool removeEntry(size_t) {return false;} template operator T() const { switch(type) { case INT: return static_cast(value.var_int); case UINT: return static_cast(value.var_uint); case INT64: return static_cast(value.var_int64); case UINT64: return static_cast(value.var_uint64); case FLOAT: return static_cast(value.var_float); case DOUBLE: return static_cast(value.var_double); case LONGDOUBLE: return static_cast(value.var_ldouble); default: return static_cast(0); } } operator std::string() const { 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; } void setBinaryData(const void *data, size_t size); void getBinaryData(const void **data, size_t *size) const { if(type == BINARY) { *data = binData; *size = value.var_size; } else { *data = 0; *size = 0; } } }; class Entry { private: friend class List; // Prevent shallow copy Entry(const Entry &o); Entry& operator=(const Entry &o); xmlNodePtr entryNode; std::map elements; std::map lists; static Element nilElement; 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, new Element(newNode))).second) { xmlUnlinkNode(newNode); xmlFreeNode(newNode); return false; } return true; } public: Entry(xmlNodePtr node); virtual ~Entry(); 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 val) { std::ostringstream buf; buf << val; return add(name, buf.str(), "int"); } bool add(const std::string &name, unsigned long 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 addBinary(const std::string &name, const void *data, size_t size); 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, new List(newNode))).second) { xmlUnlinkNode(newNode); xmlFreeNode(newNode); return false; } return true; } bool remove(const std::string &name) { std::map::iterator element = elements.find(name); if(element != elements.end()) { xmlUnlinkNode(element->second->elementNode); xmlFreeNode(element->second->elementNode); elements.erase(element); return true; } std::map::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: // Prevent shallow copy List(const List &o); List& operator=(const List &o); std::vector entries; public: List(xmlNodePtr node); virtual ~List(); 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, new 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 bool add(const std::string &name, T val) { return entry->add(name, val); } bool addBinary(const std::string &name, const void *data, size_t size) { return entry->addBinary(name, data, size); } 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) const; }; } } #endif /* MAD_COMMON_XMLPACKET_H_ */