diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2017-03-30 14:37:38 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2017-03-30 13:28:53 +0000 |
commit | 2cc1ff3bc2a247ada8fb62f37613d763fb664cf0 (patch) | |
tree | 56bfe851b2cefa6968c853124e19207fed3b1b8f /src/corelib/io/qtldurl.cpp | |
parent | cb2246ad15241016063689de1600519202b87a93 (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.cpp | 42 |
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; } |