Skip to content

Commit

Permalink
use a template to reduce duplicated code
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Smith committed Dec 23, 2020
1 parent 0ad4b86 commit 3a78377
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 59 deletions.
38 changes: 20 additions & 18 deletions modules/c++/xml.lite/include/xml/lite/Element.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,8 @@ class Element
/*!
* \param std::nothrow -- will still throw if MULTIPLE elements are found, returns NULL if none
*/
Element* getElementByTagNameNS(std::nothrow_t, const std::string& qname,
bool recurse = false) const;
Element& getElementByTagNameNS(const std::string& qname,
bool recurse = false) const
Element* getElementByTagNameNS(std::nothrow_t, const std::string& qname, bool recurse = false) const;
Element& getElementByTagNameNS(const std::string& qname, bool recurse = false) const
{
auto pElement = getElementByTagNameNS(std::nothrow, qname, recurse);
if (pElement == nullptr)
Expand All @@ -190,8 +188,7 @@ class Element
* Utility for people that dont like to pass by reference
*
*/
std::vector<Element*> getElementsByTagNameNS(const std::string& qname,
bool recurse = false) const
std::vector<Element*> getElementsByTagNameNS(const std::string& qname, bool recurse = false) const
{
std::vector<Element*> v;
getElementsByTagNameNS(qname, v, recurse);
Expand All @@ -210,10 +207,8 @@ class Element
/*!
* \param std::nothrow -- will still throw if MULTIPLE elements are found, returns NULL if none
*/
Element* getElementByTagName(std::nothrow_t, const std::string& localName,
bool recurse = false) const;
Element& getElementByTagName(const std::string& localName,
bool recurse = false) const
Element* getElementByTagName(std::nothrow_t, const std::string& localName, bool recurse = false) const;
Element& getElementByTagName(const std::string& localName, bool recurse = false) const
{
auto pElement = getElementByTagName(std::nothrow, localName, recurse);
if (pElement == nullptr)
Expand All @@ -240,18 +235,15 @@ class Element
* \param localName the local name
* \param elements the elements that match the QName
*/
void getElementsByTagName(const std::string& uri,
const std::string& localName,
void getElementsByTagName(const std::string& uri, const std::string& localName,
std::vector<Element*>& elements,
bool recurse = false) const;
/*!
* \param std::nothrow -- will still throw if MULTIPLE elements are found, returns NULL if none
*/
Element* getElementByTagName(std::nothrow_t, const std::string& uri,
const std::string& localName,
Element* getElementByTagName(std::nothrow_t, const std::string& uri, const std::string& localName,
bool recurse = false) const;
Element& getElementByTagName(const std::string& uri,
const std::string& localName,
Element& getElementByTagName(const std::string& uri, const std::string& localName,
bool recurse = false) const
{
auto pElement = getElementByTagName(std::nothrow, uri, localName, recurse);
Expand All @@ -262,6 +254,17 @@ class Element
return *pElement;
}

/*!
* Utility for people that dont like to pass by reference
*/
std::vector<Element*> getElementsByTagName(const std::string& uri, const std::string& localName,
bool recurse = false) const
{
std::vector<Element*> v;
getElementsByTagName(uri, localName, v, recurse);
return v;
}

/*!
* 1) Find this child's attribute and change it
* 2) Recursively descend over children and fix all
Expand Down Expand Up @@ -306,8 +309,7 @@ class Element
* \param localName the local name to search for
* \return true if it exists, false if not
*/
bool hasElement(const std::string& uri,
const std::string& localName) const;
bool hasElement(const std::string& uri, const std::string& localName) const;

/*!
* Returns the character data of this element.
Expand Down
66 changes: 25 additions & 41 deletions modules/c++/xml.lite/source/Element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ void xml::lite::Element::clone(const xml::lite::Element& node)
}
}

bool xml::lite::Element::hasElement(const std::string& uri,
const std::string& localName) const
bool xml::lite::Element::hasElement(const std::string& uri, const std::string& localName) const
{

for (unsigned int i = 0; i < mChildren.size(); i++)
Expand All @@ -86,8 +85,7 @@ bool xml::lite::Element::hasElement(const std::string& localName) const
return false;
}

void xml::lite::Element::getElementsByTagName(const std::string& uri,
const std::string& localName,
void xml::lite::Element::getElementsByTagName(const std::string& uri, const std::string& localName,
std::vector<Element*>& elements,
bool recurse) const
{
Expand All @@ -101,12 +99,10 @@ void xml::lite::Element::getElementsByTagName(const std::string& uri,
}
}

xml::lite::Element* xml::lite::Element::getElementByTagName(std::nothrow_t, const std::string& uri,
const std::string& localName,
bool recurse) const
template <typename TGetElements>
xml::lite::Element* getElement(TGetElements getElements, const except::Context& ctxt)
{
std::vector<Element*> elements;
getElementsByTagName(uri, localName, elements, recurse);
auto elements = getElements();
if (elements.empty())
{
return nullptr;
Expand All @@ -115,11 +111,20 @@ xml::lite::Element* xml::lite::Element::getElementByTagName(std::nothrow_t, cons
{
// Yes, this is "nothrow" ... that's for found/non-found status. We
// asked for an ELEMENT, not "elements".
throw XMLException(Ctxt("Multiple elements returned for '" + localName + "' (uri=" + uri + ")."));
throw xml::lite::XMLException(ctxt);
}
return elements[0];
}

xml::lite::Element* xml::lite::Element::getElementByTagName(std::nothrow_t,
const std::string& uri, const std::string& localName,
bool recurse) const
{
auto getElements = [&]() { return getElementsByTagName(uri, localName, recurse); };
const auto ctxt(Ctxt("Multiple elements returned for '" + localName + "' (uri=" + uri + ")."));
return getElement(getElements, ctxt);
}

void xml::lite::Element::getElementsByTagName(const std::string& localName,
std::vector<Element*>& elements,
bool recurse) const
Expand All @@ -133,22 +138,12 @@ void xml::lite::Element::getElementsByTagName(const std::string& localName,
}
}

xml::lite::Element* xml::lite::Element::getElementByTagName(std::nothrow_t, const std::string& localName,
bool recurse) const
xml::lite::Element* xml::lite::Element::getElementByTagName(std::nothrow_t,
const std::string& localName, bool recurse) const
{
std::vector<Element*> elements;
getElementsByTagName(localName, elements, recurse);
if (elements.empty())
{
return nullptr;
}
if (elements.size() > 1)
{
// Yes, this is "nothrow" ... that's for found/non-found status. We
// asked for an ELEMENT, not "elements".
throw XMLException(Ctxt("Multiple elements returned for '" + localName + "'."));
}
return elements[0];
auto getElements = [&]() { return getElementsByTagName(localName, recurse); };
const auto ctxt(Ctxt("Multiple elements returned for '" + localName + "'."));
return getElement(getElements, ctxt);
}

void xml::lite::Element::getElementsByTagNameNS(const std::string& qname,
Expand All @@ -164,22 +159,12 @@ void xml::lite::Element::getElementsByTagNameNS(const std::string& qname,
}
}

xml::lite::Element* xml::lite::Element::getElementByTagNameNS(std::nothrow_t, const std::string& qname,
bool recurse) const
xml::lite::Element* xml::lite::Element::getElementByTagNameNS(std::nothrow_t,
const std::string& qname, bool recurse) const
{
std::vector<Element*> elements;
getElementsByTagNameNS(qname, elements, recurse);
if (elements.empty())
{
return nullptr;
}
if (elements.size() > 1)
{
// Yes, this is "nothrow" ... that's for found/non-found status. We
// asked for an ELEMENT, not "elements".
throw XMLException(Ctxt("Multiple elements returned for '" + qname + "'."));
}
return elements[0];
auto getElements = [&]() { return getElementsByTagNameNS(qname, recurse); };
const auto ctxt(Ctxt("Multiple elements returned for '" + qname + "'."));
return getElement(getElements, ctxt);
}

void xml::lite::Element::destroyChildren()
Expand Down Expand Up @@ -249,7 +234,6 @@ void xml::lite::Element::getCharacterData(sys::U8string& result) const
if (encoding == xml::lite::string_encoding::utf_8)
{
// already in UTF-8, no converstion necessary
const auto pCharacterData = reinterpret_cast<sys::U8string::const_pointer>(mCharacterData.c_str());
result = str::castToU8string(mCharacterData);
}
else if (encoding == xml::lite::string_encoding::windows_1252)
Expand Down

0 comments on commit 3a78377

Please sign in to comment.