summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2019-02-14 14:01:44 +0300
committerGeorge Hazan <ghazan@miranda.im>2019-02-14 14:01:44 +0300
commit8368f365becd8668dbce2e40cecc7ba4f882f41b (patch)
treed446e441cf00d86f5cfb59ac5fd91cad6c0d37c8
parent2a704d136a65cc39ead589a6bbbc99b28a4bab82 (diff)
XML iterators, first version
-rw-r--r--include/m_xml.h128
-rw-r--r--plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp23
-rw-r--r--plugins/CurrencyRates/src/DBUtils.cpp2
-rw-r--r--plugins/CurrencyRates/src/ImportExport.cpp20
4 files changed, 148 insertions, 25 deletions
diff --git a/include/m_xml.h b/include/m_xml.h
index 1c8dffc1f5..ee50229082 100644
--- a/include/m_xml.h
+++ b/include/m_xml.h
@@ -45,6 +45,134 @@ typedef tinyxml2::XMLElement TiXmlElement;
typedef tinyxml2::XMLDocument TiXmlDocument;
/////////////////////////////////////////////////////////////////////////////////////////
+// simple element iterator
+//
+// allows traversing subnodes in a cycle like
+// for (auto *pNode : TiXmlEnum(pRoot)) {
+
+class TiXmlIterator
+{
+ const TiXmlElement *m_pCurr;
+
+public:
+ TiXmlIterator(const TiXmlElement *pNode) :
+ m_pCurr(pNode)
+ {
+ }
+
+ TiXmlIterator& operator=(const TiXmlElement *pNode)
+ {
+ m_pCurr = pNode;
+ return *this;
+ }
+
+ // Prefix ++ overload
+ TiXmlIterator& operator++()
+ {
+ if (m_pCurr)
+ m_pCurr = m_pCurr->NextSiblingElement();
+ return *this;
+ }
+
+ const TiXmlElement* operator*()
+ {
+ return m_pCurr;
+ }
+
+ bool operator!=(const TiXmlIterator &iterator)
+ {
+ return m_pCurr != iterator.m_pCurr;
+ }
+};
+
+class TiXmlEnum
+{
+ const TiXmlElement *m_pFirst;
+
+public:
+ TiXmlEnum(const TiXmlNode *pNode)
+ {
+ m_pFirst = (pNode) ? pNode->FirstChildElement() : nullptr;
+ }
+
+ TiXmlIterator begin()
+ {
+ return TiXmlIterator(m_pFirst);
+ }
+
+ TiXmlIterator end()
+ {
+ return TiXmlIterator(nullptr);
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// filtered element iterator
+//
+// allows traversing subnodes of the specified name in a cycle like
+// for (auto *pNode : TiXmlFilter(pRoot, "element")) {
+
+class TiXmlFilterIterator
+{
+ const TiXmlElement *m_pCurr;
+ const char *m_pszFilter;
+
+public:
+ TiXmlFilterIterator(const TiXmlElement *pNode, const char *pszNodeName) :
+ m_pszFilter(pszNodeName),
+ m_pCurr(pNode)
+ {
+ }
+
+ TiXmlFilterIterator& operator=(const TiXmlElement *pNode)
+ {
+ m_pCurr = pNode;
+ return *this;
+ }
+
+ // Prefix ++ overload
+ TiXmlFilterIterator& operator++()
+ {
+ if (m_pCurr)
+ m_pCurr = m_pCurr->NextSiblingElement(m_pszFilter);
+ return *this;
+ }
+
+ const TiXmlElement* operator*()
+ {
+ return m_pCurr;
+ }
+
+ bool operator!=(const TiXmlFilterIterator &iterator)
+ {
+ return m_pCurr != iterator.m_pCurr;
+ }
+};
+
+class TiXmlFilter
+{
+ const TiXmlElement *m_pFirst;
+ const char *m_pszFilter;
+
+public:
+ TiXmlFilter(const TiXmlNode *pNode, const char *pszNodeName) :
+ m_pszFilter(pszNodeName)
+ {
+ m_pFirst = (pNode) ? pNode->FirstChildElement() : nullptr;
+ }
+
+ TiXmlFilterIterator begin()
+ {
+ return TiXmlFilterIterator(m_pFirst, m_pszFilter);
+ }
+
+ TiXmlFilterIterator end()
+ {
+ return TiXmlFilterIterator(nullptr, nullptr);
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
// old API to be removed once
DECLARE_HANDLE(HXML);
diff --git a/plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp b/plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp
index 41e9b00c88..dda1e9cc18 100644
--- a/plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp
+++ b/plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp
@@ -20,7 +20,7 @@ bool parse_currencyrate(const TiXmlNode *pTop, CCurrencyRatesProviderBase::CCurr
{
tstring sSymbol, sDescription, sID;
- for (auto *pNode = pTop->FirstChildElement(); pNode != nullptr; pNode = pNode->NextSiblingElement()) {
+ for (auto *pNode : TiXmlEnum(pTop)) {
const char *sName = pNode->Value();
if (!mir_strcmpi(sName, "symbol")) {
sSymbol = GetNodeText(pNode);
@@ -47,7 +47,7 @@ bool parse_section(const TiXmlNode *pTop, CCurrencyRatesProviderBase::CCurrencyR
CCurrencyRatesProviderBase::CCurrencyRateSection::TCurrencyRates aCurrencyRates;
tstring sSectionName;
- for (auto *pNode = pTop->FirstChildElement(); pNode != nullptr; pNode = pNode->NextSiblingElement()) {
+ for (auto *pNode : TiXmlEnum(pTop)) {
const char *sName = pNode->Value();
if (!mir_strcmpi(sName, "section")) {
CCurrencyRatesProviderBase::CCurrencyRateSection qs1;
@@ -72,21 +72,16 @@ bool parse_section(const TiXmlNode *pTop, CCurrencyRatesProviderBase::CCurrencyR
const TiXmlNode* find_provider(const TiXmlNode *pRoot)
{
- const TiXmlNode *pProvider = nullptr;
-
- for (auto *pNode = pRoot->FirstChildElement(); pNode != nullptr; pNode = pNode->NextSiblingElement()) {
+ for (auto *pNode : TiXmlEnum(pRoot)) {
const char *sName = pNode->Value();
- if (!mir_strcmpi(sName, "Provider")) {
- pProvider = pNode;
- break;
- }
+ if (!mir_strcmpi(sName, "Provider"))
+ return pNode;
- pProvider = find_provider(pNode);
- if (pProvider)
- break;
+ if (auto *pProvider = find_provider(pNode))
+ return pProvider;
}
- return pProvider;
+ return nullptr;
}
CCurrencyRatesProviderBase::CXMLFileInfo parse_ini_file(const tstring &rsXMLFile, bool &rbSucceded)
@@ -99,7 +94,7 @@ CCurrencyRatesProviderBase::CXMLFileInfo parse_ini_file(const tstring &rsXMLFile
const TiXmlNode *pProvider = find_provider(&doc);
if (pProvider) {
rbSucceded = true;
- for (auto *pNode = pProvider->FirstChildElement(); pNode != nullptr; pNode = pNode->NextSiblingElement()) {
+ for (auto *pNode : TiXmlEnum(pProvider)) {
const char *sName = pNode->Value();
if (!mir_strcmpi(sName, "section")) {
CCurrencyRatesProviderBase::CCurrencyRateSection qs;
diff --git a/plugins/CurrencyRates/src/DBUtils.cpp b/plugins/CurrencyRates/src/DBUtils.cpp
index 53e1f211b3..571bad0bfb 100644
--- a/plugins/CurrencyRates/src/DBUtils.cpp
+++ b/plugins/CurrencyRates/src/DBUtils.cpp
@@ -4,7 +4,7 @@ std::wstring GetNodeText(const TiXmlElement *pNode)
{
auto *pszText = pNode->GetText();
if (pszText)
- return Utf2T(pszText);
+ return Utf2T(pszText).get();
return std::wstring();
}
diff --git a/plugins/CurrencyRates/src/ImportExport.cpp b/plugins/CurrencyRates/src/ImportExport.cpp
index 3087670e18..47bb3e1b40 100644
--- a/plugins/CurrencyRates/src/ImportExport.cpp
+++ b/plugins/CurrencyRates/src/ImportExport.cpp
@@ -253,7 +253,7 @@ bool handle_module(MCONTACT hContact, const TiXmlElement *pXmlModule)
DBCONTACTWRITESETTING dbs;
dbs.szModule = szModuleName;
- for (auto *pSetting = pXmlModule->FirstChildElement(g_szXmlSetting); pSetting != nullptr; pSetting = pSetting->NextSiblingElement(g_szXmlSetting)) {
+ for (auto *pSetting : TiXmlFilter(pXmlModule, g_szXmlSetting)) {
auto *pNode = pSetting->FirstChildElement(g_szXmlName);
if (pNode == nullptr)
continue;
@@ -342,7 +342,7 @@ size_t count_contacts(const TiXmlNode *pXmlRoot, bool bInContactsGroup)
{
size_t cContacts = 0;
- for (auto *pNode = pXmlRoot->FirstChildElement(); pNode != nullptr; pNode = pNode->NextSiblingElement()) {
+ for (auto *pNode : TiXmlEnum(pXmlRoot)) {
const char *sName = pNode->Name();
if (false == bInContactsGroup) {
if (!mir_strcmpi(g_szXmlContacts, sName))
@@ -378,7 +378,7 @@ struct CContactState
const TiXmlNode* find_currencyrates_module(const TiXmlNode *pXmlContact)
{
- for (auto *pNode = pXmlContact->FirstChildElement(); pNode != nullptr; pNode = pNode->NextSiblingElement())
+ for (auto *pNode : TiXmlEnum(pXmlContact))
if ((!mir_strcmpi(g_szXmlModule, pNode->Name())) && (!mir_strcmpi(CURRENCYRATES_MODULE_NAME, pNode->GetText())))
return pNode;
@@ -391,7 +391,7 @@ TNameValue parse_setting_node(const TiXmlNode *pXmlSetting)
assert(pXmlSetting);
const char *sName, *sValue;
- for (auto *pNode = pXmlSetting->FirstChildElement(); pNode != nullptr; pNode = pNode->NextSiblingElement()) {
+ for (auto *pNode : TiXmlEnum(pXmlSetting)) {
if (!mir_strcmpi(g_szXmlName, pNode->Name()))
sName = pNode->GetText();
else if (!mir_strcmpi(g_szXmlValue, pNode->Name()))
@@ -403,7 +403,7 @@ TNameValue parse_setting_node(const TiXmlNode *pXmlSetting)
CCurrencyRatesProviders::TCurrencyRatesProviderPtr find_provider(const TiXmlNode *pXmlCurrencyRatesModule)
{
- for (auto *pNode = pXmlCurrencyRatesModule->FirstChildElement(g_szXmlSetting); pNode != nullptr; pNode = pNode->NextSiblingElement(g_szXmlSetting)) {
+ for (auto *pNode : TiXmlFilter(pXmlCurrencyRatesModule, g_szXmlSetting)) {
TNameValue Item = parse_setting_node(pNode);
if ((!mir_strcmpi(DB_STR_CURRENCYRATE_PROVIDER, Item.first)) && Item.second)
return CModuleInfo::GetCurrencyRateProvidersPtr()->FindProvider(Utf2T(Item.second).get());
@@ -429,7 +429,7 @@ bool get_contact_state(const TiXmlNode *pXmlContact, CContactState& cst)
{
const char *sFromID = nullptr, *sToID = nullptr;
- for (auto *pNode = m_pXmlCurrencyRates->FirstChildElement(g_szXmlSetting); pNode != nullptr; pNode = pNode->NextSiblingElement(g_szXmlSetting)) {
+ for (auto *pNode : TiXmlFilter(m_pXmlCurrencyRates, g_szXmlSetting)) {
TNameValue Item = parse_setting_node(pNode);
if (!mir_strcmpi(Item.first, DB_STR_FROM_ID))
sFromID = Item.second;
@@ -443,7 +443,7 @@ bool get_contact_state(const TiXmlNode *pXmlContact, CContactState& cst)
tstring GetXMLNodeValue(const char* pszXMLNodeName) const
{
- for (auto *pNode = m_pXmlCurrencyRates->FirstChildElement(g_szXmlSetting); pNode != nullptr; pNode = pNode->NextSiblingElement(g_szXmlSetting)) {
+ for (auto *pNode : TiXmlFilter(m_pXmlCurrencyRates, g_szXmlSetting)) {
TNameValue Item = parse_setting_node(pNode);
if (!mir_strcmpi(Item.first, pszXMLNodeName))
return Utf2T(Item.second).get();
@@ -489,7 +489,7 @@ bool import_contact(const TiXmlNode *pXmlContact, CImportContext &impctx)
if (!cst.m_hContact)
return false;
- for (auto *pNode = pXmlContact->FirstChildElement(g_szXmlModule); pNode != nullptr; pNode = pNode->NextSiblingElement(g_szXmlModule))
+ for (auto *pNode : TiXmlFilter(pXmlContact, g_szXmlModule))
if (!handle_module(cst.m_hContact, pNode))
return false;
@@ -503,7 +503,7 @@ bool import_contact(const TiXmlNode *pXmlContact, CImportContext &impctx)
size_t import_contacts(const TiXmlNode *pXmlContacts, CImportContext &impctx)
{
size_t cContacts = 0;
- for (auto *pNode = pXmlContacts->FirstChildElement(g_szXmlContact); pNode != nullptr; pNode = pNode->NextSiblingElement(g_szXmlContact))
+ for (auto *pNode : TiXmlFilter(pXmlContacts, g_szXmlContact))
if (import_contact(pNode, impctx))
++cContacts;
@@ -513,7 +513,7 @@ size_t import_contacts(const TiXmlNode *pXmlContacts, CImportContext &impctx)
size_t handle_contacts_node(const TiXmlNode *pXmlRoot, CImportContext& impctx)
{
size_t cContacts = 0;
- for (auto *pNode = pXmlRoot->FirstChildElement(); pNode != nullptr; pNode = pNode->NextSiblingElement()) {
+ for (auto *pNode : TiXmlEnum(pXmlRoot)) {
if (!mir_strcmpi(g_szXmlContacts, pNode->Name()))
cContacts += import_contacts(pNode, impctx);
else