diff options
author | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
commit | 8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch) | |
tree | a17e1a767a89542ab59907462206d7dcf2e504b2 /tests/benchmarks/qdiriterator | |
download | Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.zip Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.bz2 |
Long live Qt for S60!
Diffstat (limited to 'tests/benchmarks/qdiriterator')
-rwxr-xr-x | tests/benchmarks/qdiriterator/main.cpp | 251 | ||||
-rwxr-xr-x | tests/benchmarks/qdiriterator/qdiriterator.pro | 23 | ||||
-rw-r--r-- | tests/benchmarks/qdiriterator/qfilesystemiterator.cpp | 689 | ||||
-rw-r--r-- | tests/benchmarks/qdiriterator/qfilesystemiterator.h | 99 |
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 |