Qt 4.8
qdiriterator.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
98 #include "qdiriterator.h"
99 #include "qdir_p.h"
100 
101 #include "qabstractfileengine.h"
102 
103 #include <QtCore/qset.h>
104 #include <QtCore/qstack.h>
105 #include <QtCore/qvariant.h>
106 
107 #include <QtCore/private/qfilesystemiterator_p.h>
108 #include <QtCore/private/qfilesystementry_p.h>
109 #include <QtCore/private/qfilesystemmetadata_p.h>
110 #include <QtCore/private/qfilesystemengine_p.h>
111 #include <QtCore/qfsfileengine.h>
112 #include <QtCore/private/qfileinfo_p.h>
113 
115 
116 template <class Iterator>
117 class QDirIteratorPrivateIteratorStack : public QStack<Iterator *>
118 {
119 public:
121  {
122  qDeleteAll(*this);
123  }
124 };
125 
127 {
128 public:
129  QDirIteratorPrivate(const QFileSystemEntry &entry, const QStringList &nameFilters,
130  QDir::Filters filters, QDirIterator::IteratorFlags flags, bool resolveEngine = true);
131 
132  void advance();
133 
134  bool entryMatches(const QString & fileName, const QFileInfo &fileInfo);
135  void pushDirectory(const QFileInfo &fileInfo);
136  void checkAndPushDirectory(const QFileInfo &);
137  bool matchesFilters(const QString &fileName, const QFileInfo &fi) const;
138 
140 
143  const QDir::Filters filters;
144  const QDirIterator::IteratorFlags iteratorFlags;
145 
146 #ifndef QT_NO_REGEXP
148 #endif
149 
151 #ifndef QT_NO_FILESYSTEMITERATOR
153 #endif
154 
157 
158  // Loop protection
160 };
161 
166  QDir::Filters filters, QDirIterator::IteratorFlags flags, bool resolveEngine)
167  : dirEntry(entry)
168  , nameFilters(nameFilters.contains(QLatin1String("*")) ? QStringList() : nameFilters)
169  , filters(QDir::NoFilter == filters ? QDir::AllEntries : filters)
170  , iteratorFlags(flags)
171 {
172 #ifndef QT_NO_REGEXP
173  nameRegExps.reserve(nameFilters.size());
174  for (int i = 0; i < nameFilters.size(); ++i)
176  QRegExp(nameFilters.at(i),
179 #endif
180  QFileSystemMetaData metaData;
181  if (resolveEngine)
183  QFileInfo fileInfo(new QFileInfoPrivate(dirEntry, metaData));
184 
185  // Populate fields for hasNext() and next()
186  pushDirectory(fileInfo);
187  advance();
188 }
189 
194 {
195  QString path = fileInfo.filePath();
196 
197 #ifdef Q_OS_WIN
198  if (fileInfo.isSymLink())
199  path = fileInfo.canonicalFilePath();
200 #endif
201 
203  visitedLinks << fileInfo.canonicalFilePath();
204 
205  if (engine) {
206  engine->setFileName(path);
208  if (it) {
209  it->setPath(path);
211  } else {
212  // No iterator; no entry list.
213  }
214  } else {
215 #ifndef QT_NO_FILESYSTEMITERATOR
218  nativeIterators << it;
219 #endif
220  }
221 }
222 
223 inline bool QDirIteratorPrivate::entryMatches(const QString & fileName, const QFileInfo &fileInfo)
224 {
225  checkAndPushDirectory(fileInfo);
226 
227  if (matchesFilters(fileName, fileInfo)) {
229  nextFileInfo = fileInfo;
230 
231  //We found a matching entry.
232  return true;
233  }
234 
235  return false;
236 }
237 
242 {
243  if (engine) {
244  while (!fileEngineIterators.isEmpty()) {
245  // Find the next valid iterator that matches the filters.
247  while (it = fileEngineIterators.top(), it->hasNext()) {
248  it->next();
249  if (entryMatches(it->currentFileName(), it->currentFileInfo()))
250  return;
251  }
252 
254  delete it;
255  }
256  } else {
257 #ifndef QT_NO_FILESYSTEMITERATOR
258  QFileSystemEntry nextEntry;
259  QFileSystemMetaData nextMetaData;
260 
261  while (!nativeIterators.isEmpty()) {
262  // Find the next valid iterator that matches the filters.
264  while (it = nativeIterators.top(), it->advance(nextEntry, nextMetaData)) {
265  QFileInfo info(new QFileInfoPrivate(nextEntry, nextMetaData));
266 
267  if (entryMatches(nextEntry.fileName(), info))
268  return;
269  }
270 
272  delete it;
273  }
274 #endif
275  }
276 
279 }
280 
285 {
286  // If we're doing flat iteration, we're done.
288  return;
289 
290  // Never follow non-directory entries
291  if (!fileInfo.isDir())
292  return;
293 
294  // Follow symlinks only when asked
296  return;
297 
298  // Never follow . and ..
299  QString fileName = fileInfo.fileName();
300  if (QLatin1String(".") == fileName || QLatin1String("..") == fileName)
301  return;
302 
303  // No hidden directories unless requested
304  if (!(filters & QDir::AllDirs) && !(filters & QDir::Hidden) && fileInfo.isHidden())
305  return;
306 
307  // Stop link loops
308  if (!visitedLinks.isEmpty() &&
310  return;
311 
312  pushDirectory(fileInfo);
313 }
314 
330 {
331  Q_ASSERT(!fileName.isEmpty());
332 
333  // filter . and ..?
334  const int fileNameSize = fileName.size();
335  const bool dotOrDotDot = fileName[0] == QLatin1Char('.')
336  && ((fileNameSize == 1)
337  ||(fileNameSize == 2 && fileName[1] == QLatin1Char('.')));
338  if ((filters & QDir::NoDot) && dotOrDotDot && fileNameSize == 1)
339  return false;
340  if ((filters & QDir::NoDotDot) && dotOrDotDot && fileNameSize == 2)
341  return false;
342  if ((filters & QDir::NoDotAndDotDot) && dotOrDotDot) // ### Qt5 remove (NoDotAndDotDot == NoDot|NoDotDot)
343  return false;
344 
345  // name filter
346 #ifndef QT_NO_REGEXP
347  // Pass all entries through name filters, except dirs if the AllDirs
348  if (!nameFilters.isEmpty() && !((filters & QDir::AllDirs) && fi.isDir())) {
349  bool matched = false;
352  iter != end; ++iter) {
353 
354  if (iter->exactMatch(fileName)) {
355  matched = true;
356  break;
357  }
358  }
359  if (!matched)
360  return false;
361  }
362 #endif
363  // skip symlinks
364  const bool skipSymlinks = (filters & QDir::NoSymLinks);
365  const bool includeSystem = (filters & QDir::System);
366  if(skipSymlinks && fi.isSymLink()) {
367  // The only reason to save this file is if it is a broken link and we are requesting system files.
368  if(!includeSystem || fi.exists())
369  return false;
370  }
371 
372  // filter hidden
373  const bool includeHidden = (filters & QDir::Hidden);
374  if (!includeHidden && !dotOrDotDot && fi.isHidden())
375  return false;
376 
377  // filter system files
378  if (!includeSystem && (!(fi.isFile() || fi.isDir() || fi.isSymLink())
379  || (!fi.exists() && fi.isSymLink())))
380  return false;
381 
382  // skip directories
383  const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
384  if (skipDirs && fi.isDir())
385  return false;
386 
387  // skip files
388  const bool skipFiles = !(filters & QDir::Files);
389  if (skipFiles && fi.isFile())
390  // Basically we need a reason not to exclude this file otherwise we just eliminate it.
391  return false;
392 
393  // filter permissions
394  const bool filterPermissions = ((filters & QDir::PermissionMask)
396  const bool doWritable = !filterPermissions || (filters & QDir::Writable);
397  const bool doExecutable = !filterPermissions || (filters & QDir::Executable);
398  const bool doReadable = !filterPermissions || (filters & QDir::Readable);
399  if (filterPermissions
400  && ((doReadable && !fi.isReadable())
401  || (doWritable && !fi.isWritable())
402  || (doExecutable && !fi.isExecutable()))) {
403  return false;
404  }
405 
406  return true;
407 }
408 
424 QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags)
425 {
426  // little trick to get hold of the QDirPrivate while there is no API on QDir to give it to us
427  class MyQDir : public QDir { public: const QDirPrivate *priv() const { return d_ptr.constData(); } };
428  const QDirPrivate *other = static_cast<const MyQDir*>(&dir)->priv();
429  d.reset(new QDirIteratorPrivate(other->dirEntry, other->nameFilters, other->filters, flags, !other->fileEngine.isNull()));
430 }
431 
445 QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
446  : d(new QDirIteratorPrivate(QFileSystemEntry(path), QStringList(), filters, flags))
447 {
448 }
449 
462 QDirIterator::QDirIterator(const QString &path, IteratorFlags flags)
463  : d(new QDirIteratorPrivate(QFileSystemEntry(path), QStringList(), QDir::NoFilter, flags))
464 {
465 }
466 
481  QDir::Filters filters, IteratorFlags flags)
482  : d(new QDirIteratorPrivate(QFileSystemEntry(path), nameFilters, filters, flags))
483 {
484 }
485 
490 {
491 }
492 
504 {
505  d->advance();
506  return filePath();
507 }
508 
516 {
517  if (d->engine)
518  return !d->fileEngineIterators.isEmpty();
519  else
520 #ifndef QT_NO_FILESYSTEMITERATOR
521  return !d->nativeIterators.isEmpty();
522 #else
523  return false;
524 #endif
525 }
526 
538 {
539  return d->currentFileInfo.fileName();
540 }
541 
548 {
549  return d->currentFileInfo.filePath();
550 }
551 
558 {
559  return d->currentFileInfo;
560 }
561 
566 {
567  return d->dirEntry.filePath();
568 }
569 
bool isNull() const
Returns true if this object is holding a pointer that is null.
The QDir class provides access to directory structures and their contents.
Definition: qdir.h:58
double d
Definition: qnumeric_p.h:62
QFileSystemEntry fileEntry
Definition: qfileinfo_p.h:142
bool isHidden() const
Returns true if this is a `hidden&#39; file; otherwise returns false.
Definition: qfileinfo.cpp:951
static mach_timebase_info_data_t info
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
virtual ~QDirIterator()
Destroys the QDirIterator.
bool hasNext() const
Returns true if there is at least one more entry in the directory; otherwise, false is returned...
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
#define it(className, varName)
QDirIterator(const QDir &dir, IteratorFlags flags=NoIteratorFlags)
Constructs a QDirIterator that can iterate over dir&#39;s entrylist, using dir&#39;s name filters and regular...
bool isEmpty() const
Definition: qset.h:77
QFileSystemEntry dirEntry
Definition: qdir_p.h:91
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the vector...
Definition: qvector.h:252
QString fileName() const
Returns the name of the file, excluding the path.
Definition: qfileinfo.cpp:726
QScopedPointer< QDirIteratorPrivate > d
Definition: qdiriterator.h:87
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
bool exists() const
Returns true if the file exists; otherwise returns false.
Definition: qfileinfo.cpp:675
QSharedDataPointer< QFileInfoPrivate > d_ptr
Definition: qfileinfo.h:177
The QStack class is a template class that provides a stack.
Definition: qcontainerfwd.h:63
The QString class provides a Unicode character string.
Definition: qstring.h:83
QFileInfo fileInfo() const
Returns a QFileInfo for the current directory entry.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
void pushDirectory(const QFileInfo &fileInfo)
QScopedPointer< QAbstractFileEngine > fileEngine
Definition: qdir_p.h:85
virtual void setFileName(const QString &file)
Sets the file engine&#39;s file name to file.
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
QString path() const
Returns the base directory of the iterator.
T pop()
Removes the top item from the stack and returns it.
Definition: qstack.h:67
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the vector.
Definition: qvector.h:249
QString fileName() const
Returns the file name for the current directory entry, without the path prepended.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QDirIteratorPrivateIteratorStack< QAbstractFileEngineIterator > fileEngineIterators
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory; otherwise ret...
Definition: qfileinfo.cpp:990
bool contains(const T &value) const
Definition: qset.h:91
int size() const
Returns the number of characters in this string.
Definition: qstring.h:102
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QVector< QRegExp > nameRegExps
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
bool entryMatches(const QString &fileName, const QFileInfo &fileInfo)
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
QString fileName() const
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
Definition: qfileinfo.cpp:551
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
bool isExecutable() const
Returns true if the file is executable; otherwise returns false.
Definition: qfileinfo.cpp:932
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
virtual bool hasNext() const =0
This pure virtual function returns true if there is at least one more entry in the current directory ...
bool advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
void reset(T *other=0)
Deletes the existing object it is pointing to if any, and sets its pointer to other.
void setPath(const QString &path)
Sets the iterator path to path.
virtual Iterator * beginEntryList(QDir::Filters filters, const QStringList &filterNames)
Returns an instance of a QAbstractFileEngineIterator using filters for entry filtering and filterName...
static const char *const filters[3]
QString next()
Advances the iterator to the next entry, and returns the file path of this new entry.
bool matchesFilters(const QString &fileName, const QFileInfo &fi) const
This convenience function implements the iterator&#39;s filtering logics and applies then to the current ...
QScopedPointer< QAbstractFileEngine > engine
void checkAndPushDirectory(const QFileInfo &)
QStringList nameFilters
Definition: qdir_p.h:76
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
static const QMetaObjectPrivate * priv(const uint *data)
The QAbstractFileEngineIterator class provides an iterator interface for custom file engines...
bool isFile() const
Returns true if this object points to a file or to a symbolic link to a file.
Definition: qfileinfo.cpp:971
virtual QString next()=0
This pure virtual function advances the iterator to the next directory entry, and returns the file pa...
QDir::Filters filters
Definition: qdir_p.h:78
bool contains(const T &t) const
Returns true if the vector contains an occurrence of value; otherwise returns false.
Definition: qvector.h:731
QString filePath() const
const QDirIterator::IteratorFlags iteratorFlags
QDirIteratorPrivateIteratorStack< QFileSystemIterator > nativeIterators
virtual QString currentFileName() const =0
This pure virtual function returns the name of the current directory entry, excluding the path...
const QStringList nameFilters
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
static QAbstractFileEngine * resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry, QFileSystemMetaData &data)
Resolves the entry (see QDir::searchPaths) and returns an engine for it, but never a QFSFileEngine...
void reserve(int size)
Attempts to allocate memory for at least size elements.
Definition: qvector.h:339
bool isReadable() const
Returns true if the user can read the file; otherwise returns false.
Definition: qfileinfo.cpp:896
QString filePath() const
Returns the full file path for the current directory entry.
bool isSymLink() const
Returns true if this object points to a symbolic link (or to a shortcut on Windows); otherwise return...
Definition: qfileinfo.cpp:1044
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
static const KeyPair *const end
QString filePath() const
Returns the file name, including the path (which may be absolute or relative).
Definition: qfileinfo.cpp:707
static QString fileName(const QString &fileUrl)
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
bool isWritable() const
Returns true if the user can write to the file; otherwise returns false.
Definition: qfileinfo.cpp:914
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
QSet< QString > visitedLinks
virtual QFileInfo currentFileInfo() const
The virtual function returns a QFileInfo for the current directory entry.
const QDir::Filters filters
QFileSystemEntry dirEntry
T & top()
Returns a reference to the stack&#39;s top item.
Definition: qstack.h:72
QDirIteratorPrivate(const QFileSystemEntry &entry, const QStringList &nameFilters, QDir::Filters filters, QDirIterator::IteratorFlags flags, bool resolveEngine=true)