diff options
| author | Ahmad Samir <a.samirh78@gmail.com> | 2025-07-19 16:44:28 +0300 |
|---|---|---|
| committer | Ahmad Samir <a.samirh78@gmail.com> | 2025-08-09 19:42:51 +0300 |
| commit | f180f89ce1de526e3462b0a7b4e4f13d006115ec (patch) | |
| tree | 4fc0cdb8e2d4276c060b0b934ded51539fc3e511 /src | |
| parent | 3cf10c70d9a8a48270777e8ce9b6352d2e454cc3 (diff) | |
QDirListing: port away from private QDirListing ctor, [1]: QDir
Convert the values of a QDir::Filters that can be represented by
QDirListing::IteratorFlags, and check the rest of the filters separately
in QDir.
Change-Id: Ib3cc8b04a2903111cf863b07d239d5a02f8397ca
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/corelib/io/qdir.cpp | 120 | ||||
| -rw-r--r-- | src/corelib/io/qdir_p.h | 8 | ||||
| -rw-r--r-- | src/corelib/io/qdirlisting.cpp | 10 | ||||
| -rw-r--r-- | src/corelib/io/qdirlisting.h | 3 |
4 files changed, 127 insertions, 14 deletions
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index caf8dac464b..577de7bfe1b 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -353,20 +353,113 @@ inline void QDirPrivate::sortFileList(QDir::SortFlags sort, const QFileInfoList } } +#ifndef QT_BOOTSTRAPPED +/*! \internal + + Returns \c true if the permissions flags set in \a filters match the + permissions of \a fileInfo; otherwise returns \c false. + + If there are no permissions set in \a filters this method returns \c true. +*/ +static bool checkPermissions(const QDirListing::DirEntry &dirEntry, QDir::Filters filters) +{ + const auto perms = filters & QDir::PermissionMask; + const bool filterByPermissions = perms != 0 && perms != QDir::PermissionMask; + if (filterByPermissions) { + const QFileInfo fileInfo = dirEntry.fileInfo(); + if (filters.testFlags(QDir::Readable) && !fileInfo.isReadable()) + return false; + if (filters.testFlags(QDir::Writable) && !fileInfo.isWritable()) + return false; + if (filters.testFlags(QDir::Executable) && !fileInfo.isExecutable()) + return false; + } + return true; +} + +static bool checkDotOrDotDot(const QDirListing::DirEntry &dirEntry, QDir::Filters filters) +{ + const QString fileName = dirEntry.fileName(); + if ((filters & QDir::NoDot) && fileName == u".") + return false; + if ((filters & QDir::NoDotDot) && fileName == u"..") + return false; + return true; +} + +bool QDirPrivate::checkNonDirListingFlags(const QDirListing::DirEntry &dirEntry, + QDir::Filters filters) +{ + return checkPermissions(dirEntry, filters) && checkDotOrDotDot(dirEntry, filters); +} + +static void appendIfMatchesNonDirListingFlags(const QDirListing::DirEntry &dirEntry, + QDir::Filters filters, QFileInfoList &l) +{ + if (QDirPrivate::checkNonDirListingFlags(dirEntry, filters)) + l.emplace_back(dirEntry.fileInfo()); +} + +/*! \internal + + Returns a set of QDirListing::IteratorFlags representing the flags in \a filters + that can be represented by QDirListing::IteratorFlags. + + Note that not all QDir::Filter values are supported, some flags have to be checked + separately (see checkNonDirListingFlags()). +*/ +QDirListing::IteratorFlags QDirPrivate::toDirListingFlags(QDir::Filters filters) +{ + if (filters == QDir::NoFilter) + filters = QDir::AllEntries; + + using F = QDirListing::IteratorFlag; + QDirListing::IteratorFlags flags; + if (!(filters & QDir::Dirs) && !(filters & QDir::AllDirs)) + flags |= F::ExcludeDirs; + if (!(filters & QDir::Files)) + flags |= F::ExcludeFiles; + if (!(filters & QDir::NoSymLinks)) + flags |= F::ResolveSymlinks; + if (filters & QDir::Hidden) + flags |= F::IncludeHidden; + + if (!(filters & QDir::System)) + flags |= F::ExcludeOther; + else + flags |= F::IncludeBrokenSymlinks; // QDir::System lists broken symlinks... + + + if (filters & QDir::AllDirs) + flags |= F::NoNameFiltersForDirs; + if (filters & QDir::CaseSensitive) + flags |= F::CaseSensitive; + + // QDir::Filter has NoDot and NoDotDot; QDirListing has only one, + // F::IncludeDotAndDotDot. If either of the QDir::Filter values are + // not set, list both and use checkDotOrDotDot() to filter it later. + if (!(filters & QDir::NoDot) || !(filters & QDir::NoDotDot)) { + if (!(flags & F::ExcludeDirs)) // treat '.' and '..' as dirs + flags |= F::IncludeDotAndDotDot; + } + + return flags; +} + inline void QDirPrivate::initFileLists(const QDir &dir) const { QMutexLocker locker(&fileCache.mutex); if (!fileCache.fileListsInitialized) { QFileInfoList l; - for (const auto &dirEntry : QDirListing(dir.path(), dir.nameFilters(), - dir.filter().toInt())) { - l.emplace_back(dirEntry.fileInfo()); - } + QDirListing::IteratorFlags flags = toDirListingFlags(dir.filter()); + for (const auto &dirEntry : QDirListing(dir.path(), dir.nameFilters(), flags)) + appendIfMatchesNonDirListingFlags(dirEntry, dir.filter(), l); sortFileList(sort, l, &fileCache.files, &fileCache.fileInfos); fileCache.fileListsInitialized = true; } } +#endif // !QT_BOOTSTRAPPED inline void QDirPrivate::clearCache(MetaDataClearing mode) { @@ -1439,12 +1532,13 @@ QStringList QDir::entryList(const QStringList &nameFilters, Filters filters, } } - QDirListing dirList(d->dirEntry.filePath(), nameFilters, filters.toInt()); + QDirListing::IteratorFlags flags = QDirPrivate::toDirListingFlags(filters); + QDirListing dirList(d->dirEntry.filePath(), nameFilters, flags); QStringList ret; if (needsSorting) { QFileInfoList l; for (const auto &dirEntry : dirList) - l.emplace_back(dirEntry.fileInfo()); + appendIfMatchesNonDirListingFlags(dirEntry, filters, l); d->sortFileList(sort, l, &ret, nullptr); } else { for (const auto &dirEntry : dirList) @@ -1485,8 +1579,9 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter } QFileInfoList l; - for (const auto &dirEntry : QDirListing(d->dirEntry.filePath(), nameFilters, filters.toInt())) - l.emplace_back(dirEntry.fileInfo()); + const QDirListing::IteratorFlags flags = QDirPrivate::toDirListingFlags(filters); + for (const auto &dirEntry : QDirListing(d->dirEntry.filePath(), nameFilters, flags)) + appendIfMatchesNonDirListingFlags(dirEntry, filters, l); QFileInfoList ret; d->sortFileList(sort, l, nullptr, &ret); return ret; @@ -1989,8 +2084,13 @@ bool QDir::exists(const QString &name) const bool QDir::isEmpty(Filters filters) const { Q_D(const QDir); - QDirListing dirList(d->dirEntry.filePath(), d->nameFilters, filters.toInt()); - return dirList.cbegin() == dirList.cend(); + + QDirListing::IteratorFlags flags = QDirPrivate::toDirListingFlags(filters); + for (const auto &dirEntry : QDirListing(d->dirEntry.filePath(), d->nameFilters, flags)) { + if (QDirPrivate::checkNonDirListingFlags(dirEntry, filters)) + return false; + } + return true; } #endif // !QT_BOOTSTRAPPED diff --git a/src/corelib/io/qdir_p.h b/src/corelib/io/qdir_p.h index ad2b9bf925c..dc0756d2ec3 100644 --- a/src/corelib/io/qdir_p.h +++ b/src/corelib/io/qdir_p.h @@ -16,6 +16,7 @@ // We mean it. // +#include "qdirlisting.h" #include "qfilesystementry_p.h" #include "qfilesystemmetadata_p.h" @@ -44,7 +45,13 @@ public: bool exists() const; +#ifndef QT_BOOTSTRAPPED + static QDirListing::IteratorFlags toDirListingFlags(QDir::Filters filters); + static bool checkNonDirListingFlags(const QDirListing::DirEntry &dirEntry, + QDir::Filters filters); + void initFileLists(const QDir &dir) const; +#endif // !QT_BOOTSTRAPPED static void sortFileList(QDir::SortFlags, const QFileInfoList &, QStringList *, QFileInfoList *); @@ -52,6 +59,7 @@ public: static inline QStringList splitFilters(const QString &nameFilter, QChar sep = {}); + void setPath(const QString &path); enum MetaDataClearing { KeepMetaData, IncludingMetaData }; diff --git a/src/corelib/io/qdirlisting.cpp b/src/corelib/io/qdirlisting.cpp index 363f028cb62..95d8e1fab61 100644 --- a/src/corelib/io/qdirlisting.cpp +++ b/src/corelib/io/qdirlisting.cpp @@ -129,6 +129,8 @@ When combined with Recursive, symbolic links to directories will be iterated too. Symbolic link loops (e.g., link => . or link => ..) are automatically detected and ignored. + + \omitvalue NoNameFiltersForDirs */ #include "qdirlisting.h" @@ -507,8 +509,12 @@ bool QDirListingPrivate::matchesFilters(QDirEntryInfo &entryInfo) const // name filter #if QT_CONFIG(regularexpression) - if (!regexMatchesName(fileName)) - return false; + const bool skipNameFilters = iteratorFlags.testAnyFlags(F::NoNameFiltersForDirs) + && entryInfo.isDir(); + if (!skipNameFilters) { + if (!regexMatchesName(fileName)) + return false; + } #endif // QT_CONFIG(regularexpression) if (isDotOrDotDot(fileName)) diff --git a/src/corelib/io/qdirlisting.h b/src/corelib/io/qdirlisting.h index acd240b81f7..5f807561ee3 100644 --- a/src/corelib/io/qdirlisting.h +++ b/src/corelib/io/qdirlisting.h @@ -43,6 +43,7 @@ public: Recursive = 0x000400, FollowDirSymlinks = 0x000800, IncludeBrokenSymlinks = 0x001000, + NoNameFiltersForDirs = 0x040000, // used internally }; Q_DECLARE_FLAGS(IteratorFlags, IteratorFlag) @@ -162,8 +163,6 @@ private: uint qdirIteratorFlags = 0); // QDirIterator::NoIteratorFlags == 0x0 QDirListingPrivate *d; - friend class QDir; - friend class QDirPrivate; friend class QDirIteratorPrivate; friend class QAbstractFileEngine; friend class QFileInfoGatherer; |
