summaryrefslogtreecommitdiff
path: root/zenXml/zenxml
diff options
context:
space:
mode:
Diffstat (limited to 'zenXml/zenxml')
-rwxr-xr-xzenXml/zenxml/bind.h55
-rwxr-xr-xzenXml/zenxml/cvrt_struc.h8
-rwxr-xr-xzenXml/zenxml/cvrt_text.h1
-rwxr-xr-xzenXml/zenxml/dom.h111
-rwxr-xr-xzenXml/zenxml/io.h1
-rwxr-xr-xzenXml/zenxml/parser.h22
-rwxr-xr-xzenXml/zenxml/xml.h1
7 files changed, 115 insertions, 84 deletions
diff --git a/zenXml/zenxml/bind.h b/zenXml/zenxml/bind.h
index f3cfa398..824c6cc6 100755
--- a/zenXml/zenxml/bind.h
+++ b/zenXml/zenxml/bind.h
@@ -12,6 +12,7 @@
#include "parser.h"
#include "io.h"
+
namespace zen
{
/**
@@ -167,17 +168,17 @@ public:
in["elem3"](value3); //
\endcode
*/
- XmlIn(const XmlDoc& doc) : log(std::make_shared<ErrorLog>()) { refList.push_back(&doc.root()); }
+ XmlIn(const XmlDoc& doc) : log_(std::make_shared<ErrorLog>()) { refList_.push_back(&doc.root()); }
///Construct an input proxy for a single XML element, may be nullptr
/**
\sa XmlIn(const XmlDoc& doc)
*/
- XmlIn(const XmlElement* element) : log(std::make_shared<ErrorLog>()) { refList.push_back(element); }
+ XmlIn(const XmlElement* element) : log_(std::make_shared<ErrorLog>()) { refList_.push_back(element); }
///Construct an input proxy for a single XML element
/**
\sa XmlIn(const XmlDoc& doc)
*/
- XmlIn(const XmlElement& element) : log(std::make_shared<ErrorLog>()) { refList.push_back(&element); }
+ XmlIn(const XmlElement& element) : log_(std::make_shared<ErrorLog>()) { refList_.push_back(&element); }
///Retrieve a handle to an XML child element for reading
/**
@@ -190,14 +191,14 @@ public:
{
std::vector<const XmlElement*> childList;
- if (refIndex < refList.size())
+ if (refIndex_ < refList_.size())
{
- auto iterPair = refList[refIndex]->getChildren(name);
+ auto iterPair = refList_[refIndex_]->getChildren(name);
std::for_each(iterPair.first, iterPair.second,
[&](const XmlElement& child) { childList.push_back(&child); });
}
- return XmlIn(childList, childList.empty() ? getChildNameFormatted(name) : std::string(), log);
+ return XmlIn(childList, childList.empty() ? getChildNameFormatted(name) : std::string(), log_);
}
///Refer to next sibling element with the same name
@@ -221,7 +222,7 @@ public:
}
\endcode
*/
- void next() { ++refIndex; }
+ void next() { ++refIndex_; }
///Read user data from the underlying XML element
/**
@@ -232,16 +233,16 @@ public:
template <class T>
bool operator()(T& value) const
{
- if (refIndex < refList.size())
+ if (refIndex_ < refList_.size())
{
- bool success = readStruc(*refList[refIndex], value);
+ bool success = readStruc(*refList_[refIndex_], value);
if (!success)
- log->notifyConversionError(getNameFormatted());
+ log_->notifyConversionError(getNameFormatted());
return success;
}
else
{
- log->notifyMissingElement(getNameFormatted());
+ log_->notifyMissingElement(getNameFormatted());
return false;
}
}
@@ -267,22 +268,22 @@ public:
template <class String, class T>
bool attribute(const String& name, T& value) const
{
- if (refIndex < refList.size())
+ if (refIndex_ < refList_.size())
{
- bool success = refList[refIndex]->getAttribute(name, value);
+ bool success = refList_[refIndex_]->getAttribute(name, value);
if (!success)
- log->notifyMissingAttribute(getNameFormatted(), utfTo<std::string>(name));
+ log_->notifyMissingAttribute(getNameFormatted(), utfTo<std::string>(name));
return success;
}
else
{
- log->notifyMissingElement(getNameFormatted());
+ log_->notifyMissingElement(getNameFormatted());
return false;
}
}
///Return a pointer to the underlying Xml element, may be nullptr
- const XmlElement* get() const { return refIndex < refList.size() ? refList[refIndex] : nullptr; }
+ const XmlElement* get() const { return refIndex_ < refList_.size() ? refList_[refIndex_] : nullptr; }
///Test whether the underlying XML element exists
/**
@@ -316,7 +317,7 @@ public:
However be aware that the chain of connected proxy instances will be broken once you call XmlIn::get() to retrieve the underlying pointer.
Errors that occur when working with this pointer are not logged by the original set of related instances.
*/
- bool errorsOccured() const { return !log->elementList().empty(); }
+ bool errorsOccured() const { return !log_->elementList().empty(); }
///Get a list of XML element and attribute names which failed to convert to user data.
/**
@@ -327,14 +328,14 @@ public:
std::vector<String> getErrorsAs() const
{
std::vector<String> output;
- const auto& elements = log->elementList();
+ const auto& elements = log_->elementList();
std::transform(elements.begin(), elements.end(), std::back_inserter(output), [](const std::string& str) { return utfTo<String>(str); });
return output;
}
private:
XmlIn(const std::vector<const XmlElement*>& siblingList, const std::string& elementNameFmt, const std::shared_ptr<ErrorLog>& sharedlog) :
- refList(siblingList), formattedName(elementNameFmt), log(sharedlog)
+ refList_(siblingList), formattedName_(elementNameFmt), log_(sharedlog)
{ assert((!siblingList.empty() && elementNameFmt.empty()) || (siblingList.empty() && !elementNameFmt.empty())); }
static std::string getNameFormatted(const XmlElement& elem) //"<Root> <Level1> <Level2>"
@@ -344,13 +345,13 @@ private:
std::string getNameFormatted() const
{
- if (refIndex < refList.size())
+ if (refIndex_ < refList_.size())
{
- assert(formattedName.empty());
- return getNameFormatted(*refList[refIndex]);
+ assert(formattedName_.empty());
+ return getNameFormatted(*refList_[refIndex_]);
}
else
- return formattedName;
+ return formattedName_;
}
std::string getChildNameFormatted(const std::string& childName) const
@@ -379,10 +380,10 @@ private:
std::set<std::string> usedElements;
};
- std::vector<const XmlElement*> refList; //all sibling elements with same name (all pointers bound!)
- size_t refIndex = 0; //this sibling's index in refList
- std::string formattedName; //contains full and formatted element name if (and only if) refList is empty
- std::shared_ptr<ErrorLog> log; //always bound
+ std::vector<const XmlElement*> refList_; //all sibling elements with same name (all pointers bound!)
+ size_t refIndex_ = 0; //this sibling's index in refList_
+ std::string formattedName_; //contains full and formatted element name if (and only if) refList_ is empty
+ std::shared_ptr<ErrorLog> log_; //always bound
};
}
diff --git a/zenXml/zenxml/cvrt_struc.h b/zenXml/zenxml/cvrt_struc.h
index 87687929..3a18ea73 100755
--- a/zenXml/zenxml/cvrt_struc.h
+++ b/zenXml/zenxml/cvrt_struc.h
@@ -9,6 +9,7 @@
#include "dom.h"
+
namespace zen
{
/**
@@ -42,11 +43,6 @@ template <class T> void writeStruc(const T& value, XmlElement& output);
-
-
-
-
-
//------------------------------ implementation -------------------------------------
namespace impl_2384343
{
@@ -140,7 +136,7 @@ struct ConvertElement<T, VALUE_TYPE_STL_CONTAINER>
value.insert(value.end(), childVal);
else
success = false;
- //should we support insertion of partially-loaded struct??
+ //should we support insertion of partially-loaded struct??
}
return success;
}
diff --git a/zenXml/zenxml/cvrt_text.h b/zenXml/zenxml/cvrt_text.h
index 6ff1ec94..17444861 100755
--- a/zenXml/zenxml/cvrt_text.h
+++ b/zenXml/zenxml/cvrt_text.h
@@ -10,6 +10,7 @@
#include <zen/utf.h>
#include <zen/string_tools.h>
+
namespace zen
{
/**
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" };
};
}
diff --git a/zenXml/zenxml/io.h b/zenXml/zenxml/io.h
index 1361d865..6d5a21d5 100755
--- a/zenXml/zenxml/io.h
+++ b/zenXml/zenxml/io.h
@@ -13,6 +13,7 @@
#include <zen/utf.h>
#include "error.h"
+
namespace zen
{
/**
diff --git a/zenXml/zenxml/parser.h b/zenXml/zenxml/parser.h
index bff2bb50..5c6a9ec2 100755
--- a/zenXml/zenxml/parser.h
+++ b/zenXml/zenxml/parser.h
@@ -73,7 +73,7 @@ XmlDoc parse(const std::string& stream); //throw XmlParsingError
//---------------------------- implementation ----------------------------
//see: http://www.w3.org/TR/xml/
-namespace implementation
+namespace impl
{
template <class Predicate> inline
std::string normalize(const std::string& str, Predicate pred) //pred: unary function taking a char, return true if value shall be encoded as hex
@@ -111,7 +111,9 @@ std::string normalize(const std::string& str, Predicate pred) //pred: unary func
inline
std::string normalizeName(const std::string& str)
{
- return normalize(str, [](char c) { return isWhiteSpace(c) || c == '=' || c == '/' || c == '\'' || c == '\"'; });
+ const std::string nameFmt = normalize(str, [](char c) { return isWhiteSpace(c) || c == '=' || c == '/' || c == '\'' || c == '\"'; });
+ assert(!nameFmt.empty());
+ return nameFmt;
}
inline
@@ -201,12 +203,12 @@ void serialize(const XmlElement& element, std::string& stream,
auto attr = element.getAttributes();
for (auto it = attr.first; it != attr.second; ++it)
- stream += ' ' + normalizeName(it->first) + "=\"" + normalizeAttribValue(it->second) + '\"';
+ stream += ' ' + normalizeName(it->name) + "=\"" + normalizeAttribValue(it->value) + '\"';
- //no support for mixed-mode content
auto iterPair = element.getChildren();
if (iterPair.first != iterPair.second) //structured element
{
+ //no support for mixed-mode content
stream += '>' + lineBreak;
std::for_each(iterPair.first, iterPair.second,
@@ -254,7 +256,7 @@ std::string serialize(const XmlDoc& doc,
inline
std::string serialize(const XmlDoc& doc,
const std::string& lineBreak,
- const std::string& indent) { return implementation::serialize(doc, lineBreak, indent); }
+ const std::string& indent) { return impl::serialize(doc, lineBreak, indent); }
/*
Grammar for XML parser
@@ -280,7 +282,7 @@ pm-expression:
element-list-expression
*/
-namespace implementation
+namespace impl
{
struct Token
{
@@ -355,7 +357,7 @@ public:
{
std::string name(&*pos, nameEnd - pos);
pos = nameEnd;
- return implementation::denormalize(name);
+ return denormalize(name);
}
//unknown token
@@ -371,7 +373,7 @@ public:
});
std::string output(pos, it);
pos = it;
- return implementation::denormalize(output);
+ return denormalize(output);
}
std::string extractAttributeValue()
@@ -385,7 +387,7 @@ public:
});
std::string output(pos, it);
pos = it;
- return implementation::denormalize(output);
+ return denormalize(output);
}
size_t posRow() const //current row beginning with 0
@@ -575,7 +577,7 @@ private:
inline
XmlDoc parse(const std::string& stream) //throw XmlParsingError
{
- return implementation::XmlParser(stream).parse(); //throw XmlParsingError
+ return impl::XmlParser(stream).parse(); //throw XmlParsingError
}
}
diff --git a/zenXml/zenxml/xml.h b/zenXml/zenxml/xml.h
index e0035c2b..9510645a 100755
--- a/zenXml/zenxml/xml.h
+++ b/zenXml/zenxml/xml.h
@@ -9,6 +9,7 @@
#include "bind.h"
+
/// The zen::Xml namespace
namespace zen {}
bgstack15