Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qfilesystementry.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
5
6#include <QtCore/qdir.h>
7#include <QtCore/qfile.h>
8#include <QtCore/private/qfsfileengine_p.h>
9#ifdef Q_OS_WIN
10#include <QtCore/qstringbuilder.h>
11#endif
12
14
15using namespace Qt::StringLiterals;
16
17#ifdef Q_OS_WIN
18static bool isUncRoot(const QString &server)
19{
21 if (!localPath.startsWith("\\\\"_L1))
22 return false;
23
24 int idx = localPath.indexOf(u'\\', 2);
25 if (idx == -1 || idx + 1 == localPath.length())
26 return true;
27
28 return QStringView{localPath}.right(localPath.length() - idx - 1).trimmed().isEmpty();
29}
30
31static inline QString fixIfRelativeUncPath(const QString &path)
32{
33 QString currentPath = QDir::currentPath();
34 if (currentPath.startsWith("//"_L1))
35 return currentPath % QChar(u'/') % path;
36 return path;
37}
38#endif
39
41 : m_lastSeparator(-1),
42 m_firstDotInFileName(-1),
43 m_lastDotInFileName(-1)
44{
45}
46
53 : m_filePath(QDir::fromNativeSeparators(filePath)),
54 m_lastSeparator(-2),
55 m_firstDotInFileName(-2),
56 m_lastDotInFileName(0)
57{
58}
59
66 : m_filePath(filePath),
67 m_lastSeparator(-2),
68 m_firstDotInFileName(-2),
69 m_lastDotInFileName(0)
70{
71}
72
78 : m_nativeFilePath(nativeFilePath),
79 m_lastSeparator(-2),
80 m_firstDotInFileName(-2),
81 m_lastDotInFileName(0)
82{
83}
84
85QFileSystemEntry::QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath)
86 : m_filePath(QDir::fromNativeSeparators(filePath)),
87 m_nativeFilePath(nativeFilePath),
88 m_lastSeparator(-2),
89 m_firstDotInFileName(-2),
90 m_lastDotInFileName(0)
91{
92}
93
95{
96 resolveFilePath();
97 return m_filePath;
98}
99
101{
102 resolveNativeFilePath();
103 return m_nativeFilePath;
104}
105
106void QFileSystemEntry::resolveFilePath() const
107{
108 if (m_filePath.isEmpty() && !m_nativeFilePath.isEmpty()) {
109#ifdef Q_OS_WIN
110 m_filePath = QDir::fromNativeSeparators(m_nativeFilePath);
111#else
112 m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath));
113#endif
114 }
115}
116
117void QFileSystemEntry::resolveNativeFilePath() const
118{
119 if (!m_filePath.isEmpty() && m_nativeFilePath.isEmpty()) {
120#ifdef Q_OS_WIN
121 QString filePath = m_filePath;
122 if (isRelative())
123 filePath = fixIfRelativeUncPath(m_filePath);
124 m_nativeFilePath = QFSFileEnginePrivate::longFileName(QDir::toNativeSeparators(filePath));
125#else
126 m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath));
127#endif
128 }
129}
130
132{
133 findLastSeparator();
134#if defined(Q_OS_WIN)
135 if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
136 return m_filePath.mid(2);
137#endif
138 return m_filePath.mid(m_lastSeparator + 1);
139}
140
142{
143 findLastSeparator();
144 if (m_lastSeparator == -1) {
145#if defined(Q_OS_WIN)
146 if (m_filePath.length() >= 2 && m_filePath.at(1) == u':')
147 return m_filePath.left(2);
148#endif
149 return QString(u'.');
150 }
151 if (m_lastSeparator == 0)
152 return QString(u'/');
153#if defined(Q_OS_WIN)
154 if (m_lastSeparator == 2 && m_filePath.at(1) == u':')
155 return m_filePath.left(m_lastSeparator + 1);
156#endif
157 return m_filePath.left(m_lastSeparator);
158}
159
161{
162 findFileNameSeparators();
163 int length = -1;
164 if (m_firstDotInFileName >= 0) {
165 length = m_firstDotInFileName;
166 if (m_lastSeparator != -1) // avoid off by one
167 length--;
168 }
169#if defined(Q_OS_WIN)
170 if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
171 return m_filePath.mid(2, length - 2);
172#endif
173 return m_filePath.mid(m_lastSeparator + 1, length);
174}
175
177{
178 findFileNameSeparators();
179 int length = -1;
180 if (m_firstDotInFileName >= 0) {
181 length = m_firstDotInFileName + m_lastDotInFileName;
182 if (m_lastSeparator != -1) // avoid off by one
183 length--;
184 }
185#if defined(Q_OS_WIN)
186 if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
187 return m_filePath.mid(2, length - 2);
188#endif
189 return m_filePath.mid(m_lastSeparator + 1, length);
190}
191
193{
194 findFileNameSeparators();
195
196 if (m_lastDotInFileName == -1)
197 return QString();
198
199 return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + m_lastDotInFileName + 1);
200}
201
203{
204 findFileNameSeparators();
205 if (m_firstDotInFileName == -1)
206 return QString();
207
208 return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + 1);
209}
210
211#if defined(Q_OS_WIN)
213{
214 resolveFilePath();
215 return (m_filePath.isEmpty()
216 || (m_filePath.at(0).unicode() != '/'
217 && !(m_filePath.length() >= 2 && m_filePath.at(1).unicode() == ':')));
218}
219
221{
222 resolveFilePath();
223 return ((m_filePath.length() >= 3
224 && m_filePath.at(0).isLetter()
225 && m_filePath.at(1).unicode() == ':'
226 && m_filePath.at(2).unicode() == '/')
227 || (m_filePath.length() >= 2
228 && m_filePath.at(0) == u'/'
229 && m_filePath.at(1) == u'/'));
230}
231#else
233{
234 return !isAbsolute();
235}
236
238{
239 resolveFilePath();
240 return (!m_filePath.isEmpty() && (m_filePath.at(0).unicode() == '/'));
241}
242#endif
243
244#if defined(Q_OS_WIN)
245bool QFileSystemEntry::isDriveRoot() const
246{
247 resolveFilePath();
248 return QFileSystemEntry::isDriveRootPath(m_filePath);
249}
250
251bool QFileSystemEntry::isDriveRootPath(const QString &path)
252{
253 return (path.length() == 3
254 && path.at(0).isLetter() && path.at(1) == u':'
255 && path.at(2) == u'/');
256}
257
258QString QFileSystemEntry::removeUncOrLongPathPrefix(QString path)
259{
260 constexpr qsizetype minPrefixSize = 4;
261 if (path.size() < minPrefixSize)
262 return path;
263
264 auto data = path.data();
265 const auto slash = path[0];
266 if (slash != u'\\' && slash != u'/')
267 return path;
268
269 // check for "//?/" or "/??/"
270 if (data[2] == u'?' && data[3] == slash && (data[1] == slash || data[1] == u'?')) {
271 path = path.sliced(minPrefixSize);
272
273 // check for a possible "UNC/" prefix left-over
274 if (path.size() >= 4) {
275 data = path.data();
276 if (data[0] == u'U' && data[1] == u'N' && data[2] == u'C' && data[3] == slash) {
277 data[2] = slash;
278 return path.sliced(2);
279 }
280 }
281 }
282
283 return path;
284}
285#endif // Q_OS_WIN
286
288{
289 if (path == "/"_L1
290#if defined(Q_OS_WIN)
291 || isDriveRootPath(path)
292 || isUncRoot(path)
293#endif
294 )
295 return true;
296
297 return false;
298}
299
301{
302 resolveFilePath();
303 return isRootPath(m_filePath);
304}
305
307{
308 return m_filePath.isEmpty() && m_nativeFilePath.isEmpty();
309}
310
311// private methods
312
313void QFileSystemEntry::findLastSeparator() const
314{
315 if (m_lastSeparator == -2) {
316 resolveFilePath();
317 m_lastSeparator = m_filePath.lastIndexOf(u'/');
318 }
319}
320
321void QFileSystemEntry::findFileNameSeparators() const
322{
323 if (m_firstDotInFileName == -2) {
324 resolveFilePath();
325 int firstDotInFileName = -1;
326 int lastDotInFileName = -1;
327 int lastSeparator = m_lastSeparator;
328
329 int stop;
330 if (lastSeparator < 0) {
331 lastSeparator = -1;
332 stop = 0;
333 } else {
334 stop = lastSeparator;
335 }
336
337 int i = m_filePath.size() - 1;
338 for (; i >= stop; --i) {
339 if (m_filePath.at(i).unicode() == '.') {
340 firstDotInFileName = lastDotInFileName = i;
341 break;
342 } else if (m_filePath.at(i).unicode() == '/') {
343 lastSeparator = i;
344 break;
345 }
346 }
347
348 if (lastSeparator != i) {
349 for (--i; i >= stop; --i) {
350 if (m_filePath.at(i).unicode() == '.')
351 firstDotInFileName = i;
352 else if (m_filePath.at(i).unicode() == '/') {
353 lastSeparator = i;
354 break;
355 }
356 }
357 }
358 m_lastSeparator = lastSeparator;
359 m_firstDotInFileName = firstDotInFileName == -1 ? -1 : firstDotInFileName - qMax(0, lastSeparator);
360 if (lastDotInFileName == -1)
361 m_lastDotInFileName = -1;
362 else if (firstDotInFileName == lastDotInFileName)
363 m_lastDotInFileName = 0;
364 else
365 m_lastDotInFileName = lastDotInFileName - firstDotInFileName;
366 }
367}
368
370{
371 resolveFilePath();
372 int dots = 0;
373 bool dotok = true; // checking for ".." or "." starts to relative paths
374 bool slashok = true;
375 for (QString::const_iterator iter = m_filePath.constBegin(); iter != m_filePath.constEnd(); ++iter) {
376 if (*iter == u'/') {
377 if (dots == 1 || dots == 2)
378 return false; // path contains "./" or "../"
379 if (!slashok)
380 return false; // path contains "//"
381 dots = 0;
382 dotok = true;
383 slashok = false;
384 } else if (dotok) {
385 slashok = true;
386 if (*iter == u'.') {
387 dots++;
388 if (dots > 2)
389 dotok = false;
390 } else {
391 //path element contains a character other than '.', it's clean
392 dots = 0;
393 dotok = false;
394 }
395 }
396 }
397 return (dots != 1 && dots != 2); // clean if path doesn't end in . or ..
398}
399
\inmodule QtCore
Definition qbytearray.h:57
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
\inmodule QtCore
Definition qchar.h:48
constexpr char16_t unicode() const noexcept
Returns the numeric Unicode value of the QChar.
Definition qchar.h:458
constexpr bool isLetter() const noexcept
Returns true if the character is a letter (Letter_* categories); otherwise returns false.
Definition qchar.h:470
\inmodule QtCore
Definition qdir.h:19
static QString fromNativeSeparators(const QString &pathName)
Definition qdir.cpp:962
static QString toNativeSeparators(const QString &pathName)
Definition qdir.cpp:929
static QString currentPath()
Returns the absolute path of the application's current directory.
Definition qdir.cpp:2051
Q_AUTOTEST_EXPORT NativePath nativeFilePath() const
Q_AUTOTEST_EXPORT bool isEmpty() const
Q_AUTOTEST_EXPORT QString baseName() const
Q_AUTOTEST_EXPORT bool isClean() const
Q_AUTOTEST_EXPORT QString completeBaseName() const
Q_AUTOTEST_EXPORT bool isRelative() const
static Q_CORE_EXPORT bool isRootPath(const QString &path)
Q_AUTOTEST_EXPORT QString suffix() const
Q_AUTOTEST_EXPORT QString path() const
Q_AUTOTEST_EXPORT bool isRoot() const
Q_AUTOTEST_EXPORT QString filePath() const
Q_AUTOTEST_EXPORT QString completeSuffix() const
Q_AUTOTEST_EXPORT QFileSystemEntry()
Q_AUTOTEST_EXPORT QString fileName() const
Q_AUTOTEST_EXPORT bool isAbsolute() const
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition qfile.h:162
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QString right(qsizetype n) const
Returns a substring that contains the n rightmost characters of the string.
Definition qstring.cpp:5180
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
const_iterator constEnd() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing just after the last character in...
Definition qstring.h:1211
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
QString sliced(qsizetype pos) const
Definition qstring.h:341
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
QString trimmed() const &
Definition qstring.h:380
const_iterator constBegin() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in the st...
Definition qstring.h:1203
qsizetype length() const
Returns the number of characters in this string.
Definition qstring.h:187
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage return DBusPendingCall DBusPendingCall return DBusPendingCall return dbus_int32_t return DBusServer * server
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei const GLchar *const * path
short qint16
Definition qtypes.h:42
ptrdiff_t qsizetype
Definition qtypes.h:70
static QString fromNativeSeparators(const QString &pathName)
Definition qurl.cpp:3303