7#include <QtCore/qdir.h>
8#include <QtCore/qfile.h>
9#include <QtCore/private/qfsfileengine_p.h>
11#include <QtCore/qstringbuilder.h>
16using namespace Qt::StringLiterals;
23static bool isUncRoot(
const QString &server)
25 QString localPath = QDir::toNativeSeparators(server);
26 if (!localPath.startsWith(
"\\\\"_L1))
29 int idx = localPath.indexOf(u'\\', 2);
30 if (idx == -1 || idx + 1 == localPath.length())
33 return QStringView{localPath}.right(localPath.length() - idx - 1).trimmed().isEmpty();
36static inline QString fixIfRelativeUncPath(
const QString &path)
38 QString currentPath = QDir::currentPath();
39 if (currentPath.startsWith(
"//"_L1))
40 return currentPath % QChar(u'/') % path;
45QFileSystemEntry::QFileSystemEntry()
46 : m_lastSeparator(-1),
47 m_firstDotInFileName(-1),
48 m_lastDotInFileName(-1)
53
54
55
56
57QFileSystemEntry::QFileSystemEntry(
const QString &filePath)
58 : m_filePath(QDir::fromNativeSeparators(filePath)),
59 m_lastSeparator(Uninitialized),
60 m_firstDotInFileName(Uninitialized),
61 m_lastDotInFileName(0)
66
67
68
69
70QFileSystemEntry::QFileSystemEntry(
const QString &filePath, FromInternalPath )
71 : m_filePath(filePath),
72 m_lastSeparator(Uninitialized),
73 m_firstDotInFileName(Uninitialized),
74 m_lastDotInFileName(0)
79
80
81
82QFileSystemEntry::QFileSystemEntry(
const NativePath &nativeFilePath, FromNativePath )
83 : m_nativeFilePath(nativeFilePath),
84 m_lastSeparator(Uninitialized),
85 m_firstDotInFileName(Uninitialized),
86 m_lastDotInFileName(0)
90QFileSystemEntry::QFileSystemEntry(
const QString &filePath,
const NativePath &nativeFilePath)
91 : m_filePath(QDir::fromNativeSeparators(filePath)),
92 m_nativeFilePath(nativeFilePath),
93 m_lastSeparator(Uninitialized),
94 m_firstDotInFileName(Uninitialized),
95 m_lastDotInFileName(0)
99QString QFileSystemEntry::filePath()
const
105QFileSystemEntry::NativePath QFileSystemEntry::nativeFilePath()
const
107 resolveNativeFilePath();
108 return m_nativeFilePath;
111void QFileSystemEntry::resolveFilePath()
const
113 if (m_filePath.isEmpty() && !m_nativeFilePath.isEmpty()) {
115 m_filePath = QDir::fromNativeSeparators(m_nativeFilePath);
117 m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath));
122void QFileSystemEntry::resolveNativeFilePath()
const
124 if (!m_filePath.isEmpty() && m_nativeFilePath.isEmpty()) {
126 QString filePath = m_filePath;
128 filePath = fixIfRelativeUncPath(m_filePath);
129 m_nativeFilePath = QFSFileEnginePrivate::longFileName(QDir::toNativeSeparators(filePath));
131 m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath));
136QString QFileSystemEntry::fileName()
const
140 if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
141 return m_filePath.mid(2);
143 return m_filePath.mid(m_lastSeparator + 1);
146QString QFileSystemEntry::path()
const
149 if (m_lastSeparator == -1) {
151 if (m_filePath.length() >= 2 && m_filePath.at(1) == u':')
152 return m_filePath.left(2);
154 return QString(u'.');
156 if (m_lastSeparator == 0)
157 return QString(u'/');
159 if (m_lastSeparator == 2 && m_filePath.at(1) == u':')
160 return m_filePath.left(m_lastSeparator + 1);
162 return m_filePath.left(m_lastSeparator);
165QString QFileSystemEntry::baseName()
const
167 findFileNameSeparators();
169 if (m_firstDotInFileName >= 0) {
170 length = m_firstDotInFileName;
171 if (m_lastSeparator != -1)
175 if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
176 return m_filePath.mid(2, length - 2);
178 return m_filePath.mid(m_lastSeparator + 1, length);
181QString QFileSystemEntry::completeBaseName()
const
183 findFileNameSeparators();
185 if (m_firstDotInFileName >= 0) {
186 length = m_firstDotInFileName + m_lastDotInFileName;
187 if (m_lastSeparator != -1)
191 if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
192 return m_filePath.mid(2, length - 2);
194 return m_filePath.mid(m_lastSeparator + 1, length);
197QString QFileSystemEntry::suffix()
const
199 findFileNameSeparators();
201 if (m_lastDotInFileName == -1)
204 return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + m_lastDotInFileName + 1);
207QString QFileSystemEntry::completeSuffix()
const
209 findFileNameSeparators();
210 if (m_firstDotInFileName == -1)
213 return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + 1);
217bool QFileSystemEntry::isRelative()
const
220 return (m_filePath.isEmpty()
221 || (m_filePath.at(0).unicode() !=
'/'
222 && !(m_filePath.length() >= 2 && m_filePath.at(1).unicode() ==
':')));
225bool QFileSystemEntry::isAbsolute()
const
228 return ((m_filePath.length() >= 3
229 && m_filePath.at(0).isLetter()
230 && m_filePath.at(1).unicode() ==
':'
231 && m_filePath.at(2).unicode() ==
'/')
232 || (m_filePath.length() >= 2
233 && m_filePath.at(0) == u'/'
234 && m_filePath.at(1) == u'/'));
237bool QFileSystemEntry::isRelative()
const
239 return !isAbsolute();
242bool QFileSystemEntry::isAbsolute()
const
245 return (!m_filePath.isEmpty() && (m_filePath.at(0).unicode() ==
'/'));
250bool QFileSystemEntry::isDriveRoot()
const
253 return QFileSystemEntry::isDriveRootPath(m_filePath);
256bool QFileSystemEntry::isDriveRootPath(
const QString &path)
258 return (path.length() == 3
259 && path.at(0).isLetter() && path.at(1) == u':'
260 && path.at(2) == u'/');
263QString QFileSystemEntry::removeUncOrLongPathPrefix(QString path)
265 constexpr qsizetype minPrefixSize = 4;
266 if (path.size() < minPrefixSize)
269 auto data = path.data();
270 const auto slash = path[0];
271 if (slash != u'\\' && slash != u'/')
275 if (data[2] == u'?' && data[3] == slash && (data[1] == slash || data[1] == u'?')) {
276 path = path.sliced(minPrefixSize);
279 if (path.size() >= 4) {
281 if (data[0] == u'U' && data[1] == u'N' && data[2] == u'C' && data[3] == slash) {
283 return path.sliced(2);
292bool QFileSystemEntry::isRootPath(
const QString &path)
296 || isDriveRootPath(path)
305bool QFileSystemEntry::isRoot()
const
308 return isRootPath(m_filePath);
311bool QFileSystemEntry::isEmpty()
const
313 return m_filePath.isEmpty() && m_nativeFilePath.isEmpty();
318void QFileSystemEntry::findLastSeparator()
const
320 if (m_lastSeparator == Uninitialized) {
322 m_lastSeparator = m_filePath.lastIndexOf(u'/');
326void QFileSystemEntry::findFileNameSeparators()
const
328 if (m_firstDotInFileName == Uninitialized) {
330 int firstDotInFileName = -1;
331 int lastDotInFileName = -1;
332 int lastSeparator = m_lastSeparator;
335 if (lastSeparator < 0) {
339 stop = lastSeparator;
342 Q_ASSERT(m_filePath.size() ==
int(m_filePath.size()));
343 int i =
int(m_filePath.size() - 1);
344 for (; i >= stop; --i) {
345 if (m_filePath.at(i).unicode() ==
'.') {
346 firstDotInFileName = lastDotInFileName = i;
348 }
else if (m_filePath.at(i).unicode() ==
'/') {
354 if (lastSeparator != i) {
355 for (--i; i >= stop; --i) {
356 if (m_filePath.at(i).unicode() ==
'.')
357 firstDotInFileName = i;
358 else if (m_filePath.at(i).unicode() ==
'/') {
364 m_lastSeparator = lastSeparator;
365 m_firstDotInFileName = firstDotInFileName == -1 ? -1 : firstDotInFileName - qMax(0, lastSeparator);
366 if (lastDotInFileName == -1)
367 m_lastDotInFileName = -1;
368 else if (firstDotInFileName == lastDotInFileName)
369 m_lastDotInFileName = 0;
371 m_lastDotInFileName = lastDotInFileName - firstDotInFileName;
375bool QFileSystemEntry::isClean()
const
381 for (QString::const_iterator iter = m_filePath.constBegin(); iter != m_filePath.constEnd(); ++iter) {
383 if (dots == 1 || dots == 2)
403 return (dots != 1 && dots != 2);
constexpr int Uninitialized