Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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// Assigned to m_lastSeparator and m_firstDotInFileName to indicate resolveFilePath()
18// hasn't been called yet
19constexpr int Uninitialized = -2;
20
21#ifdef Q_OS_WIN
22static bool isUncRoot(const QString &server)
23{
25 if (!localPath.startsWith("\\\\"_L1))
26 return false;
27
28 int idx = localPath.indexOf(u'\\', 2);
29 if (idx == -1 || idx + 1 == localPath.length())
30 return true;
31
32 return QStringView{localPath}.right(localPath.length() - idx - 1).trimmed().isEmpty();
33}
34
35static inline QString fixIfRelativeUncPath(const QString &path)
36{
37 QString currentPath = QDir::currentPath();
38 if (currentPath.startsWith("//"_L1))
39 return currentPath % QChar(u'/') % path;
40 return path;
41}
42#endif
43
45 : m_lastSeparator(-1),
46 m_firstDotInFileName(-1),
47 m_lastDotInFileName(-1)
48{
49}
50
57 : m_filePath(QDir::fromNativeSeparators(filePath)),
58 m_lastSeparator(Uninitialized),
59 m_firstDotInFileName(Uninitialized),
60 m_lastDotInFileName(0)
61{
62}
63
70 : m_filePath(filePath),
71 m_lastSeparator(Uninitialized),
72 m_firstDotInFileName(Uninitialized),
73 m_lastDotInFileName(0)
74{
75}
76
82 : m_nativeFilePath(nativeFilePath),
83 m_lastSeparator(Uninitialized),
84 m_firstDotInFileName(Uninitialized),
85 m_lastDotInFileName(0)
86{
87}
88
89QFileSystemEntry::QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath)
90 : m_filePath(QDir::fromNativeSeparators(filePath)),
91 m_nativeFilePath(nativeFilePath),
92 m_lastSeparator(Uninitialized),
93 m_firstDotInFileName(Uninitialized),
94 m_lastDotInFileName(0)
95{
96}
97
99{
100 resolveFilePath();
101 return m_filePath;
102}
103
105{
106 resolveNativeFilePath();
107 return m_nativeFilePath;
108}
109
110void QFileSystemEntry::resolveFilePath() const
111{
112 if (m_filePath.isEmpty() && !m_nativeFilePath.isEmpty()) {
113#ifdef Q_OS_WIN
114 m_filePath = QDir::fromNativeSeparators(m_nativeFilePath);
115#else
116 m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath));
117#endif
118 }
119}
120
121void QFileSystemEntry::resolveNativeFilePath() const
122{
123 if (!m_filePath.isEmpty() && m_nativeFilePath.isEmpty()) {
124#ifdef Q_OS_WIN
125 QString filePath = m_filePath;
126 if (isRelative())
127 filePath = fixIfRelativeUncPath(m_filePath);
128 m_nativeFilePath = QFSFileEnginePrivate::longFileName(QDir::toNativeSeparators(filePath));
129#else
130 m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath));
131#endif
132 }
133}
134
136{
137 findLastSeparator();
138#if defined(Q_OS_WIN)
139 if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
140 return m_filePath.mid(2);
141#endif
142 return m_filePath.mid(m_lastSeparator + 1);
143}
144
146{
147 findLastSeparator();
148 if (m_lastSeparator == -1) {
149#if defined(Q_OS_WIN)
150 if (m_filePath.length() >= 2 && m_filePath.at(1) == u':')
151 return m_filePath.left(2);
152#endif
153 return QString(u'.');
154 }
155 if (m_lastSeparator == 0)
156 return QString(u'/');
157#if defined(Q_OS_WIN)
158 if (m_lastSeparator == 2 && m_filePath.at(1) == u':')
159 return m_filePath.left(m_lastSeparator + 1);
160#endif
161 return m_filePath.left(m_lastSeparator);
162}
163
165{
166 findFileNameSeparators();
167 int length = -1;
168 if (m_firstDotInFileName >= 0) {
169 length = m_firstDotInFileName;
170 if (m_lastSeparator != -1) // avoid off by one
171 length--;
172 }
173#if defined(Q_OS_WIN)
174 if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
175 return m_filePath.mid(2, length - 2);
176#endif
177 return m_filePath.mid(m_lastSeparator + 1, length);
178}
179
181{
182 findFileNameSeparators();
183 int length = -1;
184 if (m_firstDotInFileName >= 0) {
185 length = m_firstDotInFileName + m_lastDotInFileName;
186 if (m_lastSeparator != -1) // avoid off by one
187 length--;
188 }
189#if defined(Q_OS_WIN)
190 if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
191 return m_filePath.mid(2, length - 2);
192#endif
193 return m_filePath.mid(m_lastSeparator + 1, length);
194}
195
197{
198 findFileNameSeparators();
199
200 if (m_lastDotInFileName == -1)
201 return QString();
202
203 return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + m_lastDotInFileName + 1);
204}
205
207{
208 findFileNameSeparators();
209 if (m_firstDotInFileName == -1)
210 return QString();
211
212 return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + 1);
213}
214
215#if defined(Q_OS_WIN)
217{
218 resolveFilePath();
219 return (m_filePath.isEmpty()
220 || (m_filePath.at(0).unicode() != '/'
221 && !(m_filePath.length() >= 2 && m_filePath.at(1).unicode() == ':')));
222}
223
225{
226 resolveFilePath();
227 return ((m_filePath.length() >= 3
228 && m_filePath.at(0).isLetter()
229 && m_filePath.at(1).unicode() == ':'
230 && m_filePath.at(2).unicode() == '/')
231 || (m_filePath.length() >= 2
232 && m_filePath.at(0) == u'/'
233 && m_filePath.at(1) == u'/'));
234}
235#else
237{
238 return !isAbsolute();
239}
240
242{
243 resolveFilePath();
244 return (!m_filePath.isEmpty() && (m_filePath.at(0).unicode() == '/'));
245}
246#endif
247
248#if defined(Q_OS_WIN)
249bool QFileSystemEntry::isDriveRoot() const
250{
251 resolveFilePath();
252 return QFileSystemEntry::isDriveRootPath(m_filePath);
253}
254
255bool QFileSystemEntry::isDriveRootPath(const QString &path)
256{
257 return (path.length() == 3
258 && path.at(0).isLetter() && path.at(1) == u':'
259 && path.at(2) == u'/');
260}
261
262QString QFileSystemEntry::removeUncOrLongPathPrefix(QString path)
263{
264 constexpr qsizetype minPrefixSize = 4;
265 if (path.size() < minPrefixSize)
266 return path;
267
268 auto data = path.data();
269 const auto slash = path[0];
270 if (slash != u'\\' && slash != u'/')
271 return path;
272
273 // check for "//?/" or "/??/"
274 if (data[2] == u'?' && data[3] == slash && (data[1] == slash || data[1] == u'?')) {
275 path = path.sliced(minPrefixSize);
276
277 // check for a possible "UNC/" prefix left-over
278 if (path.size() >= 4) {
279 data = path.data();
280 if (data[0] == u'U' && data[1] == u'N' && data[2] == u'C' && data[3] == slash) {
281 data[2] = slash;
282 return path.sliced(2);
283 }
284 }
285 }
286
287 return path;
288}
289#endif // Q_OS_WIN
290
292{
293 if (path == "/"_L1
294#if defined(Q_OS_WIN)
295 || isDriveRootPath(path)
296 || isUncRoot(path)
297#endif
298 )
299 return true;
300
301 return false;
302}
303
305{
306 resolveFilePath();
307 return isRootPath(m_filePath);
308}
309
311{
312 return m_filePath.isEmpty() && m_nativeFilePath.isEmpty();
313}
314
315// private methods
316
317void QFileSystemEntry::findLastSeparator() const
318{
319 if (m_lastSeparator == Uninitialized) {
320 resolveFilePath();
321 m_lastSeparator = m_filePath.lastIndexOf(u'/');
322 }
323}
324
325void QFileSystemEntry::findFileNameSeparators() const
326{
327 if (m_firstDotInFileName == Uninitialized) {
328 resolveFilePath();
329 int firstDotInFileName = -1;
330 int lastDotInFileName = -1;
331 int lastSeparator = m_lastSeparator;
332
333 int stop;
334 if (lastSeparator < 0) {
335 lastSeparator = -1;
336 stop = 0;
337 } else {
338 stop = lastSeparator;
339 }
340
341 int i = m_filePath.size() - 1;
342 for (; i >= stop; --i) {
343 if (m_filePath.at(i).unicode() == '.') {
344 firstDotInFileName = lastDotInFileName = i;
345 break;
346 } else if (m_filePath.at(i).unicode() == '/') {
347 lastSeparator = i;
348 break;
349 }
350 }
351
352 if (lastSeparator != i) {
353 for (--i; i >= stop; --i) {
354 if (m_filePath.at(i).unicode() == '.')
355 firstDotInFileName = i;
356 else if (m_filePath.at(i).unicode() == '/') {
357 lastSeparator = i;
358 break;
359 }
360 }
361 }
362 m_lastSeparator = lastSeparator;
363 m_firstDotInFileName = firstDotInFileName == -1 ? -1 : firstDotInFileName - qMax(0, lastSeparator);
364 if (lastDotInFileName == -1)
365 m_lastDotInFileName = -1;
366 else if (firstDotInFileName == lastDotInFileName)
367 m_lastDotInFileName = 0;
368 else
369 m_lastDotInFileName = lastDotInFileName - firstDotInFileName;
370 }
371}
372
374{
375 resolveFilePath();
376 int dots = 0;
377 bool dotok = true; // checking for ".." or "." starts to relative paths
378 bool slashok = true;
379 for (QString::const_iterator iter = m_filePath.constBegin(); iter != m_filePath.constEnd(); ++iter) {
380 if (*iter == u'/') {
381 if (dots == 1 || dots == 2)
382 return false; // path contains "./" or "../"
383 if (!slashok)
384 return false; // path contains "//"
385 dots = 0;
386 dotok = true;
387 slashok = false;
388 } else if (dotok) {
389 slashok = true;
390 if (*iter == u'.') {
391 dots++;
392 if (dots > 2)
393 dotok = false;
394 } else {
395 //path element contains a character other than '.', it's clean
396 dots = 0;
397 dotok = false;
398 }
399 }
400 }
401 return (dots != 1 && dots != 2); // clean if path doesn't end in . or ..
402}
403
\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:107
\inmodule QtCore
\inmodule QtCore
Definition qdir.h:20
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:2054
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:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString left(qsizetype n) const &
Definition qstring.h:363
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:296
const_iterator constEnd() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing just after the last character in...
Definition qstring.h:1363
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:5455
QString sliced(qsizetype pos) const &
Definition qstring.h:394
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
QString right(qsizetype n) const &
Definition qstring.h:375
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1240
QString trimmed() const &
Definition qstring.h:447
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:1355
qsizetype length() const noexcept
Returns the number of characters in this string.
Definition qstring.h:191
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 int Uninitialized
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:47
ptrdiff_t qsizetype
Definition qtypes.h:165
static QString fromNativeSeparators(const QString &pathName)
Definition qurl.cpp:3317