diff options
Diffstat (limited to 'src/Common')
-rw-r--r-- | src/Common/XmlPacket.cpp | 96 | ||||
-rw-r--r-- | src/Common/XmlPacket.h | 75 |
2 files changed, 137 insertions, 34 deletions
diff --git a/src/Common/XmlPacket.cpp b/src/Common/XmlPacket.cpp index 672d092..87045a8 100644 --- a/src/Common/XmlPacket.cpp +++ b/src/Common/XmlPacket.cpp @@ -17,8 +17,15 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <config.h> + #include "XmlPacket.h" #include <cstdlib> +#include <cstring> + +extern "C" { +#include "base64.h" +} namespace Mad { namespace Common { @@ -30,7 +37,13 @@ void XmlPacket::Element::updateStr() { if(type == NONE || type == LIST) return; - if(type != STRING) { + if(type == BINARY) { + char *base64Data; + base64_encode_alloc((char*)binData, value.var_size, &base64Data); + str = base64Data; + std::free(base64Data); + } + else if(type != STRING) { std::ostringstream buf; switch(type) { @@ -56,7 +69,6 @@ void XmlPacket::Element::updateStr() { buf << value.var_ldouble; default: break; - } str = buf.str(); @@ -69,7 +81,7 @@ void XmlPacket::Element::updateStr() { xmlFreeNode(oldNode); } -XmlPacket::Element::Element(xmlNodePtr node) : elementNode(node), type(NONE) { +XmlPacket::Element::Element(xmlNodePtr node) : elementNode(node), binData(0), type(NONE) { if(!node) return; @@ -85,7 +97,11 @@ XmlPacket::Element::Element(xmlNodePtr node) : elementNode(node), type(NONE) { str = (char*)content; - if(!xmlStrcmp(typestr, (xmlChar*)"int")) { + if(!xmlStrcmp(typestr, (xmlChar*)"binary")) { + type = BINARY; + base64_decode_alloc((char*)content, xmlStrlen(content), (char**)&binData, &value.var_size); + } + else if(!xmlStrcmp(typestr, (xmlChar*)"int")) { type = INT; value.var_int = std::strtol((char*)content, 0, 10); } @@ -123,6 +139,24 @@ XmlPacket::Element::Element(xmlNodePtr node) : elementNode(node), type(NONE) { updateStr(); } +XmlPacket::Element::~Element() { + if(binData) + std::free(binData); +} + +void XmlPacket::Element::setBinaryData(const void *data, size_t size) { + if(type != BINARY) + return; + + if(binData) + std::free(binData); + + binData = std::malloc(size); + std::memcpy(binData, data, size); + + updateStr(); +} + XmlPacket::Entry::Entry(xmlNodePtr node) : entryNode(node) { if(!node) return; @@ -134,47 +168,79 @@ XmlPacket::Entry::Entry(xmlNodePtr node) : entryNode(node) { xmlChar *name = xmlGetProp(element, (xmlChar*)"name"); if(!xmlStrcmp(element->name, (xmlChar*)"list")) - lists.insert(std::make_pair(std::string((char*)name), List(element))); + lists.insert(std::make_pair(std::string((char*)name), new List(element))); else if(!xmlStrcmp(element->name, (xmlChar*)"value")) - elements.insert(std::make_pair(std::string((char*)name), Element(element))); + elements.insert(std::make_pair(std::string((char*)name), new Element(element))); xmlFree(name); } } +XmlPacket::Entry::~Entry() { + for(std::map<std::string, Element*>::iterator element = elements.begin(); element != elements.end(); ++element) + delete element->second; + + for(std::map<std::string, List*>::iterator list = lists.begin(); list != lists.end(); ++list) + delete list->second; +} + XmlPacket::Element& XmlPacket::Entry::operator[](const std::string &name) { - std::map<std::string, Element>::iterator it = elements.find(name); + std::map<std::string, Element*>::iterator it = elements.find(name); if(it != elements.end()) - return it->second; + return *it->second; - std::map<std::string, List>::iterator it2 = lists.find(name); + std::map<std::string, List*>::iterator it2 = lists.find(name); if(it2 != lists.end()) - return it2->second; + 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); + std::map<std::string, Element*>::const_iterator it = elements.find(name); if(it != elements.end()) - return it->second; + return *it->second; - std::map<std::string, List>::const_iterator it2 = lists.find(name); + std::map<std::string, List*>::const_iterator it2 = lists.find(name); if(it2 != lists.end()) - return it2->second; + return *it2->second; return nilElement; } +bool XmlPacket::Entry::addBinary(const std::string &name, const void *data, size_t size) { + if(!entryNode) + return false; + + if(elements.find(name) != elements.end() || lists.find(name) != lists.end()) + return false; + + char *base64Data; + + base64_encode_alloc((const char*)data, size, &base64Data); + if(!base64Data) + return false; + + bool ret = add(name, std::string(base64Data), "binary"); + + std::free(base64Data); + + return ret; +} + 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)); + entries.push_back(new Entry(entry)); } } +XmlPacket::List::~List() { + for(std::vector<Entry*>::iterator entry = entries.begin(); entry != entries.end(); ++entry) + delete *entry; +} XmlPacket::XmlPacket() { doc = xmlNewDoc((xmlChar*)"1.0"); diff --git a/src/Common/XmlPacket.h b/src/Common/XmlPacket.h index e32893a..196da24 100644 --- a/src/Common/XmlPacket.h +++ b/src/Common/XmlPacket.h @@ -43,11 +43,10 @@ class XmlPacket { Entry *entry; public: - class Element { public: enum Type { - NONE, LIST, + NONE, LIST, BINARY, INT, UINT, INT64, UINT64, FLOAT, DOUBLE, LONGDOUBLE, STRING }; @@ -58,7 +57,12 @@ class XmlPacket { xmlNodePtr elementNode; private: + // Prevent shallow copy + Element(const Element &o); + Element& operator=(const Element &o); + std::string str; + void *binData; Type type; union Variant { @@ -71,6 +75,8 @@ class XmlPacket { float var_float; double var_double; long double var_ldouble; + + size_t var_size; } value; static Entry nilEntry; @@ -109,11 +115,13 @@ class XmlPacket { void updateStr(); protected: - Element(xmlNodePtr node, Type type0) : elementNode(node), type(type0) {} + Element(xmlNodePtr node, Type type0) : elementNode(node), binData(0), type(type0) {} public: Element(xmlNodePtr node); + virtual ~Element(); + Type getType() const { return type; } @@ -221,16 +229,33 @@ class XmlPacket { 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<std::string, Element> elements; - std::map<std::string, List> lists; + std::map<std::string, Element*> elements; + std::map<std::string, List*> lists; static Element nilElement; @@ -245,7 +270,7 @@ class XmlPacket { xmlSetProp(newNode, (xmlChar*)"name", (xmlChar*)name.c_str()); xmlSetProp(newNode, (xmlChar*)"type", (xmlChar*)type); - if(!elements.insert(std::make_pair(name, Element(newNode))).second) { + if(!elements.insert(std::make_pair(name, new Element(newNode))).second) { xmlUnlinkNode(newNode); xmlFreeNode(newNode); @@ -257,6 +282,7 @@ class XmlPacket { public: Entry(xmlNodePtr node); + virtual ~Entry(); Element& operator[](const std::string &name); const Element& operator[](const std::string &name) const; @@ -328,6 +354,8 @@ class XmlPacket { 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; @@ -338,7 +366,7 @@ class XmlPacket { 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) { + if(!lists.insert(std::make_pair(name, new List(newNode))).second) { xmlUnlinkNode(newNode); xmlFreeNode(newNode); @@ -349,22 +377,22 @@ class XmlPacket { } bool remove(const std::string &name) { - std::map<std::string, Element>::iterator element = elements.find(name); + std::map<std::string, Element*>::iterator element = elements.find(name); if(element != elements.end()) { - xmlUnlinkNode(element->second.elementNode); - xmlFreeNode(element->second.elementNode); + xmlUnlinkNode(element->second->elementNode); + xmlFreeNode(element->second->elementNode); elements.erase(element); return true; } - std::map<std::string, List>::iterator list = lists.find(name); + std::map<std::string, List*>::iterator list = lists.find(name); if(list != lists.end()) { - xmlUnlinkNode(list->second.elementNode); - xmlFreeNode(list->second.elementNode); + xmlUnlinkNode(list->second->elementNode); + xmlFreeNode(list->second->elementNode); lists.erase(list); @@ -377,21 +405,26 @@ class XmlPacket { class List : public Element { private: - std::vector<Entry> entries; + // Prevent shallow copy + List(const List &o); + List& operator=(const List &o); + + std::vector<Entry*> entries; public: List(xmlNodePtr node); + virtual ~List(); virtual size_t getSize() const { return entries.size(); } virtual Entry& operator[](size_t i) { - return entries[i]; + return *entries[i]; } virtual const Entry& operator[](size_t i) const { - return entries[i]; + return *entries[i]; } virtual bool insertEntry(size_t i) { @@ -401,7 +434,7 @@ class XmlPacket { xmlNodePtr newNode = xmlNewNode(0, (xmlChar*)"entry"); xmlAddChild(elementNode, newNode); - entries.insert(entries.begin()+i, Entry(newNode)); + entries.insert(entries.begin()+i, new Entry(newNode)); return true; } @@ -414,8 +447,8 @@ class XmlPacket { if(i >= getSize()) return false; - xmlUnlinkNode(entries[i].entryNode); - xmlFreeNode(entries[i].entryNode); + xmlUnlinkNode(entries[i]->entryNode); + xmlFreeNode(entries[i]->entryNode); entries.erase(entries.begin()+i); @@ -451,6 +484,10 @@ class XmlPacket { 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); } |