diff options
Diffstat (limited to 'src/Common')
-rw-r--r-- | src/Common/Request.cpp | 3 | ||||
-rw-r--r-- | src/Common/RequestHandlers/DisconnectRequestHandler.cpp | 2 | ||||
-rw-r--r-- | src/Common/RequestHandlers/FSInfoRequestHandler.cpp | 17 | ||||
-rw-r--r-- | src/Common/RequestHandlers/SimpleRequestHandler.cpp | 10 | ||||
-rw-r--r-- | src/Common/RequestHandlers/SimpleRequestHandlerGroup.cpp | 10 | ||||
-rw-r--r-- | src/Common/RequestHandlers/StatusRequestHandler.cpp | 22 | ||||
-rw-r--r-- | src/Common/RequestManager.cpp | 2 | ||||
-rw-r--r-- | src/Common/Requests/DisconnectRequest.cpp | 3 | ||||
-rw-r--r-- | src/Common/Requests/GroupUserListRequest.cpp | 2 | ||||
-rw-r--r-- | src/Common/Requests/IdentifyRequest.cpp | 2 | ||||
-rw-r--r-- | src/Common/Requests/UserGroupListRequest.cpp | 2 | ||||
-rw-r--r-- | src/Common/Requests/UserInfoRequest.cpp | 2 | ||||
-rw-r--r-- | src/Common/XmlPacket.cpp | 159 | ||||
-rw-r--r-- | src/Common/XmlPacket.h | 574 |
14 files changed, 388 insertions, 422 deletions
diff --git a/src/Common/Request.cpp b/src/Common/Request.cpp index 9aafd7f..9c2df5f 100644 --- a/src/Common/Request.cpp +++ b/src/Common/Request.cpp @@ -24,7 +24,8 @@ namespace Common { void Request::handlePacket(boost::shared_ptr<const XmlPacket> packet) { if(packet->getType() == "Error") { - signalFinished(Core::Exception((*packet)["Where"], (*packet)["ErrorCode"], (*packet)["SubCode"], (*packet)["SubSubCode"])); + signalFinished(Core::Exception(packet->get<const std::string&>("Where"), packet->get<Core::Exception::ErrorCode>("ErrorCode"), + packet->get<long>("SubCode"), packet->get<long>("SubSubCode"))); return; } else if(packet->getType() != "OK") { diff --git a/src/Common/RequestHandlers/DisconnectRequestHandler.cpp b/src/Common/RequestHandlers/DisconnectRequestHandler.cpp index 11256b1..234591f 100644 --- a/src/Common/RequestHandlers/DisconnectRequestHandler.cpp +++ b/src/Common/RequestHandlers/DisconnectRequestHandler.cpp @@ -30,7 +30,7 @@ void DisconnectRequestHandler::handlePacket(boost::shared_ptr<const XmlPacket> p XmlPacket ret; ret.setType("Error"); - ret.add("ErrorCode", Core::Exception::UNEXPECTED_PACKET); + ret.set("ErrorCode", Core::Exception::UNEXPECTED_PACKET); sendPacket(ret); diff --git a/src/Common/RequestHandlers/FSInfoRequestHandler.cpp b/src/Common/RequestHandlers/FSInfoRequestHandler.cpp index c036f7b..c381ab1 100644 --- a/src/Common/RequestHandlers/FSInfoRequestHandler.cpp +++ b/src/Common/RequestHandlers/FSInfoRequestHandler.cpp @@ -31,17 +31,16 @@ void FSInfoRequestHandler::handleRequest(boost::shared_ptr<const Common::XmlPack getApplication()->getSystemManager()->getFSInfo(&fsInfo); ret->setType("OK"); - ret->addList("filesystems"); + XmlPacket::List *list = ret->createList("filesystems"); for(std::vector<SystemManager::FSInfo>::const_iterator fs = fsInfo.begin(); fs != fsInfo.end(); ++fs) { - (*ret)["filesystems"].addEntry(); - XmlPacket::Entry &entry = (*ret)["filesystems"].back(); - - entry.add("name", fs->fsName); - entry.add("mountedOn", fs->mountedOn); - entry.add("totalSize", fs->total); - entry.add("usedSize", fs->used); - entry.add("availableSize", fs->available); + XmlPacket::List::iterator entry = list->addEntry(); + + entry->set("name", fs->fsName); + entry->set("mountedOn", fs->mountedOn); + entry->set("totalSize", fs->total); + entry->set("usedSize", fs->used); + entry->set("availableSize", fs->available); } } diff --git a/src/Common/RequestHandlers/SimpleRequestHandler.cpp b/src/Common/RequestHandlers/SimpleRequestHandler.cpp index b6a22bf..bf72a80 100644 --- a/src/Common/RequestHandlers/SimpleRequestHandler.cpp +++ b/src/Common/RequestHandlers/SimpleRequestHandler.cpp @@ -31,7 +31,7 @@ void SimpleRequestHandler::handlePacket(boost::shared_ptr<const XmlPacket> packe XmlPacket ret; ret.setType("Error"); - ret.add("ErrorCode", Core::Exception::UNEXPECTED_PACKET); + ret.set("ErrorCode", Core::Exception::UNEXPECTED_PACKET); sendPacket(ret); @@ -48,10 +48,10 @@ void SimpleRequestHandler::handlePacket(boost::shared_ptr<const XmlPacket> packe } catch(Core::Exception e) { ret.setType("Error"); - ret.add("ErrorCode", e.getErrorCode()); - ret.add("SubCode", e.getSubCode()); - ret.add("SubSubCode", e.getSubSubCode()); - ret.add("Where", e.getWhere()); + ret.set("ErrorCode", e.getErrorCode()); + ret.set("SubCode", e.getSubCode()); + ret.set("SubSubCode", e.getSubSubCode()); + ret.set("Where", e.getWhere()); } sendPacket(ret); diff --git a/src/Common/RequestHandlers/SimpleRequestHandlerGroup.cpp b/src/Common/RequestHandlers/SimpleRequestHandlerGroup.cpp index 845021d..6546ce5 100644 --- a/src/Common/RequestHandlers/SimpleRequestHandlerGroup.cpp +++ b/src/Common/RequestHandlers/SimpleRequestHandlerGroup.cpp @@ -32,7 +32,7 @@ void SimpleRequestHandlerGroup::GroupRequestHandler::handlePacket(boost::shared_ XmlPacket ret; ret.setType("Error"); - ret.add("ErrorCode", Core::Exception::UNEXPECTED_PACKET); + ret.set("ErrorCode", Core::Exception::UNEXPECTED_PACKET); sendPacket(ret); @@ -49,10 +49,10 @@ void SimpleRequestHandlerGroup::GroupRequestHandler::handlePacket(boost::shared_ } catch(Core::Exception e) { ret.setType("Error"); - ret.add("ErrorCode", e.getErrorCode()); - ret.add("SubCode", e.getSubCode()); - ret.add("SubSubCode", e.getSubSubCode()); - ret.add("Where", e.getWhere()); + ret.set("ErrorCode", e.getErrorCode()); + ret.set("SubCode", e.getSubCode()); + ret.set("SubSubCode", e.getSubSubCode()); + ret.set("Where", e.getWhere()); } sendPacket(ret); diff --git a/src/Common/RequestHandlers/StatusRequestHandler.cpp b/src/Common/RequestHandlers/StatusRequestHandler.cpp index 50dbe11..d6cdc1e 100644 --- a/src/Common/RequestHandlers/StatusRequestHandler.cpp +++ b/src/Common/RequestHandlers/StatusRequestHandler.cpp @@ -34,8 +34,8 @@ void StatusRequestHandler::handleRequest(boost::shared_ptr<const Common::XmlPack getApplication()->getSystemManager()->getUptimeInfo(&uptime, &idleTime); - ret->add("uptime", uptime); - ret->add("idleTime", idleTime); + ret->set("uptime", uptime); + ret->set("idleTime", idleTime); } catch(Core::Exception e) {} @@ -44,10 +44,10 @@ void StatusRequestHandler::handleRequest(boost::shared_ptr<const Common::XmlPack getApplication()->getSystemManager()->getMemoryInfo(&totalMem, &freeMem, &totalSwap, &freeSwap); - ret->add("totalMem", totalMem); - ret->add("freeMem", freeMem); - ret->add("totalSwap", totalSwap); - ret->add("freeSwap", freeSwap); + ret->set("totalMem", totalMem); + ret->set("freeMem", freeMem); + ret->set("totalSwap", totalSwap); + ret->set("freeSwap", freeSwap); } catch(Core::Exception e) {} @@ -57,11 +57,11 @@ void StatusRequestHandler::handleRequest(boost::shared_ptr<const Common::XmlPack getApplication()->getSystemManager()->getLoadInfo(¤tLoad, &nProcesses, &loadAvg1, &loadAvg5, &loadAvg15); - ret->add("currentLoad", currentLoad); - ret->add("nProcesses", nProcesses); - ret->add("loadAvg1", loadAvg1); - ret->add("loadAvg5", loadAvg5); - ret->add("loadAvg15", loadAvg15); + ret->set("currentLoad", currentLoad); + ret->set("nProcesses", nProcesses); + ret->set("loadAvg1", loadAvg1); + ret->set("loadAvg5", loadAvg5); + ret->set("loadAvg15", loadAvg15); } catch(Core::Exception e) {} } diff --git a/src/Common/RequestManager.cpp b/src/Common/RequestManager.cpp index c8b27a2..ab45a8f 100644 --- a/src/Common/RequestManager.cpp +++ b/src/Common/RequestManager.cpp @@ -130,7 +130,7 @@ void RequestManager::receiveHandler(Connection *connection, boost::shared_ptr<co XmlPacket ret; ret.setType("Error"); - ret.add("ErrorCode", Core::Exception::UNEXPECTED_PACKET); + ret.set("ErrorCode", Core::Exception::UNEXPECTED_PACKET); connection->sendPacket(ret, requestId); } diff --git a/src/Common/Requests/DisconnectRequest.cpp b/src/Common/Requests/DisconnectRequest.cpp index 6c4fa0d..16a6a78 100644 --- a/src/Common/Requests/DisconnectRequest.cpp +++ b/src/Common/Requests/DisconnectRequest.cpp @@ -32,7 +32,8 @@ void DisconnectRequest::sendRequest() { void DisconnectRequest::handlePacket(boost::shared_ptr<const XmlPacket> packet) { if(packet->getType() == "Error") { - signalFinished(Core::Exception((*packet)["Where"], (*packet)["ErrorCode"], (*packet)["SubCode"], (*packet)["SubSubCode"])); + signalFinished(Core::Exception(packet->get<const std::string&>("Where"), packet->get<Core::Exception::ErrorCode>("ErrorCode"), + packet->get<long>("SubCode"), packet->get<long>("SubSubCode"))); return; } else if(packet->getType() != "OK") { diff --git a/src/Common/Requests/GroupUserListRequest.cpp b/src/Common/Requests/GroupUserListRequest.cpp index f77f559..87ab1b5 100644 --- a/src/Common/Requests/GroupUserListRequest.cpp +++ b/src/Common/Requests/GroupUserListRequest.cpp @@ -26,7 +26,7 @@ namespace Requests { void GroupUserListRequest::sendRequest() { Common::XmlPacket packet; packet.setType("ListGroupUsers"); - packet.add("gid", gid); + packet.set("gid", gid); sendPacket(packet); } diff --git a/src/Common/Requests/IdentifyRequest.cpp b/src/Common/Requests/IdentifyRequest.cpp index 6cf09d1..0be8e83 100644 --- a/src/Common/Requests/IdentifyRequest.cpp +++ b/src/Common/Requests/IdentifyRequest.cpp @@ -28,7 +28,7 @@ void IdentifyRequest::sendRequest() { packet.setType("Identify"); if(!hostname.empty()) - packet.add("hostname", hostname); + packet.set("hostname", hostname); sendPacket(packet); } diff --git a/src/Common/Requests/UserGroupListRequest.cpp b/src/Common/Requests/UserGroupListRequest.cpp index ec7e23c..0c1a72f 100644 --- a/src/Common/Requests/UserGroupListRequest.cpp +++ b/src/Common/Requests/UserGroupListRequest.cpp @@ -26,7 +26,7 @@ namespace Requests { void UserGroupListRequest::sendRequest() { Common::XmlPacket packet; packet.setType("ListUserGroups"); - packet.add("uid", uid); + packet.set("uid", uid); sendPacket(packet); } diff --git a/src/Common/Requests/UserInfoRequest.cpp b/src/Common/Requests/UserInfoRequest.cpp index 455eed6..b4b6940 100644 --- a/src/Common/Requests/UserInfoRequest.cpp +++ b/src/Common/Requests/UserInfoRequest.cpp @@ -26,7 +26,7 @@ namespace Requests { void UserInfoRequest::sendRequest() { Common::XmlPacket packet; packet.setType("GetUserInfo"); - packet.add("uid", uid); + packet.set("uid", uid); sendPacket(packet); } diff --git a/src/Common/XmlPacket.cpp b/src/Common/XmlPacket.cpp index 6e3d007..8e612a9 100644 --- a/src/Common/XmlPacket.cpp +++ b/src/Common/XmlPacket.cpp @@ -24,58 +24,71 @@ #include <cstdlib> #include <cstring> +#include <iostream> + 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; + std::string typeStr; - if(type == BINARY) { - str = Base64Encoder::encode(std::vector<boost::uint8_t>((boost::uint8_t*)binData, ((boost::uint8_t*)binData)+value.var_size)); + if(type == NONE) { + str = ""; + } + else if(type == BINARY) { + str = Base64Encoder::encode(boost::get<std::vector<boost::uint8_t> >(value)); + typeStr = "binary"; } else if(type != STRING) { std::ostringstream buf; switch(type) { case INT: - buf << value.var_int; + buf << boost::get<long>(value); + typeStr = "int"; break; case UINT: - buf << value.var_uint; + buf << boost::get<unsigned long>(value); + typeStr = "uint"; break; case INT64: - buf << value.var_int64; + buf << boost::get<long long>(value); + typeStr = "int64"; break; case UINT64: - buf << value.var_uint64; + buf << boost::get<unsigned long long>(value); + typeStr = "uint64"; break; case FLOAT: - buf << value.var_float; + buf << boost::get<float>(value); + typeStr = "float"; break; case DOUBLE: - buf << value.var_double; + buf << boost::get<double>(value); + typeStr = "double"; break; case LONGDOUBLE: - buf << value.var_ldouble; + buf << boost::get<long double>(value); + typeStr = "longdouble"; default: break; } str = buf.str(); } + else + typeStr = "string"; xmlNodePtr newNode = xmlNewText((xmlChar*)str.c_str()); xmlNodePtr oldNode = elementNode->children; xmlReplaceNode(oldNode, newNode); xmlFreeNode(oldNode); + + xmlSetProp(elementNode, (xmlChar*)"type", (xmlChar*)typeStr.c_str()); } -XmlPacket::Element::Element(xmlNodePtr node) : elementNode(node), binData(0), type(NONE) { +XmlPacket::Element::Element(xmlNodePtr node) : elementNode(node), type(NONE) { if(!node) return; @@ -94,39 +107,35 @@ XmlPacket::Element::Element(xmlNodePtr node) : elementNode(node), binData(0), ty if(!xmlStrcmp(typestr, (xmlChar*)"binary")) { type = BINARY; - std::vector<boost::uint8_t> v = Base64Encoder::decode(str); - - value.var_size = v.size(); - binData = std::malloc(value.var_size); - std::memcpy(binData, v.data(), value.var_size); + value = Base64Encoder::decode(str); } else if(!xmlStrcmp(typestr, (xmlChar*)"int")) { type = INT; - value.var_int = std::strtol((char*)content, 0, 10); + value = std::strtol((char*)content, 0, 10); } else if(!xmlStrcmp(typestr, (xmlChar*)"uint")) { type = UINT; - value.var_uint = std::strtoul((char*)content, 0, 10); + value = std::strtoul((char*)content, 0, 10); } else if(!xmlStrcmp(typestr, (xmlChar*)"int64")) { type = INT64; - value.var_int64 = std::strtoll((char*)content, 0, 10); + value = std::strtoll((char*)content, 0, 10); } else if(!xmlStrcmp(typestr, (xmlChar*)"uint64")) { type = UINT64; - value.var_uint64 = std::strtoull((char*)content, 0, 10); + value = std::strtoull((char*)content, 0, 10); } else if(!xmlStrcmp(typestr, (xmlChar*)"float")) { type = FLOAT; - value.var_float = std::strtof((char*)content, 0); + value = std::strtof((char*)content, 0); } else if(!xmlStrcmp(typestr, (xmlChar*)"double")) { type = DOUBLE; - value.var_double = std::strtod((char*)content, 0); + value = std::strtod((char*)content, 0); } else if(!xmlStrcmp(typestr, (xmlChar*)"longdouble")) { type = LONGDOUBLE; - value.var_ldouble = std::strtold((char*)content, 0); + value = std::strtold((char*)content, 0); } else if(!xmlStrcmp(typestr, (xmlChar*)"string")) { type = STRING; @@ -135,25 +144,8 @@ XmlPacket::Element::Element(xmlNodePtr node) : elementNode(node), binData(0), ty xmlFree(typestr); xmlFree(content); - 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(); + if(type != NONE) + updateStr(); } XmlPacket::Entry::Entry(xmlNodePtr node) : entryNode(node) { @@ -175,51 +167,59 @@ XmlPacket::Entry::Entry(xmlNodePtr node) : entryNode(node) { } } -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); - if(it != elements.end()) - return *it->second; - std::map<std::string, List*>::iterator it2 = lists.find(name); - if(it2 != lists.end()) - return *it2->second; +template <> +std::string XmlPacket::Entry::get<std::string>(const std::string &name) const { + Element *element = getElement(name); + if(!element) + return std::string(); - return nilElement; + return element->str; } -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; +template <> +const std::string& XmlPacket::Entry::get<const std::string&>(const std::string &name) const { + static std::string empty; - std::map<std::string, List*>::const_iterator it2 = lists.find(name); - if(it2 != lists.end()) - return *it2->second; + Element *element = getElement(name); + if(!element) + return empty; - return nilElement; + return element->str; } -bool XmlPacket::Entry::addBinary(const std::string &name, const void *data, size_t size) { - if(!entryNode) - return false; +template <> +std::vector<boost::uint8_t> XmlPacket::Entry::get<std::vector<unsigned char> >(const std::string &name) const { + Element *element = getElement(name); + if(!element) + return std::vector<boost::uint8_t>(); + + switch(element->type) { + case Element::BINARY: + return boost::get<std::vector<boost::uint8_t> >(element->value); + default: + return std::vector<boost::uint8_t>(); + } +} - if(elements.find(name) != elements.end() || lists.find(name) != lists.end()) - return false; +template <> +const std::vector<boost::uint8_t>& XmlPacket::Entry::get<const std::vector<unsigned char>&>(const std::string &name) const { + static std::vector<boost::uint8_t> empty; - std::string base64Data = Base64Encoder::encode(std::vector<boost::uint8_t>((boost::uint8_t*)data, ((boost::uint8_t*)data)+size));; + Element *element = getElement(name); + if(!element) + return empty; - return add(name, base64Data, "binary"); + switch(element->type) { + case Element::BINARY: + return boost::get<std::vector<boost::uint8_t> >(element->value); + default: + return empty; + } } -XmlPacket::List::List(xmlNodePtr node) : Element(node, LIST) { +XmlPacket::List::List(xmlNodePtr node) : elementNode(node) { for(xmlNodePtr entry = node->children; entry != 0; entry = entry->next) { if(entry->type != XML_ELEMENT_NODE || xmlStrcmp(entry->name, (xmlChar*)"entry")) continue; @@ -228,11 +228,6 @@ XmlPacket::List::List(xmlNodePtr node) : Element(node, LIST) { } } -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 43ee2b2..b37b783 100644 --- a/src/Common/XmlPacket.h +++ b/src/Common/XmlPacket.h @@ -29,6 +29,14 @@ #include <libxml/parser.h> +#include <boost/cstdint.hpp> +#include <boost/noncopyable.hpp> +#include <boost/variant/get.hpp> +#include <boost/variant/variant.hpp> +#include <boost/smart_ptr.hpp> + +#include <iostream> + namespace Mad { namespace Common { @@ -42,359 +50,221 @@ class XmlPacket { xmlNodePtr packetNode; Entry *entry; - public: - class Element { - public: + class Element : private boost::noncopyable { + private: + friend class Entry; + enum Type { - NONE, LIST, BINARY, + NONE, BINARY, INT, UINT, INT64, UINT64, FLOAT, DOUBLE, LONGDOUBLE, STRING }; - protected: - friend class Entry; + typedef boost::variant<long, unsigned long, long long, unsigned long long, float, double, long double, std::vector<boost::uint8_t> > Variant; 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<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; - } + Variant value; - updateStr(); - } + std::string str; 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; - } - - virtual bool isEmpty() const { - switch(type) { - case NONE: - return true; - case BINARY: - return (value.var_size != 0); - case STRING: - return str.empty(); - default: - return false; - } - } - - 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; + template <typename T> + void set(T val, Type type0) { + type = type0; + value = val; - return operator[](getSize()-1); + updateStr(); } - virtual bool insertEntry(size_t) {return false;} - virtual bool addEntry() {return false;} - virtual bool removeEntry(size_t) {return false;} - - template<typename T> - operator T() const { - 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); - } + void set(int val) { + set<long>(val, INT); } - operator std::string() const { - return str; + void set(unsigned int val) { + set<unsigned long>(val, UINT); } - const Element& operator=(int val) { - set(val); - return *this; + void set(long val) { + set(val, INT); } - const Element& operator=(unsigned int val) { - set(val); - return *this; + void set(unsigned long val) { + set(val, UINT); } - const Element& operator=(long long val) { - set(val); - return *this; + void set(long long val) { + set(val, INT64); } - const Element& operator=(unsigned long long val) { - set(val); - return *this; + void set(unsigned long long val) { + set(val, UINT64); } - const Element& operator=(float val) { - set(val); - return *this; + void set(float val) { + set(val, FLOAT); } - const Element& operator=(double val) { - set(val); - return *this; + void set(double val) { + set(val, DOUBLE); } - const Element& operator=(long double val) { - set(val); - return *this; + void set(long double val) { + set(val, LONGDOUBLE); } - const Element& operator=(const std::string &val) { - if(type == STRING) { - str = val; - updateStr(); - } - - return *this; + void set(const std::string &val) { + type = STRING; + value = Element::Variant(); + str = val; + updateStr(); } - 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; - } + void set(const std::vector<boost::uint8_t> &val) { + set(val, BINARY); } }; - class Entry { + public: + class Entry : private boost::noncopyable { private: friend class List; - - // Prevent shallow copy - Entry(const Entry &o); - Entry& operator=(const Entry &o); + friend class XmlPacket; xmlNodePtr entryNode; std::map<std::string, Element*> elements; std::map<std::string, List*> lists; - static Element nilElement; + Element* getElement(const std::string &name) { + std::map<std::string, Element*>::iterator element = elements.find(name); - bool add(const std::string &name, const std::string &value, const char *type) { - if(!entryNode) - return false; + if(element != elements.end()) + return element->second; - if(lists.find(name) != lists.end() || elements.find(name) != elements.end()) - return false; + if(lists.find(name) != lists.end()) + return 0; - xmlNodePtr newNode = xmlNewTextChild(entryNode, 0, (xmlChar*)"value", (xmlChar*)value.c_str()); + xmlNodePtr newNode = xmlNewTextChild(entryNode, 0, (xmlChar*)"value", (xmlChar*)""); xmlSetProp(newNode, (xmlChar*)"name", (xmlChar*)name.c_str()); - xmlSetProp(newNode, (xmlChar*)"type", (xmlChar*)type); + xmlSetProp(newNode, (xmlChar*)"type", (xmlChar*)""); - if(!elements.insert(std::make_pair(name, new Element(newNode))).second) { - xmlUnlinkNode(newNode); - xmlFreeNode(newNode); + Element* newElement = new Element(newNode); - return false; - } + elements.insert(std::make_pair(name, newElement)); - return true; + return newElement; } - public: - Entry(xmlNodePtr node); - virtual ~Entry(); + Element* getElement(const std::string &name) const { + std::map<std::string, Element*>::const_iterator element = elements.find(name); - 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"); + if(element != elements.end()) + return element->second; + else + return 0; } - 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; + Entry(xmlNodePtr node); + ~Entry() { + for(std::map<std::string, Element*>::iterator element = elements.begin(); element != elements.end(); ++element) + delete element->second; - return add(name, buf.str(), "int"); + for(std::map<std::string, List*>::iterator list = lists.begin(); list != lists.end(); ++list) + delete list->second; } - bool add(const std::string &name, unsigned long val) { - std::ostringstream buf; - buf << val; - - return add(name, buf.str(), "uint"); - } + public: + template <typename T> + bool set(const std::string &name, T val) { + Element *element = getElement(name); + if(!element) + return false; - bool add(const std::string &name, long long val) { - std::ostringstream buf; - buf << val; + element->set(val); - return add(name, buf.str(), "int64"); + return true; } - bool add(const std::string &name, unsigned long long val) { - std::ostringstream buf; - buf << val; - - return add(name, buf.str(), "uint64"); + template <typename T> + T get(const std::string &name) const { + Element *element = getElement(name); + if(!element) + return T(); + + switch(element->type) { + case Element::INT: + return static_cast<T>(boost::get<long>(element->value)); + case Element::UINT: + return static_cast<T>(boost::get<unsigned long>(element->value)); + case Element::INT64: + return static_cast<T>(boost::get<long long>(element->value)); + case Element::UINT64: + return static_cast<T>(boost::get<unsigned long long>(element->value)); + case Element::FLOAT: + return static_cast<T>(boost::get<float>(element->value)); + case Element::DOUBLE: + return static_cast<T>(boost::get<double>(element->value)); + case Element::LONGDOUBLE: + return static_cast<T>(boost::get<long double>(element->value)); + default: + return static_cast<T>(0); + } } - bool add(const std::string &name, float val) { - std::ostringstream buf; - buf << val; + List* createList(const std::string &name, bool unique = false) { + std::map<std::string, List*>::iterator list = lists.find(name); - return add(name, buf.str(), "float"); - } + if(list != lists.end()) + return unique ? 0 : list->second; - bool add(const std::string &name, double val) { - std::ostringstream buf; - buf << val; + if(elements.find(name) != elements.end()) + return 0; - return add(name, buf.str(), "double"); - } + xmlNodePtr newNode = xmlNewChild(entryNode, 0, (xmlChar*)"list", 0); + xmlSetProp(newNode, (xmlChar*)"name", (xmlChar*)name.c_str()); - bool add(const std::string &name, long double val) { - std::ostringstream buf; - buf << val; + List *newList = new List(newNode); - return add(name, buf.str(), "longdouble"); - } + lists.insert(std::make_pair(name, newList)); - bool add(const std::string &name, const std::string &val) { - return add(name, val, "string"); + return newList; } - bool addBinary(const std::string &name, const void *data, size_t size); - - bool addList(const std::string &name) { - if(!entryNode) - return false; + List* getList(const std::string &name) { + std::map<std::string, List*>::iterator list = lists.find(name); - if(elements.find(name) != elements.end() || lists.find(name) != lists.end()) - return false; + if(list == lists.end()) + return 0; - xmlNodePtr newNode = xmlNewChild(entryNode, 0, (xmlChar*)"list", 0); - xmlSetProp(newNode, (xmlChar*)"name", (xmlChar*)name.c_str()); + return list->second; + } - if(!lists.insert(std::make_pair(name, new List(newNode))).second) { - xmlUnlinkNode(newNode); - xmlFreeNode(newNode); + const List* getList(const std::string &name) const { + std::map<std::string, List*>::const_iterator list = lists.find(name); - return false; - } + if(list == lists.end()) + return 0; - return true; + return list->second; } - bool remove(const std::string &name) { + void unset(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); + delete element->second; + elements.erase(element); - return true; + return; } std::map<std::string, List*>::iterator list = lists.find(name); @@ -403,69 +273,162 @@ class XmlPacket { xmlUnlinkNode(list->second->elementNode); xmlFreeNode(list->second->elementNode); + delete list->second; + lists.erase(list); - return true; + return; } - return false; + return; } }; - class List : public Element { + class List : private boost::noncopyable { private: - // Prevent shallow copy - List(const List &o); - List& operator=(const List &o); + friend class Entry; + + xmlNodePtr elementNode; std::vector<Entry*> entries; - public: + template <typename Type, typename IteratorType> + class iterator_base { + public: + friend class List; + + typedef Type value_type; + + typedef value_type &reference; + typedef value_type *pointer; + + typedef ssize_t difference_type; + + private: + IteratorType it; + + iterator_base(IteratorType it0) : it(it0) {} + + public: + iterator_base() {} + + reference operator*() const { + return **it; + } + + iterator_base operator+(const difference_type &n) const { + return iterator(it+n); + } + + iterator_base operator++(int) { + return iterator(it++); + } + + iterator_base& operator++() { + ++it; + return *this; + } + + iterator_base& operator+=(const difference_type &n) { + it += n; + return *this; + } + + iterator_base operator-(const difference_type &n) const { + return iterator(it-n); + } + + iterator_base operator--(int) { + return iterator(it--); + } + + iterator_base& operator--() { + --it; + return *this; + } + + iterator_base& operator-=(const difference_type &n) { + it -= n; + return *this; + } + + bool operator==(const iterator_base &it2) { + return it2.it == it; + } + + bool operator!=(const iterator_base &it2) { + return it2.it != it; + } + + pointer operator->() const { + return *it; + } + + reference operator[](const difference_type &n) const { + return *it[n]; + } + }; + List(xmlNodePtr node); - virtual ~List(); + ~List() { + for(std::vector<Entry*>::iterator entry = entries.begin(); entry != entries.end(); ++entry) + delete *entry; + } - virtual size_t getSize() const { + public: + typedef iterator_base<Entry, std::vector<Entry*>::iterator> iterator; + typedef iterator_base<const Entry, std::vector<Entry*>::const_iterator> const_iterator; + + size_t getSize() const { return entries.size(); } - virtual bool isEmpty() const { + bool isEmpty() const { return entries.empty(); } - virtual Entry& operator[](size_t i) { + Entry& operator[](size_t i) { return *entries[i]; } - virtual const Entry& operator[](size_t i) const { + 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); + iterator begin() { + return iterator(entries.begin()); + } - entries.insert(entries.begin()+i, new Entry(newNode)); + const_iterator begin() const { + return const_iterator(entries.begin()); + } - return true; + iterator end() { + return iterator(entries.end()); } - virtual bool addEntry() { - return insertEntry(getSize()); + const_iterator end() const { + return const_iterator(entries.end()); } - virtual bool removeEntry(size_t i) { - if(i >= getSize()) - return false; + // TODO Correct ordering + iterator insertEntry(iterator it) { + xmlNodePtr newNode = xmlNewNode(0, (xmlChar*)"entry"); + xmlAddChild(elementNode, newNode); - xmlUnlinkNode(entries[i]->entryNode); - xmlFreeNode(entries[i]->entryNode); + return iterator(entries.insert(it.it, new Entry(newNode))); + } - entries.erase(entries.begin()+i); + virtual iterator addEntry() { + return insertEntry(end()); + } - return true; + virtual void removeEntry(iterator it) { + xmlUnlinkNode(it->entryNode); + xmlFreeNode(it->entryNode); + delete *it.it; + + entries.erase(it.it); } }; @@ -484,34 +447,41 @@ class XmlPacket { std::string getType() const; void setType(const std::string &type); - Element& operator[](const std::string &name) { - return entry->operator[](name); + template <typename T> + bool set(const std::string &name, T val) { + return entry->set(name, val); } - const Element& operator[](const std::string &name) const { - return entry->operator[](name); + template <typename T> + T get(const std::string &name) const { + return entry->get<T>(name); } - template <typename T> - bool add(const std::string &name, T val) { - return entry->add(name, val); + List* createList(const std::string &name, bool unique = false) { + return entry->createList(name, unique); } - bool addBinary(const std::string &name, const void *data, size_t size) { - return entry->addBinary(name, data, size); + List* getList(const std::string &name) { + return entry->getList(name); } - bool addList(const std::string &name) { - return entry->addList(name); + const List* getList(const std::string &name) const { + return entry->getList(name); } - bool remove(const std::string &name) { - return entry->remove(name); + void unset(const std::string &name) { + entry->unset(name); } Net::Packet encode(uint16_t requestId) const; }; +template <> std::string XmlPacket::Entry::get<std::string>(const std::string &name) const; +template <> const std::string& XmlPacket::Entry::get<const std::string&>(const std::string &name) const; + +template <> std::vector<boost::uint8_t> XmlPacket::Entry::get<std::vector<unsigned char> >(const std::string &name) const; +template <> const std::vector<boost::uint8_t>& XmlPacket::Entry::get<const std::vector<unsigned char>&>(const std::string &name) const; + } } |