Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qdiriterator.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
56#include "qdiriterator.h"
57#include "qdir_p.h"
59
60#include <QtCore/qset.h>
61#include <QtCore/qstack.h>
62#include <QtCore/qvariant.h>
63#if QT_CONFIG(regularexpression)
64#include <QtCore/qregularexpression.h>
65#endif
66
67#include <QtCore/private/qfilesystemiterator_p.h>
68#include <QtCore/private/qfilesystementry_p.h>
69#include <QtCore/private/qfilesystemmetadata_p.h>
70#include <QtCore/private/qfilesystemengine_p.h>
71#include <QtCore/private/qfileinfo_p.h>
72#include <QtCore/private/qduplicatetracker_p.h>
73
74#include <memory>
75
77
78using namespace Qt::StringLiterals;
79
80template <class Iterator>
81class QDirIteratorPrivateIteratorStack : public QStack<Iterator *>
82{
83public:
85 {
86 qDeleteAll(*this);
87 }
88};
89
91{
92public:
94 QDir::Filters _filters, QDirIterator::IteratorFlags flags, bool resolveEngine = true);
95
96 void advance();
97
98 bool entryMatches(const QString & fileName, const QFileInfo &fileInfo);
99 void pushDirectory(const QFileInfo &fileInfo);
100 void checkAndPushDirectory(const QFileInfo &);
101 bool matchesFilters(const QString &fileName, const QFileInfo &fi) const;
102
103 std::unique_ptr<QAbstractFileEngine> engine;
104
107 const QDir::Filters filters;
108 const QDirIterator::IteratorFlags iteratorFlags;
109
110#if QT_CONFIG(regularexpression)
111 QList<QRegularExpression> nameRegExps;
112#endif
113
115#ifndef QT_NO_FILESYSTEMITERATOR
117#endif
118
121
122 // Loop protection
124};
125
130 QDir::Filters _filters, QDirIterator::IteratorFlags flags, bool resolveEngine)
131 : dirEntry(entry)
132 , nameFilters(nameFilters.contains("*"_L1) ? QStringList() : nameFilters)
133 , filters(QDir::NoFilter == _filters ? QDir::AllEntries : _filters)
134 , iteratorFlags(flags)
135{
136#if QT_CONFIG(regularexpression)
137 nameRegExps.reserve(nameFilters.size());
138 for (const auto &filter : nameFilters) {
141 nameRegExps.append(re);
142 }
143#endif
144 QFileSystemMetaData metaData;
145 if (resolveEngine)
147 QFileInfo fileInfo(new QFileInfoPrivate(dirEntry, metaData));
148
149 // Populate fields for hasNext() and next()
150 pushDirectory(fileInfo);
151 advance();
152}
153
158{
159 QString path = fileInfo.filePath();
160
161#ifdef Q_OS_WIN
162 if (fileInfo.isSymLink())
163 path = fileInfo.canonicalFilePath();
164#endif
165
167 // Stop link loops
168 if (visitedLinks.hasSeen(fileInfo.canonicalFilePath()))
169 return;
170 }
171
172 if (engine) {
173 engine->setFileName(path);
175 if (it) {
176 it->setPath(path);
178 } else {
179 // No iterator; no entry list.
180 }
181 } else {
182#ifndef QT_NO_FILESYSTEMITERATOR
186#else
187 qWarning("Qt was built with -no-feature-filesystemiterator: no files/plugins will be found!");
188#endif
189 }
190}
191
192inline bool QDirIteratorPrivate::entryMatches(const QString & fileName, const QFileInfo &fileInfo)
193{
194 checkAndPushDirectory(fileInfo);
195
196 if (matchesFilters(fileName, fileInfo)) {
198 nextFileInfo = fileInfo;
199
200 //We found a matching entry.
201 return true;
202 }
203
204 return false;
205}
206
211{
212 if (engine) {
213 while (!fileEngineIterators.isEmpty()) {
214 // Find the next valid iterator that matches the filters.
216 while (it = fileEngineIterators.top(), it->hasNext()) {
217 it->next();
218 if (entryMatches(it->currentFileName(), it->currentFileInfo()))
219 return;
220 }
221
223 delete it;
224 }
225 } else {
226#ifndef QT_NO_FILESYSTEMITERATOR
227 QFileSystemEntry nextEntry;
228 QFileSystemMetaData nextMetaData;
229
230 while (!nativeIterators.isEmpty()) {
231 // Find the next valid iterator that matches the filters.
233 while (it = nativeIterators.top(), it->advance(nextEntry, nextMetaData)) {
234 QFileInfo info(new QFileInfoPrivate(nextEntry, nextMetaData));
235
236 if (entryMatches(nextEntry.fileName(), info))
237 return;
238 nextMetaData = QFileSystemMetaData();
239 }
240
242 delete it;
243 }
244#endif
245 }
246
249}
250
255{
256 // If we're doing flat iteration, we're done.
258 return;
259
260 // Never follow non-directory entries
261 if (!fileInfo.isDir())
262 return;
263
264 // Follow symlinks only when asked
266 return;
267
268 // Never follow . and ..
269 QString fileName = fileInfo.fileName();
270 if ("."_L1 == fileName || ".."_L1 == fileName)
271 return;
272
273 // No hidden directories unless requested
274 if (!(filters & QDir::AllDirs) && !(filters & QDir::Hidden) && fileInfo.isHidden())
275 return;
276
277 pushDirectory(fileInfo);
278}
279
292{
293 if (fileName.isEmpty())
294 return false;
295
296 // filter . and ..?
297 const qsizetype fileNameSize = fileName.size();
298 const bool dotOrDotDot = fileName[0] == u'.'
299 && ((fileNameSize == 1)
300 ||(fileNameSize == 2 && fileName[1] == u'.'));
301 if ((filters & QDir::NoDot) && dotOrDotDot && fileNameSize == 1)
302 return false;
303 if ((filters & QDir::NoDotDot) && dotOrDotDot && fileNameSize == 2)
304 return false;
305
306 // name filter
307#if QT_CONFIG(regularexpression)
308 // Pass all entries through name filters, except dirs if the AllDirs
309 if (!nameFilters.isEmpty() && !((filters & QDir::AllDirs) && fi.isDir())) {
310 bool matched = false;
311 for (const auto &re : nameRegExps) {
312 if (re.match(fileName).hasMatch()) {
313 matched = true;
314 break;
315 }
316 }
317 if (!matched)
318 return false;
319 }
320#endif
321 // skip symlinks
322 const bool skipSymlinks = filters.testAnyFlag(QDir::NoSymLinks);
323 const bool includeSystem = filters.testAnyFlag(QDir::System);
324 if (skipSymlinks && fi.isSymLink()) {
325 // The only reason to save this file is if it is a broken link and we are requesting system files.
326 if (!includeSystem || fi.exists())
327 return false;
328 }
329
330 // filter hidden
331 const bool includeHidden = filters.testAnyFlag(QDir::Hidden);
332 if (!includeHidden && !dotOrDotDot && fi.isHidden())
333 return false;
334
335 // filter system files
336 if (!includeSystem && (!(fi.isFile() || fi.isDir() || fi.isSymLink())
337 || (!fi.exists() && fi.isSymLink())))
338 return false;
339
340 // skip directories
341 const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
342 if (skipDirs && fi.isDir())
343 return false;
344
345 // skip files
346 const bool skipFiles = !(filters & QDir::Files);
347 if (skipFiles && fi.isFile())
348 // Basically we need a reason not to exclude this file otherwise we just eliminate it.
349 return false;
350
351 // filter permissions
352 const bool filterPermissions = ((filters & QDir::PermissionMask)
354 const bool doWritable = !filterPermissions || (filters & QDir::Writable);
355 const bool doExecutable = !filterPermissions || (filters & QDir::Executable);
356 const bool doReadable = !filterPermissions || (filters & QDir::Readable);
357 if (filterPermissions
358 && ((doReadable && !fi.isReadable())
359 || (doWritable && !fi.isWritable())
360 || (doExecutable && !fi.isExecutable()))) {
361 return false;
362 }
363
364 return true;
365}
366
383{
384 const QDirPrivate *other = dir.d_ptr.constData();
385 d.reset(new QDirIteratorPrivate(other->dirEntry, other->nameFilters, other->filters, flags, bool(other->fileEngine)));
386}
387
401QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
403{
404}
405
420{
421}
422
442 QDir::Filters filters, IteratorFlags flags)
444{
445}
446
451{
452}
453
467{
468 d->advance();
469 return filePath();
470}
471
487{
488 d->advance();
489 return fileInfo();
490}
491
499{
500 if (d->engine)
501 return !d->fileEngineIterators.isEmpty();
502 else
503#ifndef QT_NO_FILESYSTEMITERATOR
504 return !d->nativeIterators.isEmpty();
505#else
506 return false;
507#endif
508}
509
521{
522 return d->currentFileInfo.fileName();
523}
524
531{
532 return d->currentFileInfo.filePath();
533}
534
541{
542 return d->currentFileInfo;
543}
544
549{
550 return d->dirEntry.filePath();
551}
552
The QAbstractFileEngineIterator class provides an iterator interface for custom file engines.
QDirIteratorPrivateIteratorStack< QAbstractFileEngineIterator > fileEngineIterators
void pushDirectory(const QFileInfo &fileInfo)
const QDir::Filters filters
std::unique_ptr< QAbstractFileEngine > engine
const QStringList nameFilters
QDuplicateTracker< QString > visitedLinks
bool entryMatches(const QString &fileName, const QFileInfo &fileInfo)
bool matchesFilters(const QString &fileName, const QFileInfo &fi) const
QFileSystemEntry dirEntry
void checkAndPushDirectory(const QFileInfo &)
QDirIteratorPrivateIteratorStack< QFileSystemIterator > nativeIterators
QDirIteratorPrivate(const QFileSystemEntry &entry, const QStringList &nameFilters, QDir::Filters _filters, QDirIterator::IteratorFlags flags, bool resolveEngine=true)
const QDirIterator::IteratorFlags iteratorFlags
bool hasNext() const
Returns true if there is at least one more entry in the directory; otherwise, false is returned.
QDirIterator(const QDir &dir, IteratorFlags flags=NoIteratorFlags)
Constructs a QDirIterator that can iterate over dir's entrylist, using dir's name filters and regular...
QString fileName() const
Returns the file name for the current directory entry, without the path prepended.
QString next()
Advances the iterator to the next entry, and returns the file path of this new entry.
~QDirIterator()
Destroys the QDirIterator.
QFileInfo fileInfo() const
Returns a QFileInfo for the current directory entry.
QFileInfo nextFileInfo()
QString filePath() const
Returns the full file path for the current directory entry.
QString path() const
Returns the base directory of the iterator.
\inmodule QtCore
Definition qdir.h:19
@ Executable
Definition qdir.h:30
@ CaseSensitive
Definition qdir.h:40
@ Files
Definition qdir.h:22
@ PermissionMask
Definition qdir.h:31
@ Hidden
Definition qdir.h:34
@ AllDirs
Definition qdir.h:39
@ NoSymLinks
Definition qdir.h:24
@ NoDotDot
Definition qdir.h:42
@ Readable
Definition qdir.h:28
@ Writable
Definition qdir.h:29
@ System
Definition qdir.h:35
@ NoDot
Definition qdir.h:41
@ Dirs
Definition qdir.h:21
bool hasSeen(const T &s)
QFileSystemEntry fileEntry
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
bool isSymLink() const
Returns true if this object points to a symbolic link, shortcut, or alias; otherwise returns false.
QString fileName() const
Returns the name of the file, excluding the path.
bool isExecutable() const
Returns true if the file is executable; otherwise returns false.
bool isFile() const
Returns true if this object points to a file or to a symbolic link to a file.
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
QSharedDataPointer< QFileInfoPrivate > d_ptr
Definition qfileinfo.h:171
bool isWritable() const
Returns true if the user can write to the file; otherwise returns false.
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
bool isHidden() const
Returns true if this is a ‘hidden’ file; otherwise returns false.
QString filePath() const
Returns the file name, including the path (which may be absolute or relative).
bool exists() const
Returns true if the file exists; otherwise returns false.
bool isReadable() const
Returns true if the user can read the file; otherwise returns false.
static QAbstractFileEngine * resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry, QFileSystemMetaData &data)
Q_AUTOTEST_EXPORT QString filePath() const
Q_AUTOTEST_EXPORT QString fileName() const
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
static QRegularExpression fromWildcard(QStringView pattern, Qt::CaseSensitivity cs=Qt::CaseInsensitive, WildcardConversionOptions options=DefaultWildcardConversion)
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\inmodule QtCore
Definition qstack.h:13
T & top()
Returns a reference to the stack's top item.
Definition qstack.h:19
T pop()
Removes the top item from the stack and returns it.
Definition qstack.h:18
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition qstring.h:1101
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ CaseInsensitive
@ CaseSensitive
#define qWarning
Definition qlogging.h:162
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLbitfield flags
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint entry
GLsizei const GLchar *const * path
ptrdiff_t qsizetype
Definition qtypes.h:70
QFileInfo info(fileName)
[8]
QFileInfo fi("c:/temp/foo")
[newstuff]
QSharedPointer< T > other(t)
[5]
QString dir
[11]
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]