Files
llvm-mingw/patches/llvm-project/0012-libcxx-Implement-parsing-of-root_name-for-paths-on-w.patch
T
Martin Storsjö 657d12c8a5 Backport another libc++ patch for std::filesystem (and locale) usage
This fixes linking against a DLL of libc++ while using the common headers
(generated from the static version of the library, but which work for
both shared and static versions) when calling e.g. std::filesystem::u8path.
2021-05-25 23:55:32 +03:00

174 lines
5.4 KiB
Diff

From 3f12aeb4ae3fd43d98f0c698952713d9fef7bef3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin@martin.st>
Date: Tue, 3 Nov 2020 23:52:32 +0200
Subject: [PATCH 12/25] [libcxx] Implement parsing of root_name for paths on
windows
Differential Revision: https://reviews.llvm.org/D91176
(cherry picked from commit 929f0bcc24e246ea02ab57df8009a6fd5751d45c)
---
libcxx/src/filesystem/operations.cpp | 92 +++++++++++++++++++++++++---
1 file changed, 85 insertions(+), 7 deletions(-)
diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp
index 674f19154e6f..88a039f85021 100644
--- a/libcxx/src/filesystem/operations.cpp
+++ b/libcxx/src/filesystem/operations.cpp
@@ -64,6 +64,10 @@ bool isSeparator(path::value_type C) {
return false;
}
+bool isDriveLetter(path::value_type C) {
+ return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z');
+}
+
namespace parser {
using string_view_t = path::__string_view;
@@ -120,6 +124,12 @@ public:
switch (State) {
case PS_BeforeBegin: {
+ PosPtr TkEnd = consumeRootName(Start, End);
+ if (TkEnd)
+ return makeState(PS_InRootName, Start, TkEnd);
+ }
+ _LIBCPP_FALLTHROUGH();
+ case PS_InRootName: {
PosPtr TkEnd = consumeSeparator(Start, End);
if (TkEnd)
return makeState(PS_InRootDir, Start, TkEnd);
@@ -142,7 +152,6 @@ public:
case PS_InTrailingSep:
return makeState(PS_AtEnd);
- case PS_InRootName:
case PS_AtEnd:
_LIBCPP_UNREACHABLE();
}
@@ -160,9 +169,15 @@ public:
if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
if (SepEnd == REnd)
return makeState(PS_InRootDir, Path.data(), RStart + 1);
+ PosPtr TkStart = consumeRootName(SepEnd, REnd);
+ if (TkStart == REnd)
+ return makeState(PS_InRootDir, RStart, RStart + 1);
return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
} else {
- PosPtr TkStart = consumeName(RStart, REnd);
+ PosPtr TkStart = consumeRootName(RStart, REnd);
+ if (TkStart == REnd)
+ return makeState(PS_InRootName, TkStart + 1, RStart + 1);
+ TkStart = consumeName(RStart, REnd);
return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
}
}
@@ -173,11 +188,17 @@ public:
PosPtr SepEnd = consumeSeparator(RStart, REnd);
if (SepEnd == REnd)
return makeState(PS_InRootDir, Path.data(), RStart + 1);
- PosPtr TkEnd = consumeName(SepEnd, REnd);
- return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1);
+ PosPtr TkStart = consumeRootName(SepEnd ? SepEnd : RStart, REnd);
+ if (TkStart == REnd) {
+ if (SepEnd)
+ return makeState(PS_InRootDir, SepEnd + 1, RStart + 1);
+ return makeState(PS_InRootName, TkStart + 1, RStart + 1);
+ }
+ TkStart = consumeName(SepEnd, REnd);
+ return makeState(PS_InFilenames, TkStart + 1, SepEnd + 1);
}
case PS_InRootDir:
- // return makeState(PS_InRootName, Path.data(), RStart + 1);
+ return makeState(PS_InRootName, Path.data(), RStart + 1);
case PS_InRootName:
case PS_BeforeBegin:
_LIBCPP_UNREACHABLE();
@@ -284,7 +305,7 @@ private:
}
PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
- if (P == End || !isSeparator(*P))
+ if (P == nullptr || P == End || !isSeparator(*P))
return nullptr;
const int Inc = P < End ? 1 : -1;
P += Inc;
@@ -293,15 +314,72 @@ private:
return P;
}
+ // Consume exactly N separators, or return nullptr.
+ PosPtr consumeNSeparators(PosPtr P, PosPtr End, int N) const noexcept {
+ PosPtr Ret = consumeSeparator(P, End);
+ if (Ret == nullptr)
+ return nullptr;
+ if (P < End) {
+ if (Ret == P + N)
+ return Ret;
+ } else {
+ if (Ret == P - N)
+ return Ret;
+ }
+ return nullptr;
+ }
+
PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
- if (P == End || isSeparator(*P))
+ PosPtr Start = P;
+ if (P == nullptr || P == End || isSeparator(*P))
return nullptr;
const int Inc = P < End ? 1 : -1;
P += Inc;
while (P != End && !isSeparator(*P))
P += Inc;
+ if (P == End && Inc < 0) {
+ // Iterating backwards and consumed all the rest of the input.
+ // Check if the start of the string would have been considered
+ // a root name.
+ PosPtr RootEnd = consumeRootName(End + 1, Start);
+ if (RootEnd)
+ return RootEnd - 1;
+ }
return P;
}
+
+ PosPtr consumeDriveLetter(PosPtr P, PosPtr End) const noexcept {
+ if (P == End)
+ return nullptr;
+ if (P < End) {
+ if (P + 1 == End || !isDriveLetter(P[0]) || P[1] != ':')
+ return nullptr;
+ return P + 2;
+ } else {
+ if (P - 1 == End || !isDriveLetter(P[-1]) || P[0] != ':')
+ return nullptr;
+ return P - 2;
+ }
+ }
+
+ PosPtr consumeNetworkRoot(PosPtr P, PosPtr End) const noexcept {
+ if (P == End)
+ return nullptr;
+ if (P < End)
+ return consumeName(consumeNSeparators(P, End, 2), End);
+ else
+ return consumeNSeparators(consumeName(P, End), End, 2);
+ }
+
+ PosPtr consumeRootName(PosPtr P, PosPtr End) const noexcept {
+#if defined(_LIBCPP_WIN32API)
+ if (PosPtr Ret = consumeDriveLetter(P, End))
+ return Ret;
+ if (PosPtr Ret = consumeNetworkRoot(P, End))
+ return Ret;
+#endif
+ return nullptr;
+ }
};
string_view_pair separate_filename(string_view_t const& s) {
--
2.25.1