From 6445444fbf67df87030543d48f7f424ec631c4ea Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sat, 9 Dec 2017 19:44:52 +0100 Subject: [PATCH] Ref T203, utility functions for URL --- src/blackmisc/network/url.cpp | 64 +++++++++++++++++++++++++++---- src/blackmisc/network/url.h | 23 +++++++++++ src/blackmisc/network/urllist.cpp | 24 ++++++++---- src/blackmisc/network/urllist.h | 6 +++ 4 files changed, 101 insertions(+), 16 deletions(-) diff --git a/src/blackmisc/network/url.cpp b/src/blackmisc/network/url.cpp index 67a22e143..e2f708e71 100644 --- a/src/blackmisc/network/url.cpp +++ b/src/blackmisc/network/url.cpp @@ -162,7 +162,7 @@ namespace BlackMisc QUrl qurl(this->toQUrl()); qurl.setPort(port); qurl.setScheme(scheme); - CUrl url(qurl); + const CUrl url(qurl); return url; } @@ -171,6 +171,54 @@ namespace BlackMisc return m_path.endsWith(ending, cs); } + bool CUrl::isFile() const + { + const QString f(this->getFileName()); + return !f.isEmpty(); + } + + bool CUrl::isFileWithSuffix(const QString &suffix) const + { + const QString f(this->getFileName()); + if (suffix.isEmpty()) { return f.contains('.'); } + return f.endsWith(suffix, Qt::CaseInsensitive); + } + + bool CUrl::isExecutableFile() const + { + return CFileUtils::isExecutableFile(this->getFileName()); + } + + bool CUrl::isSwiftInstaller() const + { + return CFileUtils::isSwiftInstaller(this->getFileName()); + } + + QString CUrl::getFileSuffix() const + { + const QString f(this->getFileName()); + const int i = f.lastIndexOf('.'); + if (i < 0) return ""; + if (f.length() <= i + 1) return ""; // ends with "." + return f.mid(i + 1); // suffix without dot + } + + QString CUrl::getFileSuffixPlusDot() const + { + const QString f(this->getFileName()); + const int i = f.lastIndexOf('.'); + if (i < 0) return ""; + if (f.length() <= i + 1) return ""; // ends with "." + return f.mid(i); // suffix with dot + } + + bool CUrl::isHavingHtmlSuffix() const + { + static const QString h1(".html"); + static const QString h2(".htm"); + return this->isFileWithSuffix(h1) || this->isFileWithSuffix(h2); + } + CUrl CUrl::withAppendedQuery(const QString &query) const { if (query.isEmpty()) { return *this; } @@ -187,8 +235,8 @@ namespace BlackMisc QJsonObject CUrl::toJson() const { - QPair v("url", getFullUrl()); - QJsonObject json({ v }); + const QPair v("url", getFullUrl()); + const QJsonObject json({ v }); return json; } @@ -210,7 +258,7 @@ namespace BlackMisc bool CUrl::isDefaultPort(const QString &protocol, int port) { - int p = protocolToDefaultPort(protocol); + const int p = protocolToDefaultPort(protocol); if (p < 0) { return false; } return port == p; } @@ -240,10 +288,10 @@ namespace BlackMisc const ColumnIndex i = index.frontCasted(); switch (i) { - case IndexHost: return CVariant::fromValue(this->m_host); - case IndexPort: return CVariant::fromValue(this->m_port); - case IndexScheme: return CVariant::fromValue(this->m_scheme); - case IndexPath: return CVariant::fromValue(this->m_path); + case IndexHost: return CVariant::fromValue(m_host); + case IndexPort: return CVariant::fromValue(m_port); + case IndexScheme: return CVariant::fromValue(m_scheme); + case IndexPath: return CVariant::fromValue(m_path); default: return CValueObject::propertyByIndex(index); } } diff --git a/src/blackmisc/network/url.h b/src/blackmisc/network/url.h index 1364ede55..c4a287642 100644 --- a/src/blackmisc/network/url.h +++ b/src/blackmisc/network/url.h @@ -142,6 +142,29 @@ namespace BlackMisc //! Path ending with? bool pathEndsWith(const QString &ending, Qt::CaseSensitivity cs = Qt::CaseInsensitive) const; + //! A path ends with "/", and file is anythingy beyond that, e.g. "path/file" + //! \sa isFile with appendix + bool isFile() const; + + //! Stricter version of isFile() + bool isFileWithSuffix(const QString &suffix = {}) const; + + //! File appendix if any, otherwise empty, does not include the "." + //! \remark similar to QFileInfo::suffix() + QString getFileSuffix() const; + + //! Suffix plus dot + QString getFileSuffixPlusDot() const; + + //! Likely a HTM file? + bool isHavingHtmlSuffix() const; + + //! \copydoc BlackMisc::CFileUtils::isExecutableFile + bool isExecutableFile() const; + + //! \copydoc BlackMisc::CFileUtils::isSwiftInstaller + bool isSwiftInstaller() const; + //! \copydoc BlackMisc::Mixin::Index::propertyByIndex CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; diff --git a/src/blackmisc/network/urllist.cpp b/src/blackmisc/network/urllist.cpp index 6cf14f584..752b48619 100644 --- a/src/blackmisc/network/urllist.cpp +++ b/src/blackmisc/network/urllist.cpp @@ -147,13 +147,13 @@ namespace BlackMisc bool CFailoverUrlList::addFailedUrl(const CUrl &failedUrl) { Q_ASSERT_X(!failedUrl.isEmpty(), Q_FUNC_INFO, "empty URL as failed"); - this->m_failedUrls.push_back(failedUrl); + m_failedUrls.push_back(failedUrl); return hasMoreUrlsToTry(); } bool CFailoverUrlList::addFailedUrls(const CUrlList &failedUrls) { - this->m_failedUrls.push_back(failedUrls); + m_failedUrls.push_back(failedUrls); return hasMoreUrlsToTry(); } @@ -173,21 +173,29 @@ namespace BlackMisc bool CFailoverUrlList::hasMoreUrlsToTry() const { - if (this->isEmpty()) { return false; } - return (m_failedUrls.size() < this->size() && m_failedUrls.size() < m_maxTrials); + return this->numberOfStillValidUrls() > 0; + } + + int CFailoverUrlList::numberOfStillValidUrls() const + { + if (this->isEmpty()) { return 0; } + if (m_failedUrls.size() >= m_maxTrials) { return 0; } + const int trailsLeft1 = qMax(m_maxTrials - m_failedUrls.size(), 0); + const int trailsLeft2 = qMax(this->size() - m_failedUrls.size(), 0); + return qMin(trailsLeft1, trailsLeft2); } CUrl CFailoverUrlList::obtainNextWorkingUrl(bool random, int connectTimeoutMs) { if (!hasMoreUrlsToTry()) { return CUrl(); } - const CUrl url(this->obtainNextUrlWithout(random, this->m_failedUrls)); + const CUrl url(this->obtainNextUrlWithout(random, m_failedUrls)); QString msg; if (CNetworkUtils::canConnect(url, msg, connectTimeoutMs)) { return url; } if (addFailedUrl(url)) { if (!msg.isEmpty()) { - this->m_errorMsgs.append(QString("URL: %1 error: %2").arg(url.toQString(), msg)); + m_errorMsgs.append(QString("URL: %1 error: %2").arg(url.toQString(), msg)); } return obtainNextWorkingUrl(random, connectTimeoutMs); } @@ -226,8 +234,8 @@ namespace BlackMisc void CFailoverUrlList::reset(int maxTrials) { - this->m_failedUrls.clear(); - if (maxTrials >= 0) { this->m_maxTrials = maxTrials; } + m_failedUrls.clear(); + if (maxTrials >= 0) { m_maxTrials = maxTrials; } } } // namespace } // namespace diff --git a/src/blackmisc/network/urllist.h b/src/blackmisc/network/urllist.h index 4ce6e4175..4755ab068 100644 --- a/src/blackmisc/network/urllist.h +++ b/src/blackmisc/network/urllist.h @@ -87,6 +87,9 @@ namespace BlackMisc //! All failed URLs const CUrlList &getFailedUrls() const { return m_failedUrls; } + //! Size of failed URLs + int getFailedUrlsSize() const { return m_failedUrls.size(); } + //! Get without the failed URLs CUrlList getWithoutFailed() const; @@ -105,6 +108,9 @@ namespace BlackMisc //! More URLs to try bool hasMoreUrlsToTry() const; + //! Number of URLs which can be used for a retry + int numberOfStillValidUrls() const; + //! Next utl from this list CUrl obtainNextUrl(bool randomStart = false);