diff options
author | João Abecasis <joao.abecasis@nokia.com> | 2010-09-03 17:33:52 (GMT) |
---|---|---|
committer | João Abecasis <joao.abecasis@nokia.com> | 2010-09-03 18:39:57 (GMT) |
commit | 367514db5f041de7cd5d36fa0a260dcadcc54a50 (patch) | |
tree | e268371539d039d0be8be0b42e900284b69826a2 /src | |
parent | a59924437dadf4ea3b972a528f449ebb2b760d81 (diff) | |
download | Qt-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.cpp | 54 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine.cpp | 87 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine_p.h | 2 |
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); }; |