diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2014-01-15 14:45:44 -0800 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-10 16:20:49 +0100 |
commit | fbc554b42c6a1d0c06d39a54b991513d7ce2db12 (patch) | |
tree | 48b2450730650c2eac216849b9b5f7c4aba49c6b /src/corelib/io | |
parent | 7f0d6c4529a7446e64d579514c3ab793517a457a (diff) |
Make QUrl::isLocalFile fast by storing a flag
The XDG specification for file URIs requires us to use triple slashes in
file:/// for URLs with absolute paths. I don't like special-casing any
particular scheme, but we've done it for file for many years now.
Since we need to test this situation in a couple of places, it's easier
to just cache the result once, in setScheme (both functions).
Change-Id: I078b45b5b6c861f4caee082b4730fd6f67684ae4
Reviewed-by: David Faure <david.faure@kdab.com>
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qurl.cpp | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index eac5a0b738..f17215964f 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -414,10 +414,16 @@ static inline QString fileScheme() return QStringLiteral("file"); } +#ifdef Q_COMPILER_CLASS_ENUM +# define colon_uchar : uchar +#else +# define colon_uchar +#endif + class QUrlPrivate { public: - enum Section { + enum Section colon_uchar { Scheme = 0x01, UserName = 0x02, Password = 0x04, @@ -432,6 +438,10 @@ public: FullUrl = 0xff }; + enum Flags colon_uchar { + IsLocalFile = 0x01 + }; + enum ErrorCode { // the high byte of the error code matches the Section // the first item in each value must be the generic "Invalid xxx Error" @@ -519,6 +529,8 @@ public: inline bool hasQuery() const { return sectionIsPresent & Query; } inline bool hasFragment() const { return sectionIsPresent & Fragment; } + inline bool isLocalFile() const { return flags & IsLocalFile; } + QString mergePaths(const QString &relativePath) const; QAtomicInt ref; @@ -539,12 +551,18 @@ public: // - Path (there's no path delimiter, so we optimize its use out of existence) // Schemes are never supposed to be empty, but we keep the flag anyway uchar sectionIsPresent; + uchar flags; + + // 32-bit: 2 bytes tail padding available + // 64-bit: 6 bytes tail padding available }; +#undef colon_uchar inline QUrlPrivate::QUrlPrivate() : ref(1), port(-1), error(0), - sectionIsPresent(0) + sectionIsPresent(0), + flags(0) { } @@ -558,7 +576,8 @@ inline QUrlPrivate::QUrlPrivate(const QUrlPrivate ©) query(copy.query), fragment(copy.fragment), error(copy.cloneError()), - sectionIsPresent(copy.sectionIsPresent) + sectionIsPresent(copy.sectionIsPresent), + flags(copy.flags) { } @@ -956,6 +975,12 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro schemeData[i] = c + 0x20; } } + + // did we set to the file protocol? + if (scheme == fileScheme()) + flags |= IsLocalFile; + else + flags &= ~IsLocalFile; return true; } @@ -1312,6 +1337,7 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode // / other path types here sectionIsPresent = 0; + flags = 0; clearError(); // find the important delimiters @@ -1867,6 +1893,7 @@ void QUrl::setScheme(const QString &scheme) if (scheme.isEmpty()) { // schemes are not allowed to be empty d->sectionIsPresent &= ~QUrlPrivate::Scheme; + d->flags &= ~QUrlPrivate::IsLocalFile; d->scheme.clear(); } else { d->setScheme(scheme, scheme.length(), /* do set error */ true); @@ -3104,6 +3131,7 @@ QUrl QUrl::resolved(const QUrl &relative) const t.d->sectionIsPresent |= QUrlPrivate::Scheme; else t.d->sectionIsPresent &= ~QUrlPrivate::Scheme; + t.d->flags |= d->flags & QUrlPrivate::IsLocalFile; } t.d->fragment = relative.d->fragment; if (relative.d->hasFragment()) @@ -3177,7 +3205,6 @@ QString QUrl::toString(FormattingOptions options) const // - there's no query or fragment to return // that is, either they aren't present, or we're removing them // - it's a local file - // (test done last since it's the most expensive) if (options.testFlag(QUrl::PreferLocalFile) && !options.testFlag(QUrl::RemovePath) && (!d->hasQuery() || options.testFlag(QUrl::RemoveQuery)) && (!d->hasFragment() || options.testFlag(QUrl::RemoveFragment)) @@ -3201,6 +3228,7 @@ QString QUrl::toString(FormattingOptions options) const url += QLatin1String("//"); d->appendAuthority(url, options, QUrlPrivate::FullUrl); } else if (isLocalFile() && pathIsAbsolute) { + // Comply with the XDG file URI spec, which requires triple slashes. url += QLatin1String("//"); } @@ -3755,11 +3783,7 @@ QString QUrl::toLocalFile() const */ bool QUrl::isLocalFile() const { - if (!d) return false; - - if (d->scheme != fileScheme()) - return false; // not file - return true; + return d && d->isLocalFile(); } /*! |