tests/benchmarks/qdiriterator/qfilesystemiterator.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 /*!
       
    43     \since 4.5
       
    44     \class QFileSystemIterator
       
    45     \brief The QFileSystemIterator class provides an iterator for directory entrylists.
       
    46 
       
    47     You can use QFileSystemIterator to navigate entries of a directory one at a time.
       
    48     It is similar to QDir::entryList() and QDir::entryInfoList(), but because
       
    49     it lists entries one at a time instead of all at once, it scales better
       
    50     and is more suitable for large directories. It also supports listing
       
    51     directory contents recursively, and following symbolic links. Unlike
       
    52     QDir::entryList(), QFileSystemIterator does not support sorting.
       
    53 
       
    54     The QFileSystemIterator constructor takes a QDir or a directory as
       
    55     argument. After construction, the iterator is located before the first
       
    56     directory entry. Here's how to iterate over all the entries sequentially:
       
    57 
       
    58     \snippet doc/src/snippets/code/src.corelib.io.qdiriterator.cpp 0
       
    59 
       
    60     The next() function returns the path to the next directory entry and
       
    61     advances the iterator. You can also call filePath() to get the current
       
    62     file path without advancing the iterator.  The fileName() function returns
       
    63     only the name of the file, similar to how QDir::entryList() works. You can
       
    64     also call fileInfo() to get a QFileInfo for the current entry.
       
    65 
       
    66     Unlike Qt's container iterators, QFileSystemIterator is uni-directional (i.e.,
       
    67     you cannot iterate directories in reverse order) and does not allow random
       
    68     access.
       
    69 
       
    70     QFileSystemIterator works with all supported file engines, and is implemented
       
    71     using QAbstractFileEngineIterator.
       
    72 
       
    73     \sa QDir, QDir::entryList(), QAbstractFileEngineIterator
       
    74 */
       
    75 
       
    76 /*! \enum QFileSystemIterator::IteratorFlag
       
    77 
       
    78     This enum describes flags that you can combine to configure the behavior
       
    79     of QFileSystemIterator.
       
    80 
       
    81     \value NoIteratorFlags The default value, representing no flags. The
       
    82     iterator will return entries for the assigned path.
       
    83 
       
    84     \value Subdirectories List entries inside all subdirectories as well.
       
    85 
       
    86     \value FollowSymlinks When combined with Subdirectories, this flag
       
    87     enables iterating through all subdirectories of the assigned path,
       
    88     following all symbolic links. Symbolic link loops (e.g., "link" => "." or
       
    89     "link" => "..") are automatically detected and ignored.
       
    90 */
       
    91 
       
    92 #include "qfilesystemiterator.h"
       
    93 
       
    94 #include <QDebug>
       
    95 #include <QtCore/qset.h>
       
    96 #include <QtCore/qstack.h>
       
    97 #include <QtCore/qvariant.h>
       
    98 
       
    99 #ifdef Q_OS_WIN
       
   100 #   include <windows.h>
       
   101 #   include <atlbase.h>
       
   102 #else
       
   103 #   include <sys/stat.h>
       
   104 #   include <sys/types.h>
       
   105 #   include <dirent.h>
       
   106 #   include <errno.h>
       
   107 #endif
       
   108 
       
   109 QT_BEGIN_NAMESPACE
       
   110 
       
   111 class QFileSystemIteratorPrivate
       
   112 {
       
   113 public:
       
   114     QFileSystemIteratorPrivate(const QString &path, const QStringList &nameFilters,
       
   115                         QDir::Filters filters, QFileSystemIterator::IteratorFlags flags);
       
   116     ~QFileSystemIteratorPrivate();
       
   117 
       
   118     void pushSubDirectory(const QByteArray &path);
       
   119     void advance();
       
   120     bool isAcceptable() const;
       
   121     bool shouldFollowDirectory(const QFileInfo &);
       
   122     //bool matchesFilters(const QAbstractFileEngineIterator *it) const;
       
   123     inline bool atEnd() const { return m_dirPaths.isEmpty(); }
       
   124 
       
   125 #ifdef Q_OS_WIN
       
   126     QStack<HANDLE>   m_dirStructs;
       
   127     WIN32_FIND_DATA* m_entry;
       
   128     WIN32_FIND_DATA  m_fileSearchResult;
       
   129     bool             m_bFirstSearchResult;
       
   130 #else
       
   131     QStack<DIR *> m_dirStructs;
       
   132     dirent *m_entry;
       
   133 #endif
       
   134 
       
   135     QSet<QString> visitedLinks;
       
   136     QStack<QByteArray> m_dirPaths;
       
   137     QFileInfo fileInfo;
       
   138     QString currentFilePath;
       
   139     QFileSystemIterator::IteratorFlags iteratorFlags;
       
   140     QDir::Filters filters;
       
   141     QStringList nameFilters;
       
   142 
       
   143     enum { DontShowDir, ShowDotDotDir, ShowDotDir, ShowDir }
       
   144         m_currentDirShown, m_nextDirShown;
       
   145 
       
   146     QFileSystemIterator *q;
       
   147 
       
   148 private:
       
   149     bool advanceHelper();  // returns true if we know we have something suitable
       
   150 };
       
   151 
       
   152 /*!
       
   153     \internal
       
   154 */
       
   155 QFileSystemIteratorPrivate::QFileSystemIteratorPrivate(const QString &path,
       
   156     const QStringList &nameFilters, QDir::Filters filters,
       
   157     QFileSystemIterator::IteratorFlags flags)
       
   158   : iteratorFlags(flags)
       
   159 {
       
   160     if (filters == QDir::NoFilter)
       
   161         filters = QDir::AllEntries;
       
   162     this->filters = filters;
       
   163     this->nameFilters = nameFilters;
       
   164 
       
   165     fileInfo.setFile(path);
       
   166     QString dir = fileInfo.isSymLink() ? fileInfo.canonicalFilePath() : path;
       
   167     pushSubDirectory(dir.toLocal8Bit());
       
   168     // skip to acceptable entry
       
   169     while (true) {
       
   170         if (atEnd())
       
   171             return;
       
   172         if (isAcceptable())
       
   173             return;
       
   174         if (advanceHelper())
       
   175             return;
       
   176     }
       
   177 }
       
   178 
       
   179 /*!
       
   180     \internal
       
   181 */
       
   182 QFileSystemIteratorPrivate::~QFileSystemIteratorPrivate()
       
   183 {
       
   184 #ifdef Q_OS_WIN
       
   185     while (!m_dirStructs.isEmpty())
       
   186         ::FindClose(m_dirStructs.pop());
       
   187 #else
       
   188     while (!m_dirStructs.isEmpty())
       
   189         ::closedir(m_dirStructs.pop());
       
   190 #endif
       
   191 }
       
   192 
       
   193 #ifdef Q_OS_WIN
       
   194 static bool isDotOrDotDot(const wchar_t* name)
       
   195 {
       
   196     if (name[0] == L'.' && name[1] == 0)
       
   197         return true;
       
   198     if (name[0] == L'.' && name[1] == L'.' && name[2] == 0)
       
   199         return true;
       
   200     return false;
       
   201 }
       
   202 #else
       
   203 static bool isDotOrDotDot(const char *name)
       
   204 {
       
   205     if (name[0] == '.' && name[1] == 0)
       
   206         return true;
       
   207     if (name[0] == '.' && name[1] == '.' && name[2] == 0)
       
   208         return true;
       
   209     return false;
       
   210 }
       
   211 #endif
       
   212 
       
   213 /*!
       
   214     \internal
       
   215 */
       
   216 void QFileSystemIteratorPrivate::pushSubDirectory(const QByteArray &path)
       
   217 {
       
   218 /*
       
   219     if (iteratorFlags & QFileSystemIterator::FollowSymlinks) {
       
   220         if (fileInfo.filePath() != path)
       
   221             fileInfo.setFile(path);
       
   222         if (fileInfo.isSymLink()) {
       
   223             visitedLinks << fileInfo.canonicalFilePath();
       
   224         } else {
       
   225             visitedLinks << fileInfo.absoluteFilePath();
       
   226         }
       
   227     }
       
   228 */
       
   229 
       
   230 #ifdef Q_OS_WIN
       
   231     wchar_t szSearchPath[MAX_PATH];
       
   232     wcscpy(szSearchPath, QString(path).utf16());
       
   233     wcscat(szSearchPath, L"\\*");
       
   234     HANDLE dir = FindFirstFile(szSearchPath, &m_fileSearchResult);
       
   235     m_bFirstSearchResult = true;
       
   236 #else
       
   237     DIR *dir = ::opendir(path.constData());
       
   238     //m_entry = ::readdir(dir);
       
   239     //while (m_entry && isDotOrDotDot(m_entry->d_name))
       
   240     //    m_entry = ::readdir(m_dirStructs.top());
       
   241 #endif
       
   242     m_dirStructs.append(dir);
       
   243     m_dirPaths.append(path);
       
   244     m_entry = 0;
       
   245     if (filters & QDir::Dirs)
       
   246         m_nextDirShown = ShowDir;
       
   247     else
       
   248         m_nextDirShown = DontShowDir;
       
   249     m_currentDirShown = DontShowDir;
       
   250 }
       
   251 
       
   252 /*!
       
   253     \internal
       
   254 */
       
   255 bool QFileSystemIteratorPrivate::isAcceptable() const
       
   256 {
       
   257     if (!m_entry)
       
   258         return false;
       
   259     return true;
       
   260 }
       
   261 
       
   262 /*!
       
   263     \internal
       
   264 */
       
   265 
       
   266 
       
   267 void QFileSystemIteratorPrivate::advance()
       
   268 {
       
   269     while (true) {
       
   270         if (advanceHelper())
       
   271             return;
       
   272         if (atEnd())
       
   273             return;
       
   274         if (isAcceptable())
       
   275             return;
       
   276     }
       
   277 }
       
   278 
       
   279 bool QFileSystemIteratorPrivate::advanceHelper()
       
   280 {
       
   281     if (m_dirStructs.isEmpty())
       
   282         return true;
       
   283 
       
   284     //printf("ADV %d %d\n", int(m_currentDirShown), int(m_nextDirShown));
       
   285 
       
   286     if ((filters & QDir::Dirs)) {
       
   287         m_currentDirShown = m_nextDirShown;
       
   288         if (m_nextDirShown == ShowDir) {
       
   289             //printf("RESTING ON DIR %s %x\n", m_dirPaths.top().constData(), int(filters));
       
   290             m_nextDirShown = (filters & QDir::NoDotAndDotDot) ? DontShowDir : ShowDotDir;
       
   291             // skip start directory itself
       
   292             if (m_dirStructs.size() == 1 && m_currentDirShown == ShowDir)
       
   293                 return advanceHelper();
       
   294             return true;
       
   295         }
       
   296         if (m_nextDirShown == ShowDotDir) {
       
   297             //printf("RESTING ON DOT %s %x\n", m_dirPaths.top().constData(), int(filters));
       
   298             m_nextDirShown = ShowDotDotDir;
       
   299             return true;
       
   300         }
       
   301         if (m_nextDirShown == ShowDotDotDir) {
       
   302             //printf("RESTING ON DOTDOT %s %x\n", m_dirPaths.top().constData(), int(filters));
       
   303             m_nextDirShown = DontShowDir;
       
   304             return true;
       
   305         }
       
   306         m_currentDirShown = DontShowDir;
       
   307     }
       
   308 
       
   309 #ifdef Q_OS_WIN
       
   310     m_entry = &m_fileSearchResult;
       
   311     if (m_bFirstSearchResult) {
       
   312         m_bFirstSearchResult = false;
       
   313     } else {
       
   314         if (!FindNextFile(m_dirStructs.top(), m_entry))
       
   315             m_entry = 0;
       
   316     }
       
   317 
       
   318     while (m_entry && isDotOrDotDot(m_entry->cFileName))
       
   319         if (!FindNextFile(m_dirStructs.top(), m_entry))
       
   320             m_entry = 0;
       
   321 
       
   322     if (!m_entry) {
       
   323         m_dirPaths.pop();
       
   324         FindClose(m_dirStructs.pop());
       
   325         return false;
       
   326     }
       
   327 
       
   328     if (m_entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
       
   329         QByteArray ba = m_dirPaths.top();
       
   330         ba += '\\';
       
   331         ba += QString::fromWCharArray(m_entry->cFileName);
       
   332         pushSubDirectory(ba);
       
   333     }
       
   334 #else
       
   335     m_entry = ::readdir(m_dirStructs.top());
       
   336     while (m_entry && isDotOrDotDot(m_entry->d_name))
       
   337         m_entry = ::readdir(m_dirStructs.top());
       
   338         //return false; // further iteration possibly needed
       
   339     //printf("READ %p %s\n", m_entry, m_entry ? m_entry->d_name : "");
       
   340 
       
   341     if (!m_entry) {
       
   342         m_dirPaths.pop();
       
   343         DIR *dir = m_dirStructs.pop();
       
   344         ::closedir(dir);
       
   345         return false; // further iteration possibly needed
       
   346     }
       
   347 
       
   348     const char *name = m_entry->d_name;
       
   349 
       
   350     QByteArray ba = m_dirPaths.top();
       
   351     ba += '/';
       
   352     ba += name;
       
   353     struct stat st;
       
   354     lstat(ba.constData(), &st);
       
   355 
       
   356     if (S_ISDIR(st.st_mode)) {
       
   357         pushSubDirectory(ba);
       
   358         return false; // further iteration possibly needed
       
   359     }
       
   360 #endif
       
   361     return false; // further iteration possiblye needed
       
   362 }
       
   363 
       
   364 /*!
       
   365     \internal
       
   366  */
       
   367 bool QFileSystemIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo)
       
   368 {
       
   369     // If we're doing flat iteration, we're done.
       
   370     if (!(iteratorFlags & QFileSystemIterator::Subdirectories))
       
   371         return false;
       
   372     
       
   373     // Never follow non-directory entries
       
   374     if (!fileInfo.isDir())
       
   375         return false;
       
   376 
       
   377 
       
   378     // Never follow . and ..
       
   379     if (fileInfo.fileName() == QLatin1String(".") || fileInfo.fileName() == QLatin1String(".."))
       
   380         return false;
       
   381 
       
   382       
       
   383     // Check symlinks
       
   384     if (fileInfo.isSymLink() && !(iteratorFlags & QFileSystemIterator::FollowSymlinks)) {
       
   385         // Follow symlinks only if FollowSymlinks was passed
       
   386         return false;
       
   387     }
       
   388 
       
   389     // Stop link loops
       
   390     if (visitedLinks.contains(fileInfo.canonicalFilePath()))
       
   391         return false;
       
   392     
       
   393     return true;
       
   394 }
       
   395     
       
   396 
       
   397 /*!
       
   398     \internal
       
   399 
       
   400     This convenience function implements the iterator's filtering logics and
       
   401     applies then to the current directory entry.
       
   402 
       
   403     It returns true if the current entry matches the filters (i.e., the
       
   404     current entry will be returned as part of the directory iteration);
       
   405     otherwise, false is returned.
       
   406 */
       
   407 #if 0
       
   408 bool QFileSystemIteratorPrivate::matchesFilters(const QAbstractFileEngineIterator *it) const
       
   409 {
       
   410     const bool filterPermissions = ((filters & QDir::PermissionMask)
       
   411                                     && (filters & QDir::PermissionMask) != QDir::PermissionMask);
       
   412     const bool skipDirs     = !(filters & (QDir::Dirs | QDir::AllDirs));
       
   413     const bool skipFiles    = !(filters & QDir::Files);
       
   414     const bool skipSymlinks = (filters & QDir::NoSymLinks);
       
   415     const bool doReadable   = !filterPermissions || (filters & QDir::Readable);
       
   416     const bool doWritable   = !filterPermissions || (filters & QDir::Writable);
       
   417     const bool doExecutable = !filterPermissions || (filters & QDir::Executable);
       
   418     const bool includeHidden = (filters & QDir::Hidden);
       
   419     const bool includeSystem = (filters & QDir::System);
       
   420 
       
   421 #ifndef QT_NO_REGEXP
       
   422     // Prepare name filters
       
   423     QList<QRegExp> regexps;
       
   424     bool hasNameFilters = !nameFilters.isEmpty() && !(nameFilters.contains(QLatin1String("*")));
       
   425     if (hasNameFilters) {
       
   426         for (int i = 0; i < nameFilters.size(); ++i) {
       
   427             regexps << QRegExp(nameFilters.at(i),
       
   428                                (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive,
       
   429                                QRegExp::Wildcard);
       
   430         }
       
   431     }
       
   432 #endif
       
   433 
       
   434     QString fileName = it->currentFileName();
       
   435     if (fileName.isEmpty()) {
       
   436         // invalid entry
       
   437         return false;
       
   438     }
       
   439 
       
   440     QFileInfo fi = it->currentFileInfo();
       
   441     QString filePath = it->currentFilePath();
       
   442 
       
   443 #ifndef QT_NO_REGEXP
       
   444     // Pass all entries through name filters, except dirs if the AllDirs
       
   445     // filter is passed.
       
   446     if (hasNameFilters && !((filters & QDir::AllDirs) && fi.isDir())) {
       
   447         bool matched = false;
       
   448         for (int i = 0; i < regexps.size(); ++i) {
       
   449             if (regexps.at(i).exactMatch(fileName)) {
       
   450                 matched = true;
       
   451                 break;
       
   452             }
       
   453         }
       
   454         if (!matched)
       
   455             return false;
       
   456     }
       
   457 #endif
       
   458     
       
   459     bool dotOrDotDot = (fileName == QLatin1String(".") || fileName == QLatin1String(".."));
       
   460     if ((filters & QDir::NoDotAndDotDot) && dotOrDotDot)
       
   461         return false;
       
   462 
       
   463     bool isHidden = !dotOrDotDot && fi.isHidden();
       
   464     if (!includeHidden && isHidden)
       
   465         return false;
       
   466 
       
   467     bool isSystem = (!fi.isFile() && !fi.isDir() && !fi.isSymLink())
       
   468                     || (!fi.exists() && fi.isSymLink());
       
   469     if (!includeSystem && isSystem)
       
   470         return false;
       
   471 
       
   472     bool alwaysShow = (filters & QDir::TypeMask) == 0
       
   473         && ((isHidden && includeHidden)
       
   474             || (includeSystem && isSystem));
       
   475 
       
   476     // Skip files and directories
       
   477     if ((filters & QDir::AllDirs) == 0 && skipDirs && fi.isDir()) {
       
   478         if (!alwaysShow)
       
   479             return false;
       
   480     }
       
   481 
       
   482     if ((skipFiles && (fi.isFile() || !fi.exists()))
       
   483         || (skipSymlinks && fi.isSymLink())) {
       
   484         if (!alwaysShow)
       
   485             return false;
       
   486     }
       
   487 
       
   488     if (filterPermissions
       
   489         && ((doReadable && !fi.isReadable())
       
   490             || (doWritable && !fi.isWritable())
       
   491             || (doExecutable && !fi.isExecutable()))) {
       
   492         return false;
       
   493     }
       
   494 
       
   495     if (!includeSystem && !dotOrDotDot && ((fi.exists() && !fi.isFile() && !fi.isDir() && !fi.isSymLink())
       
   496                                            || (!fi.exists() && fi.isSymLink()))) {
       
   497         return false;
       
   498     }
       
   499     
       
   500     return true;
       
   501 }
       
   502 #endif
       
   503 
       
   504 /*!
       
   505     Constructs a QFileSystemIterator that can iterate over \a dir's entrylist, using
       
   506     \a dir's name filters and regular filters. You can pass options via \a
       
   507     flags to decide how the directory should be iterated.
       
   508 
       
   509     By default, \a flags is NoIteratorFlags, which provides the same behavior
       
   510     as in QDir::entryList().
       
   511 
       
   512     The sorting in \a dir is ignored.
       
   513 
       
   514     \sa atEnd(), next(), IteratorFlags
       
   515 */
       
   516 QFileSystemIterator::QFileSystemIterator(const QDir &dir, IteratorFlags flags)
       
   517     : d(new QFileSystemIteratorPrivate(dir.path(), dir.nameFilters(), dir.filter(), flags))
       
   518 {
       
   519     d->q = this;
       
   520 }
       
   521 
       
   522 /*!
       
   523     Constructs a QFileSystemIterator that can iterate over \a path, with no name
       
   524     filtering and \a filters for entry filtering. You can pass options via \a
       
   525     flags to decide how the directory should be iterated.
       
   526 
       
   527     By default, \a filters is QDir::NoFilter, and \a flags is NoIteratorFlags,
       
   528     which provides the same behavior as in QDir::entryList().
       
   529 
       
   530     \sa atEnd(), next(), IteratorFlags
       
   531 */
       
   532 QFileSystemIterator::QFileSystemIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
       
   533     : d(new QFileSystemIteratorPrivate(path, QStringList(QLatin1String("*")), filters, flags))
       
   534 {
       
   535     d->q = this;
       
   536 }
       
   537 
       
   538 /*!
       
   539     Constructs a QFileSystemIterator that can iterate over \a path. You can pass
       
   540     options via \a flags to decide how the directory should be iterated.
       
   541 
       
   542     By default, \a flags is NoIteratorFlags, which provides the same behavior
       
   543     as in QDir::entryList().
       
   544 
       
   545     \sa atEnd(), next(), IteratorFlags
       
   546 */
       
   547 QFileSystemIterator::QFileSystemIterator(const QString &path, IteratorFlags flags)
       
   548     : d(new QFileSystemIteratorPrivate(path, QStringList(QLatin1String("*")), QDir::NoFilter, flags))
       
   549 {
       
   550     d->q = this;
       
   551 }
       
   552 
       
   553 /*!
       
   554     Constructs a QFileSystemIterator that can iterate over \a path, using \a
       
   555     nameFilters and \a filters. You can pass options via \a flags to decide
       
   556     how the directory should be iterated.
       
   557 
       
   558     By default, \a flags is NoIteratorFlags, which provides the same behavior
       
   559     as QDir::entryList().
       
   560 
       
   561     \sa atEnd(), next(), IteratorFlags
       
   562 */
       
   563 QFileSystemIterator::QFileSystemIterator(const QString &path, const QStringList &nameFilters,
       
   564                            QDir::Filters filters, IteratorFlags flags)
       
   565     : d(new QFileSystemIteratorPrivate(path, nameFilters, filters, flags))
       
   566 {
       
   567     d->q = this;
       
   568 }
       
   569 
       
   570 /*!
       
   571     Destroys the QFileSystemIterator.
       
   572 */
       
   573 QFileSystemIterator::~QFileSystemIterator()
       
   574 {
       
   575     delete d;
       
   576 }
       
   577 
       
   578 /*!
       
   579     Advances the iterator to the next entry, and returns the file path of this
       
   580     new entry. If atEnd() returns true, this function does nothing, and
       
   581     returns a null QString.
       
   582 
       
   583     You can call fileName() or filePath() to get the current entry file name
       
   584     or path, or fileInfo() to get a QFileInfo for the current entry.
       
   585 
       
   586     \sa hasNext(), fileName(), filePath(), fileInfo()
       
   587 */
       
   588 void QFileSystemIterator::next()
       
   589 {
       
   590     d->advance();
       
   591 }
       
   592 
       
   593 /*!
       
   594     Returns true if there is at least one more entry in the directory;
       
   595     otherwise, false is returned.
       
   596 
       
   597     \sa next(), fileName(), filePath(), fileInfo()
       
   598 */
       
   599 bool QFileSystemIterator::atEnd() const
       
   600 {
       
   601     return d->atEnd();
       
   602 }
       
   603 
       
   604 /*!
       
   605     Returns the file name for the current directory entry, without the path
       
   606     prepended. If the current entry is invalid (i.e., isValid() returns
       
   607     false), a null QString is returned.
       
   608 
       
   609     This function is provided for the convenience when iterating single
       
   610     directories. For recursive iteration, you should call filePath() or
       
   611     fileInfo() instead.
       
   612     
       
   613     \sa filePath(), fileInfo()
       
   614 */
       
   615 QString QFileSystemIterator::fileName() const
       
   616 {
       
   617     if (d->atEnd() || !d->m_entry)
       
   618         return QString();
       
   619     if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDir)
       
   620         return QString();
       
   621     if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDir)
       
   622         return QLatin1String("@");
       
   623     if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDotDir)
       
   624         return QLatin1String("@@");
       
   625 #ifdef Q_OS_WIN
       
   626     return QString::fromWCharArray(d->m_entry->cFileName);
       
   627 #else
       
   628     return QString::fromLocal8Bit(d->m_entry->d_name);
       
   629 #endif
       
   630 }
       
   631 
       
   632 /*!
       
   633     Returns the full file path for the current directory entry. If the current
       
   634     entry is invalid (i.e., isValid() returns false), a null QString is
       
   635     returned.
       
   636 
       
   637     \sa fileInfo(), fileName()
       
   638 */
       
   639 QString QFileSystemIterator::filePath() const
       
   640 {
       
   641     if (d->atEnd())
       
   642         return QString();
       
   643     QByteArray ba = d->m_dirPaths.top();
       
   644     if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDir)
       
   645         ba += "/.";
       
   646     else if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDotDir)
       
   647         ba += "/..";
       
   648     else if (d->m_entry) {
       
   649         ba += '/';
       
   650 #ifdef Q_OS_WIN
       
   651         ba += QString::fromWCharArray(d->m_entry->cFileName);
       
   652 #else
       
   653         ba += d->m_entry->d_name;
       
   654 #endif
       
   655     }
       
   656     return QString::fromLocal8Bit(ba);
       
   657 }
       
   658 
       
   659 /*!
       
   660     Returns a QFileInfo for the current directory entry. If the current entry
       
   661     is invalid (i.e., isValid() returns false), a null QFileInfo is returned.
       
   662 
       
   663     \sa filePath(), fileName()
       
   664 */
       
   665 QFileInfo QFileSystemIterator::fileInfo() const
       
   666 {
       
   667     return QFileInfo(filePath());
       
   668 }
       
   669 
       
   670 /*!
       
   671     Returns the base directory of the iterator.
       
   672 */
       
   673 QString QFileSystemIterator::path() const
       
   674 {
       
   675     return QString::fromLocal8Bit(d->m_dirPaths.top());
       
   676 }
       
   677 
       
   678 QT_END_NAMESPACE