Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdirentryinfo_p.h
Go to the documentation of this file.
1// Copyright (C) 2024 Ahmad Samir <a.samirh78@gmail.com>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QDIRENTRYINFO_P_H
6#define QDIRENTRYINFO_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/qassert.h>
20#include <QtCore/private/qfileinfo_p.h>
21#include <QtCore/private/qfilesystementry_p.h>
22#include <QtCore/private/qfilesystemmetadata_p.h>
23
24#include <type_traits>
25#include <QtCore/q23utility.h>
26#include <variant>
27
28QT_BEGIN_NAMESPACE
29
31template<class... Ts>
32struct overloaded : Ts... { using Ts::operator()...; };
33template<class... Ts>
34overloaded(Ts...) -> overloaded<Ts...>;
35
36template <typename T, typename Variant, typename...Args>
37T &emplace(Variant &v, Args&&...args)
38{
39#if !defined(Q_OS_VXWORKS) /* lacks LWG 2857 resolution */
40 && !defined(Q_CC_COVERITY) /* would report "structurally dead code" */
41 /* end */
42 return
43#endif
44 v.template emplace<T>(std::forward<Args>(args)...);
45 return *std::get_if<T>(&v);
46}
47
48//
49// Reimplementation of std::visit() to fight Coverity's UNCAUGHT_EXCEPTION
50//
51// This version never throws std::bad_variant_access (unless thrown by the
52// visitor), but Q_UNREACHABLE()s the valueless_by_exception() case. It should
53// otherwise be identical to std::visit(), incl. the O(1) access.
54//
55// Known limitations:
56// - at most three alternatives are supported (but more can be trivially added)
57// - only one variant is supported (unary visitor; binary visitation isn't)
58// - only works for "raw" std::variant, not "anything inheriting std::variant"
59//
60template <typename Visitor, typename Variant>
61constexpr decltype(auto) visit(Visitor &&vis, Variant &&var)
62{
63 using V = std::remove_reference_t<Variant>;
64 constexpr auto NumAlternatives = std::variant_size_v<V>;
65 switch (var.index()) {
66 #define QT_VARIANT_VISIT_CASE(num)
67 case num:
68 if constexpr (NumAlternatives > num) {
69 const auto p = std::get_if<num>(&var);
70 return std::forward<Visitor>(vis)(q23::forward_like<Variant>(*p));
71 }
72 break
73 /* end */
77 static_assert(NumAlternatives <= 3, "### extend this switch if you need more");
78 #undef QT_VARIANT_VISIT_CASE
79 }
80 Q_UNREACHABLE();
81}
82
83} // namespace QDirEntryInfoPrivate
84
86{
87 template<typename QueryNative, typename QueryFileInfo, typename QueryIterator>
88 decltype(auto) visit(QueryNative qn, QueryFileInfo qf, QueryIterator qi)
89 {
90 auto visitor = QDirEntryInfoPrivate::overloaded{std::move(qn), std::move(qf), std::move(qi)};
91 return QDirEntryInfoPrivate::visit(std::move(visitor), content);
92 }
93 template<typename QueryNative, typename QueryFileInfo, typename QueryIterator>
94 auto query(
95 QueryNative &&queryNative, QueryFileInfo &&queryFileInfo, QueryIterator &&queryIterator)
96 {
97 return visit(
98 std::forward<QueryNative>(queryNative),
99 std::forward<QueryFileInfo>(queryFileInfo),
100 [&](const Iterator &iterator) { return queryIterator(iterator.iterator); }
101 );
102 }
103
104 template<typename QueryNative, typename QueryFileInfo>
105 auto query(QueryNative &&queryNative, const QueryFileInfo &queryFileInfo)
106 {
107 return visit(
108 std::forward<QueryNative>(queryNative),
109 [&](Iterator &iterator) { return queryFileInfo(iterator.ensureFileInfo()); },
110 queryFileInfo
111 );
112 }
113
114public:
115 QDirEntryInfo() = default;
116
117 explicit QDirEntryInfo(const QAbstractFileEngineIterator *iterator)
118 : content(Iterator {iterator, {}})
119 {
120 }
121
122 explicit QDirEntryInfo(QFileSystemEntry &&e, QFileSystemMetaData &&md)
123 : content(Native { std::move(e), std::move(md) })
124 {
125 }
126
127 explicit QDirEntryInfo(QFileInfo &&info)
128 : content(std::move(info))
129 {
130 }
131
132 const QFileInfo &fileInfo()
133 {
134 return visit(
135 [](Iterator &iterator) -> const QFileInfo & { return iterator.ensureFileInfo(); },
136 [this](const Native &native) -> const QFileInfo & {
137 return QDirEntryInfoPrivate::emplace<QFileInfo>(content,
138 new QFileInfoPrivate(native.entry, native.metaData));
139 },
140 [](const QFileInfo &fileInfo) -> const QFileInfo & { return fileInfo; }
141 );
142 }
143
145 {
146 return query(
147 [](const Native &native) { return native.entry.fileName(); },
148 [](const QFileInfo &info) { return info.fileName(); },
149 [](const QAbstractFileEngineIterator *it) { return it->currentFileName(); });
150 }
151
153 {
154 return query(
155 [](const Native &native) { return native.entry.baseName(); },
156 [](const QFileInfo &info) { return info.baseName(); });
157 }
158
160 {
161 return query(
162 [](const Native &native) { return native.entry.completeBaseName(); },
163 [](const QFileInfo &info) { return info.completeBaseName(); });
164 }
165
167 {
168 return query(
169 [](const Native &native) { return native.entry.suffix(); },
170 [](const QFileInfo &info) { return info.suffix(); });
171 }
172
174 {
175 return query(
176 [](const Native &native) { return native.entry.completeSuffix(); },
177 [](const QFileInfo &info) { return info.completeSuffix(); });
178 }
179
181 {
182 return query(
183 [](const Native &native) { return native.entry.filePath(); },
184 [](const QFileInfo &info) { return info.filePath(); },
185 [](const QAbstractFileEngineIterator *it) { return it->currentFilePath(); });
186 }
187
188 QString bundleName() { return fileInfo().bundleName(); }
189
191 {
192 // QFileInfo caches these strings
193 return fileInfo().canonicalFilePath();
194 }
195
197 // QFileInfo caches these strings
198 return fileInfo().absoluteFilePath();
199 }
200
202 // QFileInfo caches these strings
203 return fileInfo().absolutePath();
204 }
205
206
207 bool isDir() {
208 return query(
209 [](Native &native) {
210 return native.ensureFilled(QFileSystemMetaData::DirectoryType).isDirectory();
211 },
212 [](const QFileInfo &fileInfo) {return fileInfo.isDir(); });
213 }
214
215 bool isFile() {
216 return query(
217 [](Native &native) {
218 return native.ensureFilled(QFileSystemMetaData::FileType).isFile();
219 },
220 [](const QFileInfo &fileInfo) {return fileInfo.isFile(); });
221 }
222
223 bool isSymLink() {
224 return query(
225 [](Native &native) {
226 return native.ensureFilled(QFileSystemMetaData::LegacyLinkType).isLegacyLink();
227 },
228 [](const QFileInfo &fileInfo) {return fileInfo.isSymLink(); });
229 }
230
232 return query(
233 [](Native &native) {
234 return native.ensureFilled(QFileSystemMetaData::LinkType).isLink();
235 },
236 [](const QFileInfo &fileInfo) {return fileInfo.isSymbolicLink(); });
237 }
238
239 bool exists() {
240 return query(
241 [](Native &native) {
242 return native.ensureFilled(QFileSystemMetaData::ExistsAttribute).exists();
243 },
244 [](const QFileInfo &fileInfo) {return fileInfo.exists(); });
245 }
246
247 bool isHidden() {
248 return query(
249 [](Native &native) {
250 return native.ensureFilled(QFileSystemMetaData::HiddenAttribute).isHidden();
251 },
252 [](const QFileInfo &fileInfo) {return fileInfo.isHidden(); });
253 }
254
255 bool isReadable() {
256 return query(
257 [](Native &native) {
258 return native.ensureFilled(QFileSystemMetaData::UserReadPermission).isReadable();
259 },
260 [](const QFileInfo &fileInfo) {return fileInfo.isReadable(); });
261 }
262
263 bool isWritable() {
264 return query(
265 [](Native &native) {
266 return native.ensureFilled(QFileSystemMetaData::UserWritePermission).isWritable();
267 },
268 [](const QFileInfo &fileInfo) {return fileInfo.isWritable(); });
269 }
270
272 return query(
273 [](Native &native) {
274 return native.ensureFilled(QFileSystemMetaData::UserExecutePermission)
275 .isExecutable();
276 },
277 [](const QFileInfo &fileInfo) {return fileInfo.isExecutable(); });
278 }
279
280 qint64 size() { return fileInfo().size(); }
281
282 QDateTime fileTime(QFile::FileTime type, const QTimeZone &tz)
283 {
284 return fileInfo().fileTime(type, tz);
285 }
286
287private:
288 friend class QDirListingPrivate;
289 friend class QDirListing;
290 friend class QFileSystemIterator;
292
293 struct Iterator
294 {
295 // The data we can query from both the QFileInfo and the iterator is cheaper to retrieve
296 // from the iterator. Therefore, keep the iterator around even if we create a the QFileInfo.
297 const QAbstractFileEngineIterator *iterator = nullptr;
298 std::optional<QFileInfo> fileInfo;
299
300 const QFileInfo &ensureFileInfo()
301 {
302 if (!fileInfo.has_value())
303 fileInfo = iterator->currentFileInfo();
304 return *fileInfo;
305 }
306 };
307
308 struct Native
309 {
310 QFileSystemEntry entry;
311 QFileSystemMetaData metaData;
312
313 const QFileSystemMetaData &ensureFilled(QFileSystemMetaData::MetaDataFlag what)
314 {
315 if (!metaData.hasFlags(what))
316 QFileSystemEngine::fillMetaData(entry, metaData, what);
317 return metaData;
318 }
319 };
320
321 std::variant<Native, QFileInfo, Iterator> content;
322};
323
324QT_END_NAMESPACE
325
326#endif // QDIRENTRYINFO_P_H
QDirEntryInfo(QFileSystemEntry &&e, QFileSystemMetaData &&md)
const QFileInfo & fileInfo()
QString absoluteFilePath()
QString canonicalFilePath()
QString completeSuffix()
QDateTime fileTime(QFile::FileTime type, const QTimeZone &tz)
QDirEntryInfo(QFileInfo &&info)
QDirEntryInfo()=default
QDirEntryInfo(const QAbstractFileEngineIterator *iterator)
QString completeBaseName()
QString bundleName()
QString absolutePath()
QDirIteratorPrivate(const QString &path, const QStringList &nameFilters={}, QDir::Filters dirFilters=QDir::NoFilter, QDirIterator::IteratorFlags flags=QDirIterator::NoIteratorFlags)
QDir::Filters filters
void skipToNextMatch(QDirListing::const_iterator &iter)
QDirListing::const_iterator it
The QDirIterator class provides an iterator for directory entrylists.
\inmodule QtCore
Definition qdirlisting.h:71
reference operator*() const
Returns a {const QDirListing::DirEntry &} of the directory entry this iterator points to.
const_iterator & operator++()
Pre-increment operator.
constexpr decltype(auto) visit(Visitor &&vis, Variant &&var)
T & emplace(Variant &v, Args &&...args)
overloaded(Ts...) -> overloaded< Ts... >
#define QT_VARIANT_VISIT_CASE(num)
static QDirListing::IteratorFlags toDirListingFlags(QDir::Filters filters, QDirIterator::IteratorFlags flags)