summaryrefslogtreecommitdiff
path: root/zenXml/zenxml/dom.h
diff options
context:
space:
mode:
authorDaniel Wilhelm <shieldwed@outlook.com>2018-05-09 00:09:55 +0200
committerDaniel Wilhelm <shieldwed@outlook.com>2018-05-09 00:09:55 +0200
commit9b623ea3943165fe7efb5e47a0b5b9452c1599e6 (patch)
treedde40e07e907ac6e0ca9ea32524f2cd4810d4be6 /zenXml/zenxml/dom.h
parent9.7 (diff)
downloadFreeFileSync-9b623ea3943165fe7efb5e47a0b5b9452c1599e6.tar.gz
FreeFileSync-9b623ea3943165fe7efb5e47a0b5b9452c1599e6.tar.bz2
FreeFileSync-9b623ea3943165fe7efb5e47a0b5b9452c1599e6.zip
9.8
Diffstat (limited to 'zenXml/zenxml/dom.h')
-rwxr-xr-xzenXml/zenxml/dom.h111
1 files changed, 70 insertions, 41 deletions
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 <string>
+#include <list>
#include <map>
#include <zen/fixed_list.h>
#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 <class String>
- explicit XmlElement(const String& name, XmlElement* parentElement = nullptr) : name_(utfTo<std::string>(name)), parent_(parentElement) {}
+ explicit XmlElement(const String& name, XmlElement* parent = nullptr) : name_(utfTo<std::string>(name)), parent_(parent) {}
///Retrieve the name of this XML element.
/**
@@ -60,8 +62,8 @@ public:
template <class String, class T>
bool getAttribute(const String& name, T& value) const
{
- auto it = attributes.find(utfTo<std::string>(name));
- return it == attributes.end() ? false : readText(it->second, value);
+ auto it = attributesSorted_.find(utfTo<std::string>(name));
+ return it == attributesSorted_.end() ? false : readText(it->second->value, value);
}
///Create or update an XML attribute.
@@ -74,9 +76,19 @@ public:
template <class String, class T>
void setAttribute(const String& name, const T& value)
{
+ std::string attrName = utfTo<std::string>(name);
+
std::string attrValue;
writeText(value, attrValue);
- attributes[utfTo<std::string>(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 <class String>
- void removeAttribute(const String& name) { attributes.erase(utfTo<std::string>(name)); }
+ void removeAttribute(const String& name)
+ {
+ auto it = attributesSorted_.find(utfTo<std::string>(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 <class String>
XmlElement& addChild(const String& name)
{
- std::string utf8Name = utfTo<std::string>(name);
- childElements.emplace_back(utf8Name, this);
- XmlElement& newElement = childElements.back();
- childElementsSorted.emplace(utf8Name, &newElement);
+ std::string elemName = utfTo<std::string>(name);
+ childElements_.emplace_back(elemName, this);
+ XmlElement& newElement = childElements_.back();
+ childElementsSorted_.emplace(std::move(elemName), &newElement);
return newElement;
}
@@ -110,8 +130,8 @@ public:
template <class String>
const XmlElement* getChild(const String& name) const
{
- auto it = childElementsSorted.find(utfTo<std::string>(name));
- return it == childElementsSorted.end() ? nullptr : it->second;
+ auto it = childElementsSorted_.find(utfTo<std::string>(name));
+ return it == childElementsSorted_.end() ? nullptr : it->second;
}
///\sa getChild
@@ -121,8 +141,8 @@ public:
return const_cast<XmlElement*>(static_cast<const XmlElement*>(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<std::input_iterator_tag, T>, 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 <class String>
- std::pair<ChildIterConst2, ChildIterConst2> getChildren(const String& name) const { return childElementsSorted.equal_range(utfTo<std::string>(name)); }
+ std::pair<ChildIterConst2, ChildIterConst2> getChildren(const String& name) const { return childElementsSorted_.equal_range(utfTo<std::string>(name)); }
///\sa getChildren
template <class String>
- std::pair<ChildIter2, ChildIter2> getChildren(const String& name) { return childElementsSorted.equal_range(utfTo<std::string>(name)); }
+ std::pair<ChildIter2, ChildIter2> getChildren(const String& name) { return childElementsSorted_.equal_range(utfTo<std::string>(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<ChildIterConst, ChildIterConst> getChildren() const { return std::make_pair(childElements.begin(), childElements.end()); }
+ std::pair<ChildIterConst, ChildIterConst> getChildren() const { return { childElements_.begin(), childElements_.end() }; }
///\sa getChildren
- std::pair<ChildIter, ChildIter> getChildren() { return std::make_pair(childElements.begin(), childElements.end()); }
+ std::pair<ChildIter, ChildIter> 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<std::string, std::string>::const_iterator;
+ struct Attribute
+ {
+ std::string name;
+ std::string value;
+ };
+ using AttrIter = std::list<Attribute>::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<AttrIter, AttrIter> getAttributes() const { return std::make_pair(attributes.begin(), attributes.end()); }
+ std::pair<AttrIter, AttrIter> 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<std::string, std::string> attributes;
- FixedList<XmlElement> childElements; //all child elements in order of creation
- std::multimap<std::string, XmlElement*> childElementsSorted; //alternate key: sorted by element name
- XmlElement* parent_;
+
+ std::list<Attribute> attributes_; //attributes in order of creation
+ std::map<std::string, std::list<Attribute>::iterator> attributesSorted_; //alternate view: sorted by attribute name
+
+ FixedList<XmlElement> childElements_; //child elements in order of creation
+ std::multimap<std::string, XmlElement*> 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: <?xml version="1.0" encoding="UTF-8" ?>
- 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 <class String>
- 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" };
};
}
bgstack15