summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qtldurl.cpp
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2017-03-30 14:37:38 +0200
committerMarc Mutz <marc.mutz@kdab.com>2017-03-30 13:28:53 +0000
commit2cc1ff3bc2a247ada8fb62f37613d763fb664cf0 (patch)
tree56bfe851b2cefa6968c853124e19207fed3b1b8f /src/corelib/io/qtldurl.cpp
parentcb2246ad15241016063689de1600519202b87a93 (diff)
Optimize qIsEffectiveTLD()
TLD lookup is performed in up to three steps, which are decribed in a code comment. For the purposes of this patch, it suffices to mention that the last two steps involved a QStringBuilder expression. Avoid having to build these strings by distinguishing between the lookups using an enum instead of a string prefix. Since qt_hash() calls can now be chained, form the hash value by hashing the prefix character and the domain (part) separately. Also perform the expensive fromUtf8() call only when the string prefix (if any) matched. Once we have nothrow UTF-8/UTF-16 comparison operators, qIsEffectiveTLD() will no longer allocate memory, and run at full speed. Not there, yet, though. I have full confidence that the optimizer will have field day with this, inline all three containsTLDEntry() calls, and constant-fold the checks inside the loop. GCC does, so I didn't try to do it by hand. Change-Id: I1a7647ff52b6742310928ad859d851d1f0c6bdc3 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/io/qtldurl.cpp')
-rw-r--r--src/corelib/io/qtldurl.cpp42
1 files changed, 23 insertions, 19 deletions
diff --git a/src/corelib/io/qtldurl.cpp b/src/corelib/io/qtldurl.cpp
index 96543bbbfd..a934d19fa2 100644
--- a/src/corelib/io/qtldurl.cpp
+++ b/src/corelib/io/qtldurl.cpp
@@ -50,9 +50,21 @@
QT_BEGIN_NAMESPACE
-static bool containsTLDEntry(const QStringRef &entry)
+enum TLDMatchType {
+ ExactMatch,
+ SuffixMatch,
+ ExceptionMatch,
+};
+
+static bool containsTLDEntry(QStringView entry, TLDMatchType match)
{
- int index = qt_hash(entry) % tldCount;
+ const QStringView matchSymbols[] = {
+ QStringViewLiteral(""),
+ QStringViewLiteral("*"),
+ QStringViewLiteral("!"),
+ };
+ const auto symbol = matchSymbols[match];
+ int index = qt_hash(entry, qt_hash(symbol)) % tldCount;
// select the right chunk from the big table
short chunk = 0;
@@ -65,19 +77,14 @@ static bool containsTLDEntry(const QStringRef &entry)
// check all the entries from the given index
while (chunkIndex < tldIndices[index+1] - offset) {
- QString currentEntry = QString::fromUtf8(tldData[chunk] + chunkIndex);
- if (currentEntry == entry)
+ const auto utf8 = tldData[chunk] + chunkIndex;
+ if ((symbol.isEmpty() || QLatin1Char(*utf8) == symbol) && entry == QString::fromUtf8(utf8 + symbol.size()))
return true;
- chunkIndex += qstrlen(tldData[chunk] + chunkIndex) + 1; // +1 for the ending \0
+ chunkIndex += qstrlen(utf8) + 1; // +1 for the ending \0
}
return false;
}
-static inline bool containsTLDEntry(const QString &entry)
-{
- return containsTLDEntry(QStringRef(&entry));
-}
-
/*!
\internal
@@ -111,19 +118,16 @@ Q_CORE_EXPORT bool qIsEffectiveTLD(const QStringRef &domain)
{
// for domain 'foo.bar.com':
// 1. return if TLD table contains 'foo.bar.com'
- if (containsTLDEntry(domain))
+ // 2. else if table contains '*.bar.com',
+ // 3. test that table does not contain '!foo.bar.com'
+
+ if (containsTLDEntry(domain, ExactMatch)) // 1
return true;
const int dot = domain.indexOf(QLatin1Char('.'));
if (dot >= 0) {
- int count = domain.size() - dot;
- QString wildCardDomain = QLatin1Char('*') + domain.right(count);
- // 2. if table contains '*.bar.com',
- // test if table contains '!foo.bar.com'
- if (containsTLDEntry(wildCardDomain)) {
- QString exceptionDomain = QLatin1Char('!') + domain;
- return (! containsTLDEntry(exceptionDomain));
- }
+ if (containsTLDEntry(domain.mid(dot), SuffixMatch)) // 2
+ return !containsTLDEntry(domain, ExceptionMatch); // 3
}
return false;
}