From 4f47ee4de46f1fa2df9fef163590807e2fae28d1 Mon Sep 17 00:00:00 2001 From: Ahmad Samir Date: Fri, 20 Sep 2024 00:22:06 +0300 Subject: [PATCH] QDir: refactor PathNormalization enum AllowUncPaths (and the whole enum) is private API that is always enabled only on Windows (build-time decision). So, remove it and change the unittests to match reality. Now DefaultNormalization on Windows implies handling UNC paths. This was suggested in code review by Thiago; since this is a hot code path, the goal is letting the compiler keep the flags parameter to qt_normalizePathSegments() in a register, by keeping the PathNormalization enum as small as possible. Drive-by change: since those lines in the unittest are changed anyway, take the chance and use u""_s syntax. Change-Id: I3dcf30d888a0ea9f8898e260e65c5f85655296d5 Reviewed-by: Thiago Macieira --- src/corelib/io/qdir.cpp | 27 ++--- src/corelib/io/qdir_p.h | 1 - tests/auto/corelib/io/qdir/tst_qdir.cpp | 150 ++++++++++++------------ 3 files changed, 84 insertions(+), 94 deletions(-) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index a7e12eaae35..efad270cf82 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -51,33 +51,24 @@ static QString driveSpec(const QString &path) } #endif -enum { -#if defined(Q_OS_WIN) - OSSupportsUncPaths = true -#else - OSSupportsUncPaths = false -#endif -}; - // Return the length of the root part of an absolute path, for use by cleanPath(), cd(). -static qsizetype rootLength(QStringView name, bool allowUncPaths) +static qsizetype rootLength(QStringView name) { +#if defined(Q_OS_WIN) const qsizetype len = name.size(); - // starts with double slash - if (allowUncPaths && name.startsWith("//"_L1)) { + // Handle possible UNC paths which start with double slash + if (name.startsWith("//"_L1)) { // Server name '//server/path' is part of the prefix. const qsizetype nextSlash = name.indexOf(u'/', 2); return nextSlash >= 0 ? nextSlash + 1 : len; } -#if defined(Q_OS_WIN) if (len >= 2 && name.at(1) == u':') { // Handle a possible drive letter return len > 2 && name.at(2) == u'/' ? 3 : 2; } #endif - if (len && name.at(0) == u'/') - return 1; - return 0; + + return name.startsWith(u'/') ? 1 : 0; } //************* QDirPrivate @@ -2227,9 +2218,8 @@ bool QDir::match(const QString &filter, const QString &fileName) */ bool qt_normalizePathSegments(QString *path, QDirPrivate::PathNormalizations flags) { - const bool allowUncPaths = flags.testAnyFlag(QDirPrivate::AllowUncPaths); const bool isRemote = flags.testAnyFlag(QDirPrivate::RemotePath); - const qsizetype prefixLength = rootLength(*path, allowUncPaths); + const qsizetype prefixLength = rootLength(*path); // RFC 3986 says: "The input buffer is initialized with the now-appended // path components and the output buffer is initialized to the empty @@ -2372,8 +2362,7 @@ static bool qt_cleanPath(QString *path) QString &ret = *path; ret = QDir::fromNativeSeparators(ret); - auto normalization = OSSupportsUncPaths ? QDirPrivate::AllowUncPaths : QDirPrivate::DefaultNormalization; - bool ok = qt_normalizePathSegments(&ret, normalization); + bool ok = qt_normalizePathSegments(&ret, QDirPrivate::DefaultNormalization); // Strip away last slash except for root directories if (ret.size() > 1 && ret.endsWith(u'/')) { diff --git a/src/corelib/io/qdir_p.h b/src/corelib/io/qdir_p.h index 36a20c64723..aebb14b98bd 100644 --- a/src/corelib/io/qdir_p.h +++ b/src/corelib/io/qdir_p.h @@ -29,7 +29,6 @@ class QDirPrivate : public QSharedData public: enum PathNormalization { DefaultNormalization = 0x00, - AllowUncPaths = 0x01, RemotePath = 0x02, }; Q_DECLARE_FLAGS(PathNormalizations, PathNormalization) diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index bc9bd8411b3..90d2d45c689 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -62,7 +62,6 @@ class tst_QDir : public QObject Q_OBJECT public: - enum UncHandling { HandleUnc, IgnoreUnc }; tst_QDir(); private slots: @@ -222,8 +221,6 @@ private: }; }; -Q_DECLARE_METATYPE(tst_QDir::UncHandling) - tst_QDir::tst_QDir() #ifdef Q_OS_ANDROID : m_dataPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) @@ -1381,92 +1378,97 @@ tst_QDir::cleanPath() void tst_QDir::normalizePathSegments_data() { QTest::addColumn("path"); - QTest::addColumn("uncHandling"); QTest::addColumn("expected"); - QTest::newRow("data0") << "/Users/sam/troll/qt4.0//.." << HandleUnc << "/Users/sam/troll/"; - QTest::newRow("data1") << "/Users/sam////troll/qt4.0//.." << HandleUnc << "/Users/sam/troll/"; - QTest::newRow("data53") <<"/b//." << HandleUnc << "/b/"; - QTest::newRow("data54") <<"/b//./" << HandleUnc << "/b/"; - QTest::newRow("data55") <<"/b/." << HandleUnc << "/b/"; - QTest::newRow("data56") <<"/b/./" << HandleUnc << "/b/"; - QTest::newRow("data57") <<"/b" << HandleUnc << "/b"; + QTest::newRow("data0") << u"/Users/sam/troll/qt4.0//.."_s << u"/Users/sam/troll/"_s; + QTest::newRow("data1") << u"/Users/sam////troll/qt4.0//.."_s << u"/Users/sam/troll/"_s; + QTest::newRow("data53") <