diff options
Diffstat (limited to 'src/Common/XmlPacket.cpp')
-rw-r--r-- | src/Common/XmlPacket.cpp | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/src/Common/XmlPacket.cpp b/src/Common/XmlPacket.cpp new file mode 100644 index 0000000..8da861c --- /dev/null +++ b/src/Common/XmlPacket.cpp @@ -0,0 +1,239 @@ +/* + * XmlProcessor.cpp + * + * 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/>. + */ + +#include "XmlPacket.h" +#include <cstdlib> + +namespace Mad { +namespace Common { + +XmlPacket::Entry XmlPacket::Element::nilEntry(0); +XmlPacket::Element XmlPacket::Entry::nilElement(0); + +void XmlPacket::Element::updateStr() { + if(type == NONE || type == LIST) + return; + + if(type != STRING) { + std::ostringstream buf; + + switch(type) { + case INT: + buf << value.var_int; + break; + case UINT: + buf << value.var_uint; + break; + case INT64: + buf << value.var_int64; + break; + case UINT64: + buf << value.var_uint64; + break; + case FLOAT: + buf << value.var_float; + break; + case DOUBLE: + buf << value.var_double; + break; + case LONGDOUBLE: + buf << value.var_ldouble; + default: + break; + + } + + str = buf.str(); + } + + xmlNodePtr newNode = xmlNewText((xmlChar*)str.c_str()); + xmlNodePtr oldNode = elementNode->children; + + xmlReplaceNode(oldNode, newNode); + xmlFreeNode(oldNode); +} + +XmlPacket::Element::Element(xmlNodePtr node) : elementNode(node), type(NONE) { + if(!node) + return; + + xmlChar *typestr = xmlGetProp(node, (xmlChar*)"type"); + if(!typestr) + return; + + xmlChar *content = xmlNodeGetContent(node->children); + if(!content) { + xmlFree(typestr); + return; + } + + str = (char*)content; + + if(!xmlStrcmp(typestr, (xmlChar*)"int")) { + type = INT; + value.var_int = std::strtol((char*)content, 0, 10); + } + else if(!xmlStrcmp(typestr, (xmlChar*)"uint")) { + type = UINT; + value.var_uint = std::strtoul((char*)content, 0, 10); + } + else if(!xmlStrcmp(typestr, (xmlChar*)"int64")) { + type = INT64; + value.var_int64 = std::strtoll((char*)content, 0, 10); + } + else if(!xmlStrcmp(typestr, (xmlChar*)"uint64")) { + type = UINT64; + value.var_uint64 = std::strtoull((char*)content, 0, 10); + } + else if(!xmlStrcmp(typestr, (xmlChar*)"float")) { + type = FLOAT; + value.var_float = std::strtof((char*)content, 0); + } + else if(!xmlStrcmp(typestr, (xmlChar*)"double")) { + type = DOUBLE; + value.var_double = std::strtod((char*)content, 0); + } + else if(!xmlStrcmp(typestr, (xmlChar*)"longdouble")) { + type = LONGDOUBLE; + value.var_ldouble = std::strtold((char*)content, 0); + } + else if(!xmlStrcmp(typestr, (xmlChar*)"string")) { + type = STRING; + } + + xmlFree(typestr); + xmlFree(content); + + updateStr(); +} + +XmlPacket::Entry::Entry(xmlNodePtr node) : entryNode(node) { + if(!node) + return; + + for(xmlNodePtr element = node->children; element != 0; element = element->next) { + if(element->type != XML_ELEMENT_NODE) + continue; + + xmlChar *name = xmlGetProp(element, (xmlChar*)"name"); + + if(!xmlStrcmp(element->name, (xmlChar*)"list")) + lists.insert(std::make_pair(std::string((char*)name), List(element))); + else if(!xmlStrcmp(element->name, (xmlChar*)"value")) + elements.insert(std::make_pair(std::string((char*)name), Element(element))); + + xmlFree(name); + } +} + +XmlPacket::Element& XmlPacket::Entry::operator[](const std::string &name) { + std::map<std::string, Element>::iterator it = elements.find(name); + if(it != elements.end()) + return it->second; + + std::map<std::string, List>::iterator it2 = lists.find(name); + if(it2 != lists.end()) + return it2->second; + + return nilElement; +} + +const XmlPacket::Element& XmlPacket::Entry::operator[](const std::string &name) const { + std::map<std::string, Element>::const_iterator it = elements.find(name); + if(it != elements.end()) + return it->second; + + std::map<std::string, List>::const_iterator it2 = lists.find(name); + if(it2 != lists.end()) + return it2->second; + + return nilElement; +} + +XmlPacket::List::List(xmlNodePtr node) : Element(node, LIST) { + for(xmlNodePtr entry = node->children; entry != 0; entry = entry->next) { + if(entry->type != XML_ELEMENT_NODE || xmlStrcmp(entry->name, (xmlChar*)"entry")) + continue; + + entries.push_back(Entry(entry)); + } +} + + +XmlPacket::XmlPacket() { + doc = xmlNewDoc((xmlChar*)"1.0"); + + packetNode = xmlNewNode(0, (xmlChar*)"packet"); + xmlDocSetRootElement(doc, packetNode); + + entry = new Entry(packetNode); +} + +XmlPacket::XmlPacket(const XmlPacket &o) { + doc = xmlCopyDoc(o.doc, 1); + packetNode = xmlDocGetRootElement(doc); + entry = new Entry(packetNode); +} + +XmlPacket::XmlPacket(const Net::Packet &packet) { + doc = xmlParseMemory((const char*)packet.getData(), packet.getLength()); + packetNode = xmlDocGetRootElement(doc); + entry = new Entry(packetNode); +} + +XmlPacket& XmlPacket::operator=(const XmlPacket &o) { + delete entry; + xmlFreeDoc(doc); + + doc = xmlCopyDoc(o.doc, 1); + packetNode = xmlDocGetRootElement(doc); + entry = new Entry(packetNode); + + return *this; +} + +std::string XmlPacket::getType() const { + xmlChar *type = xmlGetProp(packetNode, (xmlChar*)"type"); + + std::string ret(type ? (char*)type : ""); + + xmlFree(type); + + return ret; +} + +void XmlPacket::setType(const std::string &type) { + xmlSetProp(packetNode, (xmlChar*)"type", (xmlChar*)type.c_str()); +} + +Net::Packet XmlPacket::encode(uint16_t requestId) { + xmlChar *buf; + int length; + + xmlDocDumpMemory(doc, &buf, &length); + + Net::Packet packet(Net::Packet::XML, requestId, buf, length); + + xmlFree(buf); + + return packet; +} + +} +} |