diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2009-03-19 10:34:54 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2009-07-21 13:48:45 (GMT) |
commit | b01ae86c02d2ca81f30055be4641ca418ac94d9b (patch) | |
tree | 65a9e5436a8797655760be1888575a9cdc4c8040 /src | |
parent | 3b545a4008fed0250d61ce1bb54af1a47fd8df92 (diff) | |
download | Qt-b01ae86c02d2ca81f30055be4641ca418ac94d9b.zip Qt-b01ae86c02d2ca81f30055be4641ca418ac94d9b.tar.gz Qt-b01ae86c02d2ca81f30055be4641ca418ac94d9b.tar.bz2 |
Improve performance in QUrl parsing by doing in-line operations.
Unfortunately, I can't do it all inline because the punycode encoding
and decoding requires reading the source several times. (Maybe the
decoding can be done with some effort in the future)
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/io/qurl.cpp | 63 |
1 files changed, 32 insertions, 31 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index d65cee2..fcae0d6 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -2904,11 +2904,11 @@ static bool isBidirectionalL(const QChar &ch) #ifdef QT_BUILD_INTERNAL // export for tst_qurl.cpp Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from); -Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QStringRef &); +Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len); #else // non-test build, keep the symbols for ourselves -static QString void qt_nameprep(QString *source, int from) -static bool qt_check_std3rules(const QStringRef &); +static void qt_nameprep(QString *source, int from); +static bool qt_check_std3rules(const QChar *uc, int len); #endif void qt_nameprep(QString *source, int from) @@ -2966,14 +2966,13 @@ void qt_nameprep(QString *source, int from) } } -bool qt_check_std3rules(const QStringRef &source) +bool qt_check_std3rules(const QChar *uc, int len) { - int len = source.length(); if (len > 63) return false; for (int i = 0; i < len; ++i) { - register ushort c = source.at(i).unicode(); + register ushort c = uc[i].unicode(); if (c == '-' && (i == 0 || i == len - 1)) return false; @@ -3264,41 +3263,43 @@ static QString qt_ACE_do(const QString &domainMC, AceOperation op) simple = false; } - QString aux; - QStringRef label; + // copy the label to the destination, which also serves as our scratch area + int prevLen = result.size(); + result.resize(prevLen + idx - lastIdx); + memcpy(result.data() + prevLen, domain.constData() + lastIdx, (idx - lastIdx) * sizeof(QChar)); + if (simple) { - // fastest conversion: this is the common case (non IDN-domains) - // just memcpy from source (domain) to destination (result) + // fastest case: this is the common case (non IDN-domains) // there's no need to nameprep since everything is ASCII already - int prevLen = result.size(); - result.resize(prevLen + idx - lastIdx); - memcpy(result.data() + prevLen, domain.constData() + lastIdx, (idx - lastIdx) * sizeof(QChar)); - - label = QStringRef(&result, prevLen, result.length() - prevLen); - } else { + // so we're done + if (!qt_check_std3rules(result.constData() + prevLen, result.length() - prevLen)) + return QString(); + } else { // Nameprep the host. If the labels in the hostname are Punycode - // encoded, we decode them immediately, then nameprep them. - QString tmp = domain.mid(lastIdx, idx - lastIdx); - qt_nameprep(&tmp, 0); + // encoded, we decode them immediately. + qt_nameprep(&result, prevLen); - if (isIdnEnabled) { - toPunycodeHelper(tmp.constData(), tmp.size(), &aux); - label = QStringRef(&aux); + // Punycode encoding and decoding cannot be done in-place + // That means we need one or two temporaries + QString aceForm; + aceForm.reserve(result.size() - prevLen + 4 + 4); // "xn--" and "-xyz" + toPunycodeHelper(result.constData() + prevLen, result.size() - prevLen, &aceForm); - tmp = QUrl::fromPunycode(aux.toLatin1()); + if (isIdnEnabled) { + QString tmp = QUrl::fromPunycode(aceForm.toLatin1()); if (tmp.isEmpty()) - return QString(); - result += tmp; + return QString(); // shouldn't happen, since we've just punycode-encoded it + result.resize(prevLen + tmp.size()); + memcpy(result.data() + prevLen, tmp.constData(), tmp.size() * sizeof(QChar)); } else { - int prevLen = result.size(); - toPunycodeHelper(tmp.constData(), tmp.size(), &result); - - label = QStringRef(&result, prevLen, result.length() - prevLen); + result.resize(prevLen + aceForm.size()); + memcpy(result.data() + prevLen, aceForm.constData(), aceForm.size() * sizeof(QChar)); } + + if (!qt_check_std3rules(aceForm.constData(), aceForm.size())) + return QString(); } - if (!qt_check_std3rules(label)) - return QString(); lastIdx = idx + 1; if (lastIdx < domain.size() + 1) |