summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2014-01-15 14:45:44 -0800
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-10 16:20:49 +0100
commitfbc554b42c6a1d0c06d39a54b991513d7ce2db12 (patch)
tree48b2450730650c2eac216849b9b5f7c4aba49c6b /src/corelib/io
parent7f0d6c4529a7446e64d579514c3ab793517a457a (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.cpp42
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 &copy)
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();
}
/*!