summaryrefslogtreecommitdiffstats
path: root/tests/benchmarks/qdiriterator
diff options
context:
space:
mode:
authoraxis <qt-info@nokia.com>2009-04-24 11:34:15 (GMT)
committeraxis <qt-info@nokia.com>2009-04-24 11:34:15 (GMT)
commit8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch)
treea17e1a767a89542ab59907462206d7dcf2e504b2 /tests/benchmarks/qdiriterator
downloadQt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.zip
Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz
Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.bz2
Long live Qt for S60!
Diffstat (limited to 'tests/benchmarks/qdiriterator')
-rwxr-xr-xtests/benchmarks/qdiriterator/main.cpp251
-rwxr-xr-xtests/benchmarks/qdiriterator/qdiriterator.pro23
-rw-r--r--tests/benchmarks/qdiriterator/qfilesystemiterator.cpp689
-rw-r--r--tests/benchmarks/qdiriterator/qfilesystemiterator.h99
4 files changed, 1062 insertions, 0 deletions
diff --git a/tests/benchmarks/qdiriterator/main.cpp b/tests/benchmarks/qdiriterator/main.cpp
new file mode 100755
index 0000000..6d1c203
--- /dev/null
+++ b/tests/benchmarks/qdiriterator/main.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QDebug>
+#include <QDirIterator>
+#include <QString>
+
+#ifdef Q_OS_WIN
+# include <windows.h>
+# include <atlbase.h>
+#else
+# include <sys/stat.h>
+# include <sys/types.h>
+# include <dirent.h>
+# include <errno.h>
+# include <string.h>
+#endif
+
+#include <qtest.h>
+
+#include "qfilesystemiterator.h"
+
+class tst_qdiriterator : public QObject
+{
+ Q_OBJECT
+private slots:
+ void posix();
+ void posix_data() { data(); }
+ void diriterator();
+ void diriterator_data() { data(); }
+ void fsiterator();
+ void fsiterator_data() { data(); }
+ void data();
+};
+
+
+void tst_qdiriterator::data()
+{
+#ifdef Q_OS_WINCE
+ QByteArray qtdir = qPrintable(QCoreApplication::applicationDirPath());
+ qtdir += "/depot";
+#else
+#if defined(Q_OS_WIN)
+ const char *qtdir = "C:\\depot\\qt\\main";
+#else
+ const char *qtdir = ::getenv("QTDIR");
+#endif
+ if (!qtdir) {
+ fprintf(stderr, "QTDIR not set\n");
+ exit(1);
+ }
+#endif
+
+ QTest::addColumn<QByteArray>("dirpath");
+ QByteArray ba = QByteArray(qtdir) + "/src/corelib";
+ QByteArray ba1 = ba + "/io";
+ QTest::newRow(ba) << ba;
+ //QTest::newRow(ba1) << ba1;
+}
+
+#ifdef Q_OS_WIN
+static int posix_helper(const wchar_t *dirpath)
+{
+ int count = 0;
+ HANDLE hSearch;
+ WIN32_FIND_DATA fd;
+
+ const size_t origDirPathLength = wcslen(dirpath);
+
+ wchar_t appendedPath[MAX_PATH];
+ wcscpy(appendedPath, dirpath);
+ wcscat(appendedPath, L"\\*");
+ hSearch = FindFirstFileW(appendedPath, &fd);
+ appendedPath[origDirPathLength] = 0;
+
+ if (hSearch == INVALID_HANDLE_VALUE) {
+ qWarning("FindFirstFile failed");
+ return count;
+ }
+
+ do {
+ if (!(fd.cFileName[0] == L'.' && fd.cFileName[1] == 0) &&
+ !(fd.cFileName[0] == L'.' && fd.cFileName[1] == L'.' && fd.cFileName[2] == 0))
+ {
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ wcscat(appendedPath, L"\\");
+ wcscat(appendedPath, fd.cFileName);
+ count += posix_helper(appendedPath);
+ appendedPath[origDirPathLength] = 0;
+ }
+ else {
+ ++count;
+ }
+ }
+ } while (FindNextFile(hSearch, &fd));
+ FindClose(hSearch);
+
+ return count;
+}
+
+#else
+
+static int posix_helper(const char *dirpath)
+{
+ //qDebug() << "DIR" << dirpath;
+ DIR *dir = ::opendir(dirpath);
+ if (!dir)
+ return 0;
+
+ dirent *entry = 0;
+
+ int count = 0;
+ while ((entry = ::readdir(dir))) {
+ if (qstrcmp(entry->d_name, ".") == 0)
+ continue;
+ if (qstrcmp(entry->d_name, "..") == 0)
+ continue;
+ ++count;
+ QByteArray ba = dirpath;
+ ba += '/';
+ ba += entry->d_name;
+ struct stat st;
+ lstat(ba.constData(), &st);
+ if (S_ISDIR(st.st_mode))
+ count += posix_helper(ba.constData());
+ }
+
+ ::closedir(dir);
+ return count;
+}
+#endif
+
+
+void tst_qdiriterator::posix()
+{
+ QFETCH(QByteArray, dirpath);
+
+ int count = 0;
+ QString path(dirpath);
+ QBENCHMARK {
+#ifdef Q_OS_WIN
+ count = posix_helper(path.utf16());
+#else
+ count = posix_helper(dirpath.constData());
+#endif
+ }
+ qDebug() << count;
+}
+
+void tst_qdiriterator::diriterator()
+{
+ QFETCH(QByteArray, dirpath);
+
+ int count = 0;
+
+ QBENCHMARK {
+ int c = 0;
+
+ QDirIterator dir(dirpath,
+ //QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot,
+ //QDir::AllEntries | QDir::Hidden,
+ QDir::Files,
+ QDirIterator::Subdirectories);
+
+ while (dir.hasNext()) {
+ dir.next();
+ //printf("%s\n", qPrintable(dir.fileName()));
+ 0 && printf("%d %s\n",
+ dir.fileInfo().isDir(),
+ //qPrintable(dir.fileInfo().absoluteFilePath()),
+ //qPrintable(dir.path()),
+ qPrintable(dir.filePath()));
+ ++c;
+ }
+ count = c;
+ }
+ qDebug() << count;
+}
+
+void tst_qdiriterator::fsiterator()
+{
+ QFETCH(QByteArray, dirpath);
+
+ int count = 0;
+ int dump = 0;
+
+ QBENCHMARK {
+ int c = 0;
+
+ dump && printf("\n\n\n\n");
+ QFileSystemIterator dir(dirpath,
+ //QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot,
+ //QDir::AllEntries | QDir::Hidden,
+ //QDir::Files | QDir::NoDotAndDotDot,
+ QDir::Files,
+ QFileSystemIterator::Subdirectories);
+
+ for (; !dir.atEnd(); dir.next()) {
+ dump && printf("%d %s\n",
+ dir.fileInfo().isDir(),
+ //qPrintable(dir.fileInfo().absoluteFilePath()),
+ //qPrintable(dir.path()),
+ qPrintable(dir.filePath())
+ );
+ ++c;
+ }
+ count = c;
+ }
+ qDebug() << count;
+}
+
+QTEST_MAIN(tst_qdiriterator)
+
+#include "main.moc"
diff --git a/tests/benchmarks/qdiriterator/qdiriterator.pro b/tests/benchmarks/qdiriterator/qdiriterator.pro
new file mode 100755
index 0000000..fb4b753
--- /dev/null
+++ b/tests/benchmarks/qdiriterator/qdiriterator.pro
@@ -0,0 +1,23 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_qdiriterator
+DEPENDPATH += .
+INCLUDEPATH += .
+
+QT -= gui
+
+CONFIG += release
+CONFIG += debug
+
+
+SOURCES += main.cpp
+
+SOURCES += qfilesystemiterator.cpp
+HEADERS += qfilesystemiterator.h
+
+wince*: {
+ corelibdir.sources = $$QT_SOURCE_TREE/src/corelib
+ corelibdir.path = ./depot/src
+ DEPLOYMENT += corelibdir
+}
+
diff --git a/tests/benchmarks/qdiriterator/qfilesystemiterator.cpp b/tests/benchmarks/qdiriterator/qfilesystemiterator.cpp
new file mode 100644
index 0000000..144794f
--- /dev/null
+++ b/tests/benchmarks/qdiriterator/qfilesystemiterator.cpp
@@ -0,0 +1,689 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \since 4.5
+ \class QFileSystemIterator
+ \brief The QFileSystemIterator class provides an iterator for directory entrylists.
+
+ You can use QFileSystemIterator to navigate entries of a directory one at a time.
+ It is similar to QDir::entryList() and QDir::entryInfoList(), but because
+ it lists entries one at a time instead of all at once, it scales better
+ and is more suitable for large directories. It also supports listing
+ directory contents recursively, and following symbolic links. Unlike
+ QDir::entryList(), QFileSystemIterator does not support sorting.
+
+ The QFileSystemIterator constructor takes a QDir or a directory as
+ argument. After construction, the iterator is located before the first
+ directory entry. Here's how to iterate over all the entries sequentially:
+
+ \snippet doc/src/snippets/code/src.corelib.io.qdiriterator.cpp 0
+
+ The next() function returns the path to the next directory entry and
+ advances the iterator. You can also call filePath() to get the current
+ file path without advancing the iterator. The fileName() function returns
+ only the name of the file, similar to how QDir::entryList() works. You can
+ also call fileInfo() to get a QFileInfo for the current entry.
+
+ Unlike Qt's container iterators, QFileSystemIterator is uni-directional (i.e.,
+ you cannot iterate directories in reverse order) and does not allow random
+ access.
+
+ QFileSystemIterator works with all supported file engines, and is implemented
+ using QAbstractFileEngineIterator.
+
+ \sa QDir, QDir::entryList(), QAbstractFileEngineIterator
+*/
+
+/*! \enum QFileSystemIterator::IteratorFlag
+
+ This enum describes flags that you can combine to configure the behavior
+ of QFileSystemIterator.
+
+ \value NoIteratorFlags The default value, representing no flags. The
+ iterator will return entries for the assigned path.
+
+ \value Subdirectories List entries inside all subdirectories as well.
+
+ \value FollowSymlinks When combined with Subdirectories, this flag
+ enables iterating through all subdirectories of the assigned path,
+ following all symbolic links. Symbolic link loops (e.g., "link" => "." or
+ "link" => "..") are automatically detected and ignored.
+*/
+
+#include "qfilesystemiterator.h"
+
+#include <QDebug>
+#include <QtCore/qset.h>
+#include <QtCore/qstack.h>
+#include <QtCore/qvariant.h>
+
+#ifdef Q_OS_WIN
+# include <windows.h>
+# include <atlbase.h>
+#else
+# include <sys/stat.h>
+# include <sys/types.h>
+# include <dirent.h>
+# include <errno.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+inline QString convertString(TCHAR* sz)
+{
+#ifdef UNICODE
+ return QString::fromUtf16(sz);
+#else
+ return QString::fromLocal8Bit(sz);
+#endif
+}
+#endif
+
+class QFileSystemIteratorPrivate
+{
+public:
+ QFileSystemIteratorPrivate(const QString &path, const QStringList &nameFilters,
+ QDir::Filters filters, QFileSystemIterator::IteratorFlags flags);
+ ~QFileSystemIteratorPrivate();
+
+ void pushSubDirectory(const QByteArray &path);
+ void advance();
+ bool isAcceptable() const;
+ bool shouldFollowDirectory(const QFileInfo &);
+ //bool matchesFilters(const QAbstractFileEngineIterator *it) const;
+ inline bool atEnd() const { return m_dirPaths.isEmpty(); }
+
+#ifdef Q_OS_WIN
+ QStack<HANDLE> m_dirStructs;
+ WIN32_FIND_DATA* m_entry;
+ WIN32_FIND_DATA m_fileSearchResult;
+ bool m_bFirstSearchResult;
+#else
+ QStack<DIR *> m_dirStructs;
+ dirent *m_entry;
+#endif
+
+ QSet<QString> visitedLinks;
+ QStack<QByteArray> m_dirPaths;
+ QFileInfo fileInfo;
+ QString currentFilePath;
+ QFileSystemIterator::IteratorFlags iteratorFlags;
+ QDir::Filters filters;
+ QStringList nameFilters;
+
+ enum { DontShowDir, ShowDotDotDir, ShowDotDir, ShowDir }
+ m_currentDirShown, m_nextDirShown;
+
+ QFileSystemIterator *q;
+
+private:
+ bool advanceHelper(); // returns true if we know we have something suitable
+};
+
+/*!
+ \internal
+*/
+QFileSystemIteratorPrivate::QFileSystemIteratorPrivate(const QString &path,
+ const QStringList &nameFilters, QDir::Filters filters,
+ QFileSystemIterator::IteratorFlags flags)
+ : iteratorFlags(flags)
+{
+ if (filters == QDir::NoFilter)
+ filters = QDir::AllEntries;
+ this->filters = filters;
+ this->nameFilters = nameFilters;
+
+ fileInfo.setFile(path);
+ QString dir = fileInfo.isSymLink() ? fileInfo.canonicalFilePath() : path;
+ pushSubDirectory(dir.toLocal8Bit());
+ // skip to acceptable entry
+ while (true) {
+ if (atEnd())
+ return;
+ if (isAcceptable())
+ return;
+ if (advanceHelper())
+ return;
+ }
+}
+
+/*!
+ \internal
+*/
+QFileSystemIteratorPrivate::~QFileSystemIteratorPrivate()
+{
+#ifdef Q_OS_WIN
+ while (!m_dirStructs.isEmpty())
+ ::FindClose(m_dirStructs.pop());
+#else
+ while (!m_dirStructs.isEmpty())
+ ::closedir(m_dirStructs.pop());
+#endif
+}
+
+#ifdef Q_OS_WIN
+static bool isDotOrDotDot(const TCHAR* name)
+{
+ if (name[0] == L'.' && name[1] == 0)
+ return true;
+ if (name[0] == L'.' && name[1] == L'.' && name[2] == 0)
+ return true;
+ return false;
+}
+#else
+static bool isDotOrDotDot(const char *name)
+{
+ if (name[0] == '.' && name[1] == 0)
+ return true;
+ if (name[0] == '.' && name[1] == '.' && name[2] == 0)
+ return true;
+ return false;
+}
+#endif
+
+/*!
+ \internal
+*/
+void QFileSystemIteratorPrivate::pushSubDirectory(const QByteArray &path)
+{
+/*
+ if (iteratorFlags & QFileSystemIterator::FollowSymlinks) {
+ if (fileInfo.filePath() != path)
+ fileInfo.setFile(path);
+ if (fileInfo.isSymLink()) {
+ visitedLinks << fileInfo.canonicalFilePath();
+ } else {
+ visitedLinks << fileInfo.absoluteFilePath();
+ }
+ }
+*/
+
+#ifdef Q_OS_WIN
+ wchar_t szSearchPath[MAX_PATH];
+ wcscpy(szSearchPath, QString(path).utf16());
+ wcscat(szSearchPath, L"\\*");
+ HANDLE dir = FindFirstFile(szSearchPath, &m_fileSearchResult);
+ m_bFirstSearchResult = true;
+#else
+ DIR *dir = ::opendir(path.constData());
+ //m_entry = ::readdir(dir);
+ //while (m_entry && isDotOrDotDot(m_entry->d_name))
+ // m_entry = ::readdir(m_dirStructs.top());
+#endif
+ m_dirStructs.append(dir);
+ m_dirPaths.append(path);
+ m_entry = 0;
+ if (filters & QDir::Dirs)
+ m_nextDirShown = ShowDir;
+ else
+ m_nextDirShown = DontShowDir;
+ m_currentDirShown = DontShowDir;
+}
+
+/*!
+ \internal
+*/
+bool QFileSystemIteratorPrivate::isAcceptable() const
+{
+ if (!m_entry)
+ return false;
+ return true;
+}
+
+/*!
+ \internal
+*/
+
+
+void QFileSystemIteratorPrivate::advance()
+{
+ while (true) {
+ if (advanceHelper())
+ return;
+ if (atEnd())
+ return;
+ if (isAcceptable())
+ return;
+ }
+}
+
+bool QFileSystemIteratorPrivate::advanceHelper()
+{
+ if (m_dirStructs.isEmpty())
+ return true;
+
+ //printf("ADV %d %d\n", int(m_currentDirShown), int(m_nextDirShown));
+
+ if ((filters & QDir::Dirs)) {
+ m_currentDirShown = m_nextDirShown;
+ if (m_nextDirShown == ShowDir) {
+ //printf("RESTING ON DIR %s %x\n", m_dirPaths.top().constData(), int(filters));
+ m_nextDirShown = (filters & QDir::NoDotAndDotDot) ? DontShowDir : ShowDotDir;
+ // skip start directory itself
+ if (m_dirStructs.size() == 1 && m_currentDirShown == ShowDir)
+ return advanceHelper();
+ return true;
+ }
+ if (m_nextDirShown == ShowDotDir) {
+ //printf("RESTING ON DOT %s %x\n", m_dirPaths.top().constData(), int(filters));
+ m_nextDirShown = ShowDotDotDir;
+ return true;
+ }
+ if (m_nextDirShown == ShowDotDotDir) {
+ //printf("RESTING ON DOTDOT %s %x\n", m_dirPaths.top().constData(), int(filters));
+ m_nextDirShown = DontShowDir;
+ return true;
+ }
+ m_currentDirShown = DontShowDir;
+ }
+
+#ifdef Q_OS_WIN
+ m_entry = &m_fileSearchResult;
+ if (m_bFirstSearchResult) {
+ m_bFirstSearchResult = false;
+ } else {
+ if (!FindNextFile(m_dirStructs.top(), m_entry))
+ m_entry = 0;
+ }
+
+ while (m_entry && isDotOrDotDot(m_entry->cFileName))
+ if (!FindNextFile(m_dirStructs.top(), m_entry))
+ m_entry = 0;
+
+ if (!m_entry) {
+ m_dirPaths.pop();
+ FindClose(m_dirStructs.pop());
+ return false;
+ }
+
+ if (m_entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ QByteArray ba = m_dirPaths.top();
+ ba += '\\';
+ ba += convertString(m_entry->cFileName);
+ pushSubDirectory(ba);
+ }
+#else
+ m_entry = ::readdir(m_dirStructs.top());
+ while (m_entry && isDotOrDotDot(m_entry->d_name))
+ m_entry = ::readdir(m_dirStructs.top());
+ //return false; // further iteration possibly needed
+ //printf("READ %p %s\n", m_entry, m_entry ? m_entry->d_name : "");
+
+ if (!m_entry) {
+ m_dirPaths.pop();
+ DIR *dir = m_dirStructs.pop();
+ ::closedir(dir);
+ return false; // further iteration possibly needed
+ }
+
+ const char *name = m_entry->d_name;
+
+ QByteArray ba = m_dirPaths.top();
+ ba += '/';
+ ba += name;
+ struct stat st;
+ lstat(ba.constData(), &st);
+
+ if (S_ISDIR(st.st_mode)) {
+ pushSubDirectory(ba);
+ return false; // further iteration possibly needed
+ }
+#endif
+ return false; // further iteration possiblye needed
+}
+
+/*!
+ \internal
+ */
+bool QFileSystemIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo)
+{
+ // If we're doing flat iteration, we're done.
+ if (!(iteratorFlags & QFileSystemIterator::Subdirectories))
+ return false;
+
+ // Never follow non-directory entries
+ if (!fileInfo.isDir())
+ return false;
+
+
+ // Never follow . and ..
+ if (fileInfo.fileName() == QLatin1String(".") || fileInfo.fileName() == QLatin1String(".."))
+ return false;
+
+
+ // Check symlinks
+ if (fileInfo.isSymLink() && !(iteratorFlags & QFileSystemIterator::FollowSymlinks)) {
+ // Follow symlinks only if FollowSymlinks was passed
+ return false;
+ }
+
+ // Stop link loops
+ if (visitedLinks.contains(fileInfo.canonicalFilePath()))
+ return false;
+
+ return true;
+}
+
+
+/*!
+ \internal
+
+ This convenience function implements the iterator's filtering logics and
+ applies then to the current directory entry.
+
+ It returns true if the current entry matches the filters (i.e., the
+ current entry will be returned as part of the directory iteration);
+ otherwise, false is returned.
+*/
+#if 0
+bool QFileSystemIteratorPrivate::matchesFilters(const QAbstractFileEngineIterator *it) const
+{
+ const bool filterPermissions = ((filters & QDir::PermissionMask)
+ && (filters & QDir::PermissionMask) != QDir::PermissionMask);
+ const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
+ const bool skipFiles = !(filters & QDir::Files);
+ const bool skipSymlinks = (filters & QDir::NoSymLinks);
+ const bool doReadable = !filterPermissions || (filters & QDir::Readable);
+ const bool doWritable = !filterPermissions || (filters & QDir::Writable);
+ const bool doExecutable = !filterPermissions || (filters & QDir::Executable);
+ const bool includeHidden = (filters & QDir::Hidden);
+ const bool includeSystem = (filters & QDir::System);
+
+#ifndef QT_NO_REGEXP
+ // Prepare name filters
+ QList<QRegExp> regexps;
+ bool hasNameFilters = !nameFilters.isEmpty() && !(nameFilters.contains(QLatin1String("*")));
+ if (hasNameFilters) {
+ for (int i = 0; i < nameFilters.size(); ++i) {
+ regexps << QRegExp(nameFilters.at(i),
+ (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive,
+ QRegExp::Wildcard);
+ }
+ }
+#endif
+
+ QString fileName = it->currentFileName();
+ if (fileName.isEmpty()) {
+ // invalid entry
+ return false;
+ }
+
+ QFileInfo fi = it->currentFileInfo();
+ QString filePath = it->currentFilePath();
+
+#ifndef QT_NO_REGEXP
+ // Pass all entries through name filters, except dirs if the AllDirs
+ // filter is passed.
+ if (hasNameFilters && !((filters & QDir::AllDirs) && fi.isDir())) {
+ bool matched = false;
+ for (int i = 0; i < regexps.size(); ++i) {
+ if (regexps.at(i).exactMatch(fileName)) {
+ matched = true;
+ break;
+ }
+ }
+ if (!matched)
+ return false;
+ }
+#endif
+
+ bool dotOrDotDot = (fileName == QLatin1String(".") || fileName == QLatin1String(".."));
+ if ((filters & QDir::NoDotAndDotDot) && dotOrDotDot)
+ return false;
+
+ bool isHidden = !dotOrDotDot && fi.isHidden();
+ if (!includeHidden && isHidden)
+ return false;
+
+ bool isSystem = (!fi.isFile() && !fi.isDir() && !fi.isSymLink())
+ || (!fi.exists() && fi.isSymLink());
+ if (!includeSystem && isSystem)
+ return false;
+
+ bool alwaysShow = (filters & QDir::TypeMask) == 0
+ && ((isHidden && includeHidden)
+ || (includeSystem && isSystem));
+
+ // Skip files and directories
+ if ((filters & QDir::AllDirs) == 0 && skipDirs && fi.isDir()) {
+ if (!alwaysShow)
+ return false;
+ }
+
+ if ((skipFiles && (fi.isFile() || !fi.exists()))
+ || (skipSymlinks && fi.isSymLink())) {
+ if (!alwaysShow)
+ return false;
+ }
+
+ if (filterPermissions
+ && ((doReadable && !fi.isReadable())
+ || (doWritable && !fi.isWritable())
+ || (doExecutable && !fi.isExecutable()))) {
+ return false;
+ }
+
+ if (!includeSystem && !dotOrDotDot && ((fi.exists() && !fi.isFile() && !fi.isDir() && !fi.isSymLink())
+ || (!fi.exists() && fi.isSymLink()))) {
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+/*!
+ Constructs a QFileSystemIterator that can iterate over \a dir's entrylist, using
+ \a dir's name filters and regular filters. You can pass options via \a
+ flags to decide how the directory should be iterated.
+
+ By default, \a flags is NoIteratorFlags, which provides the same behavior
+ as in QDir::entryList().
+
+ The sorting in \a dir is ignored.
+
+ \sa atEnd(), next(), IteratorFlags
+*/
+QFileSystemIterator::QFileSystemIterator(const QDir &dir, IteratorFlags flags)
+ : d(new QFileSystemIteratorPrivate(dir.path(), dir.nameFilters(), dir.filter(), flags))
+{
+ d->q = this;
+}
+
+/*!
+ Constructs a QFileSystemIterator that can iterate over \a path, with no name
+ filtering and \a filters for entry filtering. You can pass options via \a
+ flags to decide how the directory should be iterated.
+
+ By default, \a filters is QDir::NoFilter, and \a flags is NoIteratorFlags,
+ which provides the same behavior as in QDir::entryList().
+
+ \sa atEnd(), next(), IteratorFlags
+*/
+QFileSystemIterator::QFileSystemIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
+ : d(new QFileSystemIteratorPrivate(path, QStringList(QLatin1String("*")), filters, flags))
+{
+ d->q = this;
+}
+
+/*!
+ Constructs a QFileSystemIterator that can iterate over \a path. You can pass
+ options via \a flags to decide how the directory should be iterated.
+
+ By default, \a flags is NoIteratorFlags, which provides the same behavior
+ as in QDir::entryList().
+
+ \sa atEnd(), next(), IteratorFlags
+*/
+QFileSystemIterator::QFileSystemIterator(const QString &path, IteratorFlags flags)
+ : d(new QFileSystemIteratorPrivate(path, QStringList(QLatin1String("*")), QDir::NoFilter, flags))
+{
+ d->q = this;
+}
+
+/*!
+ Constructs a QFileSystemIterator that can iterate over \a path, using \a
+ nameFilters and \a filters. You can pass options via \a flags to decide
+ how the directory should be iterated.
+
+ By default, \a flags is NoIteratorFlags, which provides the same behavior
+ as QDir::entryList().
+
+ \sa atEnd(), next(), IteratorFlags
+*/
+QFileSystemIterator::QFileSystemIterator(const QString &path, const QStringList &nameFilters,
+ QDir::Filters filters, IteratorFlags flags)
+ : d(new QFileSystemIteratorPrivate(path, nameFilters, filters, flags))
+{
+ d->q = this;
+}
+
+/*!
+ Destroys the QFileSystemIterator.
+*/
+QFileSystemIterator::~QFileSystemIterator()
+{
+ delete d;
+}
+
+/*!
+ Advances the iterator to the next entry, and returns the file path of this
+ new entry. If atEnd() returns true, this function does nothing, and
+ returns a null QString.
+
+ You can call fileName() or filePath() to get the current entry file name
+ or path, or fileInfo() to get a QFileInfo for the current entry.
+
+ \sa hasNext(), fileName(), filePath(), fileInfo()
+*/
+void QFileSystemIterator::next()
+{
+ d->advance();
+}
+
+/*!
+ Returns true if there is at least one more entry in the directory;
+ otherwise, false is returned.
+
+ \sa next(), fileName(), filePath(), fileInfo()
+*/
+bool QFileSystemIterator::atEnd() const
+{
+ return d->atEnd();
+}
+
+/*!
+ Returns the file name for the current directory entry, without the path
+ prepended. If the current entry is invalid (i.e., isValid() returns
+ false), a null QString is returned.
+
+ This function is provided for the convenience when iterating single
+ directories. For recursive iteration, you should call filePath() or
+ fileInfo() instead.
+
+ \sa filePath(), fileInfo()
+*/
+QString QFileSystemIterator::fileName() const
+{
+ if (d->atEnd() || !d->m_entry)
+ return QString();
+ if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDir)
+ return QString();
+ if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDir)
+ return QLatin1String("@");
+ if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDotDir)
+ return QLatin1String("@@");
+#ifdef Q_OS_WIN
+ return convertString(d->m_entry->cFileName);
+#else
+ return QString::fromLocal8Bit(d->m_entry->d_name);
+#endif
+}
+
+/*!
+ Returns the full file path for the current directory entry. If the current
+ entry is invalid (i.e., isValid() returns false), a null QString is
+ returned.
+
+ \sa fileInfo(), fileName()
+*/
+QString QFileSystemIterator::filePath() const
+{
+ if (d->atEnd())
+ return QString();
+ QByteArray ba = d->m_dirPaths.top();
+ if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDir)
+ ba += "/.";
+ else if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDotDir)
+ ba += "/..";
+ else if (d->m_entry) {
+ ba += '/';
+#ifdef Q_OS_WIN
+ ba += convertString(d->m_entry->cFileName);
+#else
+ ba += d->m_entry->d_name;
+#endif
+ }
+ return QString::fromLocal8Bit(ba);
+}
+
+/*!
+ Returns a QFileInfo for the current directory entry. If the current entry
+ is invalid (i.e., isValid() returns false), a null QFileInfo is returned.
+
+ \sa filePath(), fileName()
+*/
+QFileInfo QFileSystemIterator::fileInfo() const
+{
+ return QFileInfo(filePath());
+}
+
+/*!
+ Returns the base directory of the iterator.
+*/
+QString QFileSystemIterator::path() const
+{
+ return QString::fromLocal8Bit(d->m_dirPaths.top());
+}
+
+QT_END_NAMESPACE
diff --git a/tests/benchmarks/qdiriterator/qfilesystemiterator.h b/tests/benchmarks/qdiriterator/qfilesystemiterator.h
new file mode 100644
index 0000000..b5f42b7
--- /dev/null
+++ b/tests/benchmarks/qdiriterator/qfilesystemiterator.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMITERATOR_H
+#define QFILESYSTEMITERATOR_H
+
+#include <QtCore/qdir.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QFileSystemIteratorPrivate;
+class //Q_CORE_EXPORT
+QFileSystemIterator
+{
+public:
+ enum IteratorFlag {
+ NoIteratorFlags = 0x0,
+ FollowSymlinks = 0x1,
+ Subdirectories = 0x2
+ };
+ Q_DECLARE_FLAGS(IteratorFlags, IteratorFlag)
+
+ QFileSystemIterator(const QDir &dir, IteratorFlags flags = NoIteratorFlags);
+ QFileSystemIterator(const QString &path,
+ IteratorFlags flags = NoIteratorFlags);
+ QFileSystemIterator(const QString &path,
+ QDir::Filters filter,
+ IteratorFlags flags = NoIteratorFlags);
+ QFileSystemIterator(const QString &path,
+ const QStringList &nameFilters,
+ QDir::Filters filters = QDir::NoFilter,
+ IteratorFlags flags = NoIteratorFlags);
+
+ virtual ~QFileSystemIterator();
+
+ void next();
+ bool atEnd() const;
+
+ QString fileName() const;
+ QString filePath() const;
+ QFileInfo fileInfo() const;
+ QString path() const;
+
+private:
+ Q_DISABLE_COPY(QFileSystemIterator)
+
+ QFileSystemIteratorPrivate *d;
+ friend class QDir;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemIterator::IteratorFlags)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif