diff options
author | Prasanth Ullattil <prasanth.ullattil@nokia.com> | 2010-09-15 15:10:21 (GMT) |
---|---|---|
committer | Prasanth Ullattil <prasanth.ullattil@nokia.com> | 2010-09-15 16:56:43 (GMT) |
commit | 6bc165d0fbbc4704d87e59cc0795dc2769228dc3 (patch) | |
tree | 39e63f6e92eb3c11afc8fd3ac1a8408b5121abab | |
parent | fd4463c07f577d9df212388062028f9119e19add (diff) | |
download | Qt-6bc165d0fbbc4704d87e59cc0795dc2769228dc3.zip Qt-6bc165d0fbbc4704d87e59cc0795dc2769228dc3.tar.gz Qt-6bc165d0fbbc4704d87e59cc0795dc2769228dc3.tar.bz2 |
Implement QFileSystemIterator for windows.
The search is implemented using FindFirstFileEx(). Following
optimizations are done
* Using large Fetch buffer on Windows 7
* Querying only the long file name
* Querying for directories only, depending on QDir::Filters
Reviewed-by: Joao
-rw-r--r-- | qmake/Makefile.win32 | 5 | ||||
-rw-r--r-- | qmake/Makefile.win32-g++ | 4 | ||||
-rw-r--r-- | qmake/Makefile.win32-g++-sh | 4 | ||||
-rw-r--r-- | qmake/qmake.pri | 2 | ||||
-rw-r--r-- | src/corelib/io/io.pri | 1 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemiterator_p.h | 6 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemiterator_win.cpp | 84 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_iterator.cpp | 20 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_iterator_p.h | 10 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_iterator_win.cpp | 162 | ||||
-rw-r--r-- | src/tools/bootstrap/bootstrap.pro | 1 | ||||
-rw-r--r-- | tools/configure/configure.pro | 1 | ||||
-rw-r--r-- | tools/qtestlib/wince/cetest/bootstrapped.pri | 1 |
13 files changed, 87 insertions, 214 deletions
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index fa17b9d..906d284 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -104,7 +104,6 @@ QTOBJS= \ qtemporaryfile.obj \ qabstractfileengine.obj \ qfsfileengine_win.obj \ - qfsfileengine_iterator_win.obj \ qfileinfo.obj \ qglobal.obj \ qhash.obj \ @@ -161,7 +160,6 @@ clean:: -del qtemporaryfile.obj -del qabstractfileengine.obj -del qfsfileengine_win.obj - -del qfsfileengine_iterator_win.obj -del qfileinfo.obj -del qglobal.obj -del qhash.obj @@ -333,9 +331,6 @@ qfilesystemiterator_win.obj: $(SOURCE_PATH)\src\corelib\io\qfilesystemiterator_w qfsfileengine_win.obj: $(SOURCE_PATH)\src\corelib\io\qfsfileengine_win.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfsfileengine_win.cpp -qfsfileengine_iterator_win.obj: $(SOURCE_PATH)\src\corelib\io\qfsfileengine_iterator_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfsfileengine_iterator_win.cpp - qfsfileengine.obj: $(SOURCE_PATH)\src\corelib\io\qfsfileengine.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfsfileengine.cpp diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++ index 57ea3d5..2bab255 100644 --- a/qmake/Makefile.win32-g++ +++ b/qmake/Makefile.win32-g++ @@ -68,7 +68,6 @@ QTOBJS= \ qfsfileengine.o \ qfsfileengine_iterator.o \ qfsfileengine_win.o \ - qfsfileengine_iterator_win.o \ qglobal.o \ qhash.o \ qiodevice.o \ @@ -211,9 +210,6 @@ qfilesystemiterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win qfsfileengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp -qfsfileengine_iterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_win.cpp - qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp diff --git a/qmake/Makefile.win32-g++-sh b/qmake/Makefile.win32-g++-sh index 33deb01..db78933 100644 --- a/qmake/Makefile.win32-g++-sh +++ b/qmake/Makefile.win32-g++-sh @@ -67,7 +67,6 @@ QTOBJS= \ qfsfileengine.o \ qfsfileengine_iterator.o \ qfsfileengine_win.o \ - qfsfileengine_iterator_win.o \ qglobal.o \ qhash.o \ qiodevice.o \ @@ -206,9 +205,6 @@ qfilesystemiterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win qfsfileengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp -qfsfileengine_iterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_win.cpp - qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp diff --git a/qmake/qmake.pri b/qmake/qmake.pri index cd81c82..1d35183 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -135,7 +135,7 @@ bootstrap { #Qt code LIBS += -framework ApplicationServices } } else:win32 { - SOURCES += qfilesystemengine_win.cpp qfsfileengine_win.cpp qfilesystemiterator_win.cpp qfsfileengine_iterator_win.cpp qsettings_win.cpp + SOURCES += qfilesystemengine_win.cpp qfsfileengine_win.cpp qfilesystemiterator_win.cpp qsettings_win.cpp win32-msvc*:LIBS += ole32.lib advapi32.lib win32-g++*:LIBS += -lole32 -luuid } diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 4a2f042..9d209ea 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -65,7 +65,6 @@ win32 { SOURCES += io/qprocess_win.cpp SOURCES += io/qfsfileengine_win.cpp - SOURCES += io/qfsfileengine_iterator_win.cpp SOURCES += io/qfilesystemwatcher_win.cpp HEADERS += io/qfilesystemwatcher_win_p.h HEADERS += io/qwindowspipewriter_p.h diff --git a/src/corelib/io/qfilesystemiterator_p.h b/src/corelib/io/qfilesystemiterator_p.h index d3b195d..66f4b1e 100644 --- a/src/corelib/io/qfilesystemiterator_p.h +++ b/src/corelib/io/qfilesystemiterator_p.h @@ -86,6 +86,12 @@ private: // Platform-specific data #if defined(Q_OS_WIN) + QFileSystemEntry::NativePath dirPath; + HANDLE findFileHandle; + QStringList uncShares; + bool uncFallback; + int uncShareIndex; + bool onlyDirs; #elif defined (Q_OS_SYMBIAN) RDir dirHandle; TEntryArray entries; diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp index 3c73496..373a50a 100644 --- a/src/corelib/io/qfilesystemiterator_win.cpp +++ b/src/corelib/io/qfilesystemiterator_win.cpp @@ -40,26 +40,102 @@ ****************************************************************************/ #include "qfilesystemiterator_p.h" +#include "qfilesystemengine_p.h" +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE +bool done = true; + QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters, const QStringList &nameFilters, QDirIterator::IteratorFlags flags) + : nativePath(entry.nativeFilePath()) + , dirPath(entry.filePath()) + , findFileHandle(INVALID_HANDLE_VALUE) + , uncFallback(false) + , uncShareIndex(0) + , onlyDirs(false) { - Q_UNUSED(entry) - Q_UNUSED(filters) Q_UNUSED(nameFilters) Q_UNUSED(flags) + if (nativePath.endsWith(QLatin1String(".lnk"))) { + QFileSystemMetaData metaData; + QFileSystemEntry link = QFileSystemEngine::getLinkTarget(entry, metaData); + nativePath = link.nativeFilePath(); + } + if (!nativePath.endsWith(QLatin1Char('\\'))) + nativePath.append(QLatin1Char('\\')); + nativePath.append(QLatin1Char('*')); + if (!dirPath.endsWith(QLatin1Char('//'))) + dirPath.append(QLatin1Char('//')); + if ((filters & (QDir::Dirs|QDir::Drives)) && (!(filters & (QDir::Files)))) + onlyDirs = true; } QFileSystemIterator::~QFileSystemIterator() { + if (findFileHandle != INVALID_HANDLE_VALUE) + FindClose(findFileHandle); } bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData) { - Q_UNUSED(fileEntry) - Q_UNUSED(metaData) + bool haveData = false; + WIN32_FIND_DATA findData; + + if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback) { + haveData = true; + DWORD dwAdditionalFlags = 0; + if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) + dwAdditionalFlags = 2; // FIND_FIRST_EX_LARGE_FETCH + int searchOps = 0; // FindExSearchNameMatch + if (onlyDirs) + searchOps = 1 ; // FindExSearchLimitToDirectories +#if !defined(Q_OS_WINCE) + int infoLevel = 1 ; // FindExInfoBasic; +#else + int infoLevel = 0; // FindExInfoStandard; +#endif + findFileHandle = FindFirstFileEx((const wchar_t *)nativePath.utf16(), FINDEX_INFO_LEVELS(infoLevel), &findData, + FINDEX_SEARCH_OPS(searchOps), 0, dwAdditionalFlags); + if (findFileHandle == INVALID_HANDLE_VALUE) { + if (nativePath.startsWith(QLatin1String("\\\\?\\UNC\\"))) { + QStringList parts = nativePath.split(QLatin1Char('\\'), QString::SkipEmptyParts); + if (parts.count() == 4 && QFileSystemEngine::uncListSharesOnServer( + QLatin1String("\\\\") + parts.at(2), &uncShares)) { + if (uncShares.isEmpty()) + return false; // No shares found in the server + else + uncFallback = true; + } + } + } + } + if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback) + return false; + // Retrieve the new file information. + if (!haveData) { + if (uncFallback) { + if (++uncShareIndex >= uncShares.count()) + return false; + } else { + if (!FindNextFile(findFileHandle, &findData)) + return false; + } + } + // Create the new file system entry & meta data. + if (uncFallback) { + fileEntry = QFileSystemEntry(dirPath + uncShares.at(uncShareIndex)); + metaData.fillFromFileAttribute(FILE_ATTRIBUTE_DIRECTORY); + return true; + } else { + QString fileName = QString::fromWCharArray(findData.cFileName); + fileEntry = QFileSystemEntry(dirPath + fileName); + if (!fileName.endsWith(QLatin1String(".lnk"))) { + metaData.fillFromFindData(findData, true); + } + return true; + } return false; } diff --git a/src/corelib/io/qfsfileengine_iterator.cpp b/src/corelib/io/qfsfileengine_iterator.cpp index 4617f49..f6f08c7 100644 --- a/src/corelib/io/qfsfileengine_iterator.cpp +++ b/src/corelib/io/qfsfileengine_iterator.cpp @@ -49,23 +49,14 @@ QT_BEGIN_NAMESPACE QFSFileEngineIterator::QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames) : QAbstractFileEngineIterator(filters, filterNames) -#ifdef Q_OS_UNIX , done(false) -#endif { -#ifndef Q_OS_UNIX - newPlatformSpecifics(); -#endif } QFSFileEngineIterator::~QFSFileEngineIterator() { -#ifndef Q_OS_UNIX - deletePlatformSpecifics(); -#endif } -#ifdef Q_OS_UNIX bool QFSFileEngineIterator::hasNext() const { if (!done && !nativeIterator) { @@ -76,7 +67,6 @@ bool QFSFileEngineIterator::hasNext() const return !done; } -#endif QString QFSFileEngineIterator::next() { @@ -87,7 +77,6 @@ QString QFSFileEngineIterator::next() return currentFilePath(); } -#ifdef Q_OS_UNIX void QFSFileEngineIterator::advance() const { currentInfo = nextInfo; @@ -101,24 +90,15 @@ void QFSFileEngineIterator::advance() const nativeIterator.reset(); } } -#endif QString QFSFileEngineIterator::currentFileName() const { -#ifdef Q_OS_UNIX return currentInfo.fileName(); -#else - return currentEntry; -#endif } QFileInfo QFSFileEngineIterator::currentFileInfo() const { -#ifdef Q_OS_UNIX return currentInfo; -#else - return QAbstractFileEngineIterator::currentFileInfo(); -#endif } QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_iterator_p.h b/src/corelib/io/qfsfileengine_iterator_p.h index 7940fbd..ac9598d 100644 --- a/src/corelib/io/qfsfileengine_iterator_p.h +++ b/src/corelib/io/qfsfileengine_iterator_p.h @@ -77,21 +77,11 @@ public: QFileInfo currentFileInfo() const; private: -#ifdef Q_OS_UNIX void advance() const; mutable QScopedPointer<QFileSystemIterator> nativeIterator; mutable QFileInfo currentInfo; mutable QFileInfo nextInfo; mutable bool done; -#else - QFSFileEngineIteratorPlatformSpecificData *platform; - friend class QFSFileEngineIteratorPlatformSpecificData; - void newPlatformSpecifics(); - void deletePlatformSpecifics(); - void advance(); - - QString currentEntry; -#endif }; QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_iterator_win.cpp b/src/corelib/io/qfsfileengine_iterator_win.cpp deleted file mode 100644 index d4e6f5a..0000000 --- a/src/corelib/io/qfsfileengine_iterator_win.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfsfileengine_iterator_p.h" -#include "qfsfileengine_p.h" -#include "qfilesystemengine_p.h" -#include "qplatformdefs.h" - -#include <QtCore/qvariant.h> - -QT_BEGIN_NAMESPACE - -class QFSFileEngineIteratorPlatformSpecificData -{ -public: - inline QFSFileEngineIteratorPlatformSpecificData() - : uncShareIndex(-1), findFileHandle(INVALID_HANDLE_VALUE), - done(false), uncFallback(false) - {} - - QFSFileEngineIterator *it; - - QStringList uncShares; - int uncShareIndex; - - HANDLE findFileHandle; - WIN32_FIND_DATA findData; - bool done; - bool uncFallback; - - void saveCurrentFileName(); -}; - -void QFSFileEngineIteratorPlatformSpecificData::saveCurrentFileName() -{ - if (uncFallback) { - // Windows share / UNC path - it->currentEntry = uncShares.at(uncShareIndex - 1); - } else { - // Local directory - it->currentEntry = QString::fromWCharArray(findData.cFileName); - } -} - -void QFSFileEngineIterator::advance() -{ - platform->saveCurrentFileName(); - - if (platform->done) - return; - - if (platform->uncFallback) { - ++platform->uncShareIndex; - } else if (platform->findFileHandle != INVALID_HANDLE_VALUE) { - if (!FindNextFile(platform->findFileHandle, &platform->findData)) { - platform->done = true; - FindClose(platform->findFileHandle); - } - } -} - -void QFSFileEngineIterator::newPlatformSpecifics() -{ - platform = new QFSFileEngineIteratorPlatformSpecificData; - platform->it = this; -} - -void QFSFileEngineIterator::deletePlatformSpecifics() -{ - delete platform; - platform = 0; -} - -bool QFSFileEngineIterator::hasNext() const -{ - if (platform->done) - return false; - - if (platform->uncFallback) - return platform->uncShareIndex > 0 && platform->uncShareIndex <= platform->uncShares.size(); - - if (platform->findFileHandle == INVALID_HANDLE_VALUE) { - QString path = this->path(); - // Local directory - if (path.endsWith(QLatin1String(".lnk"))) - path = QFileInfo(path).readLink(); - - if (!path.endsWith(QLatin1Char('/'))) - path.append(QLatin1Char('/')); - path.append(QLatin1String("*.*")); - - QString fileName = QFSFileEnginePrivate::longFileName(path); - platform->findFileHandle = FindFirstFile((const wchar_t *)fileName.utf16(), &platform->findData); - - if (platform->findFileHandle == INVALID_HANDLE_VALUE) { - if (path.startsWith(QLatin1String("//"))) { - path = this->path(); - // UNC - QStringList parts = QDir::toNativeSeparators(path).split(QLatin1Char('\\'), QString::SkipEmptyParts); - - if (parts.count() == 1 && QFileSystemEngine::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(0), - &platform->uncShares)) { - if (platform->uncShares.isEmpty()) { - platform->done = true; - } else { - platform->uncShareIndex = 1; - } - platform->uncFallback = true; - } else { - platform->done = true; - } - } else { - platform->done = true; - } - } - - if (!platform->done && (!platform->uncFallback || !platform->uncShares.isEmpty())) - platform->saveCurrentFileName(); - } - - return !platform->done; -} - -QT_END_NAMESPACE diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 81b785a..179cb0b 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -92,7 +92,6 @@ unix:SOURCES += ../../corelib/io/qfilesystemengine_unix.cpp \ win32:SOURCES += ../../corelib/io/qfilesystemengine_win.cpp \ ../../corelib/io/qfilesystemiterator_win.cpp \ ../../corelib/io/qfsfileengine_win.cpp \ - ../../corelib/io/qfsfileengine_iterator_win.cpp macx: { QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 #enables weak linking for 10.4 (exported) diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro index fe1b028..6450038 100644 --- a/tools/configure/configure.pro +++ b/tools/configure/configure.pro @@ -97,7 +97,6 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \ diff --git a/tools/qtestlib/wince/cetest/bootstrapped.pri b/tools/qtestlib/wince/cetest/bootstrapped.pri index 76245b0..56c8ab7 100644 --- a/tools/qtestlib/wince/cetest/bootstrapped.pri +++ b/tools/qtestlib/wince/cetest/bootstrapped.pri @@ -12,7 +12,6 @@ SOURCES += \ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.cpp \ |