From 9b623ea3943165fe7efb5e47a0b5b9452c1599e6 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Wed, 9 May 2018 00:09:55 +0200 Subject: 9.8 --- zenXml/zenxml/dom.h | 111 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 41 deletions(-) (limited to 'zenXml/zenxml/dom.h') diff --git a/zenXml/zenxml/dom.h b/zenXml/zenxml/dom.h index 09977f1d..c8959e4b 100755 --- a/zenXml/zenxml/dom.h +++ b/zenXml/zenxml/dom.h @@ -8,10 +8,12 @@ #define DOM_H_82085720723894567204564256 #include +#include #include #include #include "cvrt_text.h" //"readText/writeText" + namespace zen { class XmlDoc; @@ -20,11 +22,11 @@ class XmlDoc; class XmlElement { public: - XmlElement() : parent_(nullptr) {} + XmlElement() {} //Construct an empty XML element template - explicit XmlElement(const String& name, XmlElement* parentElement = nullptr) : name_(utfTo(name)), parent_(parentElement) {} + explicit XmlElement(const String& name, XmlElement* parent = nullptr) : name_(utfTo(name)), parent_(parent) {} ///Retrieve the name of this XML element. /** @@ -60,8 +62,8 @@ public: template bool getAttribute(const String& name, T& value) const { - auto it = attributes.find(utfTo(name)); - return it == attributes.end() ? false : readText(it->second, value); + auto it = attributesSorted_.find(utfTo(name)); + return it == attributesSorted_.end() ? false : readText(it->second->value, value); } ///Create or update an XML attribute. @@ -74,9 +76,19 @@ public: template void setAttribute(const String& name, const T& value) { + std::string attrName = utfTo(name); + std::string attrValue; writeText(value, attrValue); - attributes[utfTo(name)] = attrValue; + + auto it = attributesSorted_.find(attrName); + if (it != attributesSorted_.end()) + it->second->value = std::move(attrValue); + else + { + auto itBack = attributes_.insert(attributes_.end(), { attrName, std::move(attrValue) }); + attributesSorted_.emplace(std::move(attrName), itBack); + } } ///Remove the attribute with the given name. @@ -84,7 +96,15 @@ public: \tparam String Arbitrary string-like type: e.g. std::string, wchar_t*, char[], wchar_t, wxString, MyStringClass, ... */ template - void removeAttribute(const String& name) { attributes.erase(utfTo(name)); } + void removeAttribute(const String& name) + { + auto it = attributesSorted_.find(utfTo(name)); + if (it != attributesSorted_.end()) + { + attributes_.erase(it->second); + attributesSorted_.erase(it); + } + } ///Create a new child element and return a reference to it. /** @@ -94,10 +114,10 @@ public: template XmlElement& addChild(const String& name) { - std::string utf8Name = utfTo(name); - childElements.emplace_back(utf8Name, this); - XmlElement& newElement = childElements.back(); - childElementsSorted.emplace(utf8Name, &newElement); + std::string elemName = utfTo(name); + childElements_.emplace_back(elemName, this); + XmlElement& newElement = childElements_.back(); + childElementsSorted_.emplace(std::move(elemName), &newElement); return newElement; } @@ -110,8 +130,8 @@ public: template const XmlElement* getChild(const String& name) const { - auto it = childElementsSorted.find(utfTo(name)); - return it == childElementsSorted.end() ? nullptr : it->second; + auto it = childElementsSorted_.find(utfTo(name)); + return it == childElementsSorted_.end() ? nullptr : it->second; } ///\sa getChild @@ -121,8 +141,8 @@ public: return const_cast(static_cast(this)->getChild(name)); } - template < class IterTy, //underlying iterator type - class T, //target object type + template < class IterTy, //underlying iterator type + class T, //target object type class AccessPolicy > //access policy: see AccessPtrMap class PtrIter : public std::iterator, private AccessPolicy //get rid of shared_ptr indirection { @@ -159,11 +179,11 @@ public: \return A pair of STL begin/end iterators to access the child elements sequentially. */ template - std::pair getChildren(const String& name) const { return childElementsSorted.equal_range(utfTo(name)); } + std::pair getChildren(const String& name) const { return childElementsSorted_.equal_range(utfTo(name)); } ///\sa getChildren template - std::pair getChildren(const String& name) { return childElementsSorted.equal_range(utfTo(name)); } + std::pair getChildren(const String& name) { return childElementsSorted_.equal_range(utfTo(name)); } struct AccessListElement { @@ -183,41 +203,47 @@ public: \endcode \return A pair of STL begin/end iterators to access all child elements sequentially. */ - std::pair getChildren() const { return std::make_pair(childElements.begin(), childElements.end()); } + std::pair getChildren() const { return { childElements_.begin(), childElements_.end() }; } ///\sa getChildren - std::pair getChildren() { return std::make_pair(childElements.begin(), childElements.end()); } + std::pair getChildren() { return { childElements_.begin(), childElements_.end() }; } ///Get parent XML element, may be nullptr for root element XmlElement* parent() { return parent_; } ///Get parent XML element, may be nullptr for root element const XmlElement* parent() const { return parent_; } - using AttrIter = std::map::const_iterator; + struct Attribute + { + std::string name; + std::string value; + }; + using AttrIter = std::list::const_iterator; /* -> disabled documentation extraction \brief Get all attributes associated with the element. \code auto iterPair = elem.getAttributes(); for (auto it = iterPair.first; it != iterPair.second; ++it) - std::cout << "name: " << it->first << " value: " << it->second << "\n"; + std::cout << "name: " << it->name << " value: " << it->value << "\n"; \endcode \return A pair of STL begin/end iterators to access all attributes sequentially as a list of name/value pairs of std::string. */ - std::pair getAttributes() const { return std::make_pair(attributes.begin(), attributes.end()); } + std::pair getAttributes() const { return { attributes_.begin(), attributes_.end() }; } //swap two elements while keeping references to parent. -> disabled documentation extraction void swapSubtree(XmlElement& other) { - name_ .swap(other.name_); - value_ .swap(other.value_); - attributes.swap(other.attributes); - childElements.swap(other.childElements); - childElementsSorted.swap(other.childElementsSorted); - //std::swap(parent_, other.parent_); -> parent is physical location; update children's parent reference instead: - for (XmlElement& child : childElements) + name_ .swap(other.name_); + value_ .swap(other.value_); + attributes_ .swap(other.attributes_); + attributesSorted_ .swap(other.attributesSorted_); + childElements_ .swap(other.childElements_); + childElementsSorted_.swap(other.childElementsSorted_); + + for (XmlElement& child : childElements_) child.parent_ = this; - for (XmlElement& child : other.childElements) + for (XmlElement& child : other.childElements_) child.parent_ = &other; } @@ -227,10 +253,13 @@ private: std::string name_; std::string value_; - std::map attributes; - FixedList childElements; //all child elements in order of creation - std::multimap childElementsSorted; //alternate key: sorted by element name - XmlElement* parent_; + + std::list attributes_; //attributes in order of creation + std::map::iterator> attributesSorted_; //alternate view: sorted by attribute name + + FixedList childElements_; //child elements in order of creation + std::multimap childElementsSorted_; //alternate view: sorted by element name + XmlElement* parent_ = nullptr; }; @@ -247,7 +276,7 @@ class XmlDoc { public: ///Default constructor setting up an empty XML document with a standard declaration: - XmlDoc() : version_("1.0"), encoding_("UTF-8"), rootElement("Root") {} + XmlDoc() {} XmlDoc(XmlDoc&& tmp) { swap(tmp); } XmlDoc& operator=(XmlDoc&& tmp) { swap(tmp); return *this; } @@ -258,12 +287,12 @@ public: \param rootName The name of the XML document's root element. */ template - XmlDoc(String rootName) : version_("1.0"), encoding_("UTF-8"), rootElement(rootName) {} + XmlDoc(String rootName) : root_(rootName) {} ///Get a const reference to the document's root element. - const XmlElement& root() const { return rootElement; } + const XmlElement& root() const { return root_; } ///Get a reference to the document's root element. - XmlElement& root() { return rootElement; } + XmlElement& root() { return root_; } ///Get the version used in the XML declaration. /** @@ -313,18 +342,18 @@ public: version_ .swap(other.version_); encoding_ .swap(other.encoding_); standalone_.swap(other.standalone_); - rootElement.swapSubtree(other.rootElement); + root_.swapSubtree(other.root_); } private: XmlDoc (const XmlDoc&) = delete; //not implemented, thanks to XmlElement::parent_ XmlDoc& operator=(const XmlDoc&) = delete; - std::string version_; - std::string encoding_; + std::string version_ { "1.0" }; + std::string encoding_{ "UTF-8" }; std::string standalone_; - XmlElement rootElement; + XmlElement root_{ "Root" }; }; } -- cgit