summaryrefslogtreecommitdiffstats
path: root/src/Common/XmlPacket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/XmlPacket.cpp')
-rw-r--r--src/Common/XmlPacket.cpp239
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;
+}
+
+}
+}