summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoão Abecasis <joao.abecasis@nokia.com>2010-09-03 17:33:52 (GMT)
committerJoão Abecasis <joao.abecasis@nokia.com>2010-09-03 18:39:57 (GMT)
commit367514db5f041de7cd5d36fa0a260dcadcc54a50 (patch)
treee268371539d039d0be8be0b42e900284b69826a2 /src
parenta59924437dadf4ea3b972a528f449ebb2b760d81 (diff)
downloadQt-367514db5f041de7cd5d36fa0a260dcadcc54a50.zip
Qt-367514db5f041de7cd5d36fa0a260dcadcc54a50.tar.gz
Qt-367514db5f041de7cd5d36fa0a260dcadcc54a50.tar.bz2
Split QAbstractFileEngine::create
The new, ugly-named resolveEntryAndCreateLegacyEngine will never instantiate QFSFileEngine and uses the QFileSystemEngine API to check if files exist, when necessary. This way, we reduce allocations of QFSFileEngine when resolving paths. Clients of the QAbstractFileEngine API will be able to opt-out of using QFSFileEngine altogether. Reviewed-by: Thomas Zander
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qabstractfileengine.cpp54
-rw-r--r--src/corelib/io/qfilesystemengine.cpp87
-rw-r--r--src/corelib/io/qfilesystemengine_p.h2
3 files changed, 102 insertions, 41 deletions
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index e055e7b..67109aa 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -52,6 +52,10 @@
#include "qdiriterator.h"
#include "qstringbuilder.h"
+#include <QtCore/private/qfilesystementry_p.h>
+#include <QtCore/private/qfilesystemmetadata_p.h>
+#include <QtCore/private/qfilesystemengine_p.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -200,49 +204,17 @@ QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path)
*/
QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
{
- if (QAbstractFileEngine *engine = qt_custom_file_engine_handler_create(filePath))
- return engine;
-
-#ifdef QT_BUILD_CORE_LIB
- for (int prefixSeparator = 0; prefixSeparator < fileName.size(); ++prefixSeparator) {
- QChar const ch = fileName[prefixSeparator];
- if (ch == QLatin1Char('/'))
- break;
-
- if (ch == QLatin1Char(':')) {
- if (prefixSeparator == 0)
- return new QResourceFileEngine(fileName);
-
- if (prefixSeparator == 1)
- break;
-
- const QStringList &paths = QDir::searchPaths(fileName.left(prefixSeparator));
- for (int i = 0; i < paths.count(); i++) {
- QAbstractFileEngine *engine = create(paths.at(i) % QLatin1Char('/') % fileName.mid(prefixSeparator + 1));
- if (engine && (engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) {
- return engine;
- }
- delete engine;
- }
-
- break;
- }
-
- // There's no need to fully validate the prefix here. Consulting the
- // unicode tables could be expensive and validation is already
- // performed in QDir::setSearchPaths.
- //
- // if (!ch.isLetterOrNumber())
- // break;
- }
+ QFileSystemEntry entry(fileName);
+ QFileSystemMetaData metaData;
+ QAbstractFileEngine *engine = QFileSystemEngine::resolveEntryAndCreateLegacyEngine(entry, metaData);
+
+#ifndef QT_NO_FSFILEENGINE
+ if (!engine)
+ // fall back to regular file engine
+ return new QFSFileEngine(entry.filePath());
#endif
-#ifdef QT_NO_FSFILEENGINE
- return 0;
-#else
- // fall back to regular file engine
- return new QFSFileEngine(fileName);
-#endif
+ return engine;
}
/*!
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
index 04e53ce..a6c226e 100644
--- a/src/corelib/io/qfilesystemengine.cpp
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -42,6 +42,12 @@
#include "qfilesystemengine_p.h"
#include <QtCore/qdir.h>
#include <QtCore/qset.h>
+#include <QtCore/private/qabstractfileengine_p.h>
+#ifdef QT_BUILD_CORE_LIB
+#include <QtCore/private/qresource_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
/*!
\internal
@@ -111,3 +117,84 @@ QString QFileSystemEngine::slowCanonicalized(const QString &path)
return QDir::cleanPath(tmpPath);
}
+static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &entry, QFileSystemMetaData &data,
+ QAbstractFileEngine *&engine)
+{
+ QString const &filePath = entry.filePath();
+ if ((engine = qt_custom_file_engine_handler_create(filePath)))
+ return true;
+
+#if defined(QT_BUILD_CORE_LIB)
+ for (int prefixSeparator = 0; prefixSeparator < filePath.size(); ++prefixSeparator) {
+ QChar const ch = filePath[prefixSeparator];
+ if (ch == QLatin1Char('/'))
+ break;
+
+ if (ch == QLatin1Char(':')) {
+ if (prefixSeparator == 0) {
+ engine = new QResourceFileEngine(filePath);
+ return true;
+ }
+
+ if (prefixSeparator == 1)
+ break;
+
+ const QStringList &paths = QDir::searchPaths(filePath.left(prefixSeparator));
+ for (int i = 0; i < paths.count(); i++) {
+ entry = QFileSystemEntry(paths.at(i) % QLatin1Char('/') % filePath.mid(prefixSeparator + 1));
+ // Recurse!
+ if (_q_resolveEntryAndCreateLegacyEngine_recursive(entry, data, engine)) {
+ // FIXME: This will over-stat if we recurse
+ if (engine) {
+ if (engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)
+ return true;
+ delete engine;
+ engine = 0;
+ } else if (QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute)
+ && data.exists()) {
+ return true;
+ }
+ }
+ }
+
+ // entry may have been clobbered at this point.
+ return false;
+ }
+
+ // There's no need to fully validate the prefix here. Consulting the
+ // unicode tables could be expensive and validation is already
+ // performed in QDir::setSearchPaths.
+ //
+ // if (!ch.isLetterOrNumber())
+ // break;
+ }
+#endif // defined(QT_BUILD_CORE_LIB)
+
+ return true;
+}
+
+/*!
+ \internal
+
+ Resolves the \a entry (see QDir::searchPaths) and returns an engine for
+ it, but never a QFSFileEngine.
+
+ \returns a file engine that can be used to access the entry. Returns 0 if
+ QFileSystemEngine API should be used to query and interact with the file
+ system object.
+*/
+QAbstractFileEngine *QFileSystemEngine::resolveEntryAndCreateLegacyEngine(
+ QFileSystemEntry &entry, QFileSystemMetaData &data) {
+ QFileSystemEntry copy = entry;
+ QAbstractFileEngine *engine = 0;
+
+ if (_q_resolveEntryAndCreateLegacyEngine_recursive(copy, data, engine))
+ // Reset entry to resolved copy.
+ entry = copy;
+ else
+ data.clear();
+
+ return engine;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h
index 182ccd6..990a5ff 100644
--- a/src/corelib/io/qfilesystemengine_p.h
+++ b/src/corelib/io/qfilesystemengine_p.h
@@ -88,6 +88,8 @@ public:
static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions,
QFileSystemMetaData *data = 0);
+ static QAbstractFileEngine *resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry,
+ QFileSystemMetaData &data);
private:
static QString slowCanonicalized(const QString &path);
};