7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
144#if QT_CONFIG(regularexpression)
145#include <QtCore/qregularexpression.h>
148#include <QtCore/private/qfilesystemiterator_p.h>
149#include <QtCore/private/qfilesystementry_p.h>
150#include <QtCore/private/qfilesystemmetadata_p.h>
151#include <QtCore/private/qfilesystemengine_p.h>
152#include <QtCore/private/qfileinfo_p.h>
153#include <QtCore/private/qduplicatetracker_p.h>
162using namespace Qt::StringLiterals;
171 template <
typename T>
196#if QT_CONFIG(regularexpression)
218#ifndef QT_NO_FILESYSTEMITERATOR
224 {
qWarning(
"Qt was built with -no-feature-filesystemiterator: no files/plugins will be found!"); }
230 bool matchesFilters(
const QFileInfo &fileInfo)
const;
231 bool matchesFilters(
QDirEntryInfo::Iterator &iterator)
const;
232 bool matchesFilters(
const QFileInfo &fileInfo,
const QString &fileName)
const;
238 if (nameFilters.contains(
"*"_L1))
241#if QT_CONFIG(regularexpression)
242 nameRegExps.reserve(size_t(nameFilters.size()));
244 const bool isCase = iteratorFlags.testAnyFlags(QDirListing::IteratorFlag::CaseSensitive);
245 const auto cs = isCase ? Qt::CaseSensitive : Qt::CaseInsensitive;
246 for (
const auto &filter : std::as_const(nameFilters))
247 nameRegExps.emplace_back(QRegularExpression::fromWildcard(filter, cs));
252
253
254
255
256
259 Q_ASSERT(
std::holds_alternative<
QDirEntryInfo::Native>(initialEntryInfo.content));
265 if (
auto engine = QFileSystemEngine::createLegacyEngine(native.entry, native.metaData))
266 data.emplace<EngineData>(std::move(engine));
268 data.emplace<NativeData>();
275 const bool followSymlinks =
276 iteratorFlags.testAnyFlags(QDirListing::IteratorFlag::FollowDirSymlinks);
278 if (
auto *d = std::get_if<EngineData>(&data)) {
279 const QString path = [&entryInfo] {
281 if (entryInfo.isSymLink())
282 return entryInfo.canonicalFilePath();
284 return entryInfo.filePath();
288 if (followSymlinks && d->visitedLinks.hasSeen(entryInfo.canonicalFilePath()))
292 if (entryInfo.isJunction() && d->visitedLinks.hasSeen(entryInfo.junctionTarget()))
296 d->engine->setFileName(path);
297 if (
auto it = d->engine->beginEntryList(path, iteratorFlags, nameFilters)) {
298 d->iterators.push(
std::move(it));
304#ifndef QT_NO_FILESYSTEMITERATOR
310 auto it = std::make_unique<QFileSystemIterator>(native->entry, iteratorFlags);
313 if (followSymlinks) {
314 QFileSystemNativeId id = it->nativeId();
315 if (id.isValid() && d->visitedLinks.hasSeen(id))
320 if (entryInfo.isJunction()) {
321 QFileSystemNativeId id = it->nativeId();
322 if (id.isValid() && d->visitedLinks.hasSeen(id))
327 d->iterators.push(
std::move(it));
339
340
341
342
343
344
345
346
347
348
349
350
351
354 if (
auto *d = std::get_if<EngineData>(&data)) {
355 while (!d->iterators.empty()) {
358 while (d->iterators.top()->advance()) {
361 currentEntryInfo = std::move(entryInfo);
370#ifndef QT_NO_FILESYSTEMITERATOR
371 while (!d->iterators.empty()) {
374 while (std::optional r = d->iterators.top()->advance()) {
376 currentEntryInfo = std::move(*r);
389 return fileName ==
"."_L1 || fileName ==
".."_L1;
394 using F = QDirListing::IteratorFlag;
396 if (!iteratorFlags.testAnyFlags(F::Recursive))
400 if (!iteratorFlags.testAnyFlags(F::FollowDirSymlinks) && entryInfo.isSymLink())
404 if (isDotOrDotDot(entryInfo.fileName()))
408 const bool includeHidden = iteratorFlags.testAnyFlags(QDirListing::IteratorFlag::IncludeHidden);
421 using F = QDirListing::IteratorFlag;
422 using M = QFileSystemMetaData;
424 const QString fileName = native.entry.fileName();
425 if (fileName.isEmpty())
429#if QT_CONFIG(regularexpression)
430 const bool skipNameFilters = iteratorFlags.testAnyFlags(F::NoNameFiltersForDirs)
431 && native.ensureFilled(M::DirectoryType).isDirectory();
432 if (!skipNameFilters) {
433 if (!regexMatchesName(fileName))
438 if (isDotOrDotDot(fileName))
439 return iteratorFlags.testFlags(F::IncludeDotAndDotDot);
441 if (!iteratorFlags.testAnyFlag(F::IncludeHidden)
442 && native.ensureFilled(M::HiddenAttribute).isHidden()) {
446 if (iteratorFlags.testAnyFlags(F::IncludeBrokenSymlinks)
447 && native.ensureFilled(M::LegacyLinkType).isLegacyLink()
448 && !native.ensureFilled(M::ExistsAttribute).exists()) {
452 if (iteratorFlags.testFlag(F::ResolveSymlinks)) {
453 if (native.ensureFilled(M::LegacyLinkType).isLegacyLink()
454 && !native.ensureFilled(M::ExistsAttribute).exists()) {
458 constexpr auto f = F::ExcludeFiles | F::ExcludeDirs | F::ExcludeOther;
459 const bool filterByTargetType = iteratorFlags.testAnyFlags(f);
460 if (filterByTargetType && native.ensureFilled(M::LegacyLinkType).isLegacyLink())
464 if (iteratorFlags.testAnyFlag(F::ExcludeOther)
465 && !native.ensureFilled(M::FileType).isFile()
466 && !native.ensureFilled(M::DirectoryType).isDirectory()
467 && !native.ensureFilled(M::LegacyLinkType).isLegacyLink()) {
471 if (iteratorFlags.testAnyFlags(F::ExcludeDirs)
472 && native.ensureFilled(M::DirectoryType).isDirectory()) {
476 if (iteratorFlags.testAnyFlags(F::ExcludeFiles) && native.ensureFilled(M::FileType).isFile())
482bool QDirListingPrivate::matchesFilters(
const QFileInfo &fileInfo,
const QString &fileName)
const
484 using F = QDirListing::IteratorFlag;
486 Q_ASSERT(!fileName.isEmpty());
489#if QT_CONFIG(regularexpression)
490 const bool skipNameFilters = iteratorFlags.testFlag(F::NoNameFiltersForDirs)
492 if (!skipNameFilters) {
493 if (!regexMatchesName(fileName))
498 if (isDotOrDotDot(fileName))
499 return iteratorFlags.testFlag(F::IncludeDotAndDotDot);
501 if (!iteratorFlags.testFlag(F::IncludeHidden) && fileInfo.isHidden())
504 const bool includeBrokenSymlinks = iteratorFlags.testAnyFlags(F::IncludeBrokenSymlinks);
505 if (includeBrokenSymlinks && fileInfo.isSymLink() && !fileInfo.exists())
508 if (iteratorFlags.testFlag(F::ResolveSymlinks)) {
509 if (fileInfo.isSymLink() && !fileInfo.exists())
512 constexpr auto f = F::ExcludeFiles | F::ExcludeDirs | F::ExcludeOther;
513 const bool filterByTargetType = iteratorFlags.testAnyFlags(f);
514 if (filterByTargetType && fileInfo.isSymLink())
518 if (iteratorFlags.testFlag(F::ExcludeOther)
519 && !fileInfo.isFile() && !fileInfo.isDir() && !fileInfo.isSymLink()) {
523 if (iteratorFlags.testFlag(F::ExcludeDirs) && fileInfo.isDir())
526 if (iteratorFlags.testFlag(F::ExcludeFiles) && fileInfo.isFile())
534 using F = QDirListing::IteratorFlag;
536 const QString fileName = iterator.iterator->currentFileName();
537 if (fileName.isEmpty())
541 if (iteratorFlags.testFlag(F::IncludeHidden)
542 && !iteratorFlags.testAnyFlags(
543 F::NoNameFiltersForDirs |
544 F::IncludeBrokenSymlinks |
550#if QT_CONFIG(regularexpression)
551 if (!regexMatchesName(fileName))
554 if (isDotOrDotDot(fileName))
555 return iteratorFlags.testFlags(F::IncludeDotAndDotDot);
561 return matchesFilters(iterator.ensureFileInfo(), fileName);
566 const QString fileName = fileInfo.fileName();
567 return !fileName.isEmpty() && matchesFilters(fileInfo, fileName);
571
572
573
574
575
576
579 return std::visit([
this](
auto &e) {
return matchesFilters(e); },
585 if (
auto *d = std::get_if<EngineData>(&data))
586 return !d->iterators.empty();
588#if !defined(QT_NO_FILESYSTEMITERATOR)
589 if (
auto *d = std::get_if<NativeData>(&data))
590 return !d->iterators.empty();
597
598
599
600
601
602
603
604
605
609 d->initialEntryInfo.content = QDirEntryInfo::Native { QFileSystemEntry(path), {} };
610 d->iteratorFlags = flags;
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637QDirListing::QDirListing(
const QString &path,
const QStringList &nameFilters, IteratorFlags flags)
640 d->initialEntryInfo.content = QDirEntryInfo::Native { QFileSystemEntry(path), {} };
641 d->nameFilters = nameFilters;
642 d->iteratorFlags = flags;
647
648
649
650
651
652
653
654
655
656
659
660
661
662
663
664
667
668
675
676
679 return d->initialEntryInfo.filePath();
683
684
687 return d->iteratorFlags;
691
692
693
696 return d->nameFilters;
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
729
730
731
732
735
736
737
738
741
742
743
744
745
746
747
748
749
750
751
752
753
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
795
796
797
798
799
802
803
804
805
806
809
810
811
812
813
816
817
818
819
820
821
822
823
824
825
826
827
828
829
832
833
834
835
836
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
896 return dirListPtr->currentEntryInfo.fileInfo();
901 return dirListPtr->currentEntryInfo.fileName();
906 return dirListPtr->currentEntryInfo.baseName();
911 return dirListPtr->currentEntryInfo.completeBaseName();
916 return dirListPtr->currentEntryInfo.suffix();
921 return dirListPtr->currentEntryInfo.bundleName();
926 return dirListPtr->currentEntryInfo.completeSuffix();
931 return dirListPtr->currentEntryInfo.filePath();
936 return dirListPtr->currentEntryInfo.canonicalFilePath();
941 return dirListPtr->currentEntryInfo.absoluteFilePath();
946 return dirListPtr->currentEntryInfo.absolutePath();
951 return dirListPtr->currentEntryInfo.isDir();
956 return dirListPtr->currentEntryInfo.isFile();
961 return dirListPtr->currentEntryInfo.isSymLink();
966 return dirListPtr->currentEntryInfo.exists();
971 return dirListPtr->currentEntryInfo.isHidden();
976 return dirListPtr->currentEntryInfo.isReadable();
981 return dirListPtr->currentEntryInfo.isWritable();
986 return dirListPtr->currentEntryInfo.isExecutable();
991 return dirListPtr->currentEntryInfo.size();
996 return dirListPtr->currentEntryInfo.fileTime(type, tz);
bool entryMatches(QDirEntryInfo &info)
QDirListing::IteratorFlags iteratorFlags
void pushInitialDirectory()
std::variant< std::monostate, EngineData, NativeData > data
void checkAndPushDirectory(QDirEntryInfo &info)
bool hasIterators() const
bool matchesFilters(QDirEntryInfo &data) const
QDirEntryInfo initialEntryInfo
QDirEntryInfo currentEntryInfo
void pushDirectory(QDirEntryInfo &info)
Q_CORE_EXPORT bool isReadable() const
Q_CORE_EXPORT bool isHidden() const
Q_CORE_EXPORT bool isWritable() const
Q_CORE_EXPORT bool isExecutable() const
Q_CORE_EXPORT bool isFile() const
Q_CORE_EXPORT bool exists() const
Q_CORE_EXPORT bool isSymLink() const
Q_CORE_EXPORT bool isDir() const
const_iterator & operator++()
Pre-increment operator.
static bool isDotOrDotDot(QStringView fileName)
vector_stack< FEngineIteratorPtr > iterators
QDuplicateTracker< QString > visitedLinks
std::unique_ptr< QAbstractFileEngine > engine
EngineData(std::unique_ptr< QAbstractFileEngine > engine) noexcept
vector_stack< FsIteratorPtr > iterators
QDuplicateTracker< QFileSystemNativeId > visitedLinks