forked from OSchip/llvm-project
[Support] Add a new path style for Windows with forward slashes
This behaves just like the regular Windows style, with both separator forms accepted, but with get_separator() returning forward slashes. Add a more descriptive name for the existing style, keeping the old name around as an alias initially. Add a new function `make_preferred()` (like the C++17 `std::filesystem::path` function with the same name), which converts windows paths to the preferred separator form (while this one works on any platform and takes a `path::Style` argument). Contrary to `native()` (just like `make_preferred()` in `std::filesystem`), this doesn't do anything at all on Posix, it doesn't try to reinterpret backslashes into forward slashes there. Differential Revision: https://reviews.llvm.org/D111879
This commit is contained in:
parent
f95bd18b5f
commit
a8b54834a1
|
@ -25,7 +25,13 @@ namespace llvm {
|
|||
namespace sys {
|
||||
namespace path {
|
||||
|
||||
enum class Style { windows, posix, native };
|
||||
enum class Style {
|
||||
native,
|
||||
posix,
|
||||
windows_slash,
|
||||
windows_backslash,
|
||||
windows = windows_backslash, // deprecated
|
||||
};
|
||||
|
||||
/// Check if \p S uses POSIX path rules.
|
||||
constexpr bool is_style_posix(Style S) {
|
||||
|
@ -257,6 +263,17 @@ void native(const Twine &path, SmallVectorImpl<char> &result,
|
|||
/// @param path A path that is transformed to native format.
|
||||
void native(SmallVectorImpl<char> &path, Style style = Style::native);
|
||||
|
||||
/// For Windows path styles, convert path to use the preferred path separators.
|
||||
/// For other styles, do nothing.
|
||||
///
|
||||
/// @param path A path that is transformed to preferred format.
|
||||
inline void make_preferred(SmallVectorImpl<char> &path,
|
||||
Style style = Style::native) {
|
||||
if (!is_style_windows(style))
|
||||
return;
|
||||
native(path, style);
|
||||
}
|
||||
|
||||
/// Replaces backslashes with slashes if Windows.
|
||||
///
|
||||
/// @param path processed path
|
||||
|
|
|
@ -37,13 +37,15 @@ namespace {
|
|||
using llvm::sys::path::Style;
|
||||
|
||||
inline Style real_style(Style style) {
|
||||
if (style != Style::native)
|
||||
return style;
|
||||
if (is_style_posix(style))
|
||||
return Style::posix;
|
||||
return Style::windows;
|
||||
}
|
||||
|
||||
inline const char *separators(Style style) {
|
||||
if (real_style(style) == Style::windows)
|
||||
if (is_style_windows(style))
|
||||
return "\\/";
|
||||
return "/";
|
||||
}
|
||||
|
@ -547,7 +549,9 @@ void native(SmallVectorImpl<char> &Path, Style style) {
|
|||
if (Path.empty())
|
||||
return;
|
||||
if (is_style_windows(style)) {
|
||||
std::replace(Path.begin(), Path.end(), '/', '\\');
|
||||
for (char &Ch : Path)
|
||||
if (is_separator(Ch, style))
|
||||
Ch = preferred_separator(style);
|
||||
if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
|
||||
SmallString<128> PathHome;
|
||||
home_directory(PathHome);
|
||||
|
@ -601,7 +605,7 @@ bool is_separator(char value, Style style) {
|
|||
}
|
||||
|
||||
StringRef get_separator(Style style) {
|
||||
if (is_style_windows(style))
|
||||
if (real_style(style) == Style::windows)
|
||||
return "\\";
|
||||
return "/";
|
||||
}
|
||||
|
|
|
@ -75,7 +75,9 @@ TEST(is_style_Style, Works) {
|
|||
// Check platform-independent results.
|
||||
EXPECT_TRUE(is_style_posix(Style::posix));
|
||||
EXPECT_TRUE(is_style_windows(Style::windows));
|
||||
EXPECT_TRUE(is_style_windows(Style::windows_slash));
|
||||
EXPECT_FALSE(is_style_posix(Style::windows));
|
||||
EXPECT_FALSE(is_style_posix(Style::windows_slash));
|
||||
EXPECT_FALSE(is_style_windows(Style::posix));
|
||||
|
||||
// Check platform-dependent results.
|
||||
|
@ -95,12 +97,19 @@ TEST(is_separator, Works) {
|
|||
EXPECT_FALSE(path::is_separator(' '));
|
||||
|
||||
EXPECT_TRUE(path::is_separator('\\', path::Style::windows));
|
||||
EXPECT_TRUE(path::is_separator('\\', path::Style::windows_slash));
|
||||
EXPECT_FALSE(path::is_separator('\\', path::Style::posix));
|
||||
|
||||
EXPECT_EQ(path::is_style_windows(path::Style::native),
|
||||
path::is_separator('\\'));
|
||||
}
|
||||
|
||||
TEST(get_separator, Works) {
|
||||
EXPECT_EQ(path::get_separator(path::Style::posix), "/");
|
||||
EXPECT_EQ(path::get_separator(path::Style::windows_backslash), "\\");
|
||||
EXPECT_EQ(path::get_separator(path::Style::windows_slash), "/");
|
||||
}
|
||||
|
||||
TEST(is_absolute_gnu, Works) {
|
||||
// Test tuple <Path, ExpectedPosixValue, ExpectedWindowsValue>.
|
||||
const std::tuple<StringRef, bool, bool> Paths[] = {
|
||||
|
@ -383,6 +392,8 @@ TEST(Support, PathIterator) {
|
|||
testing::ElementsAre("/", ".c", ".d", "..", "."));
|
||||
EXPECT_THAT(GetComponents("c:\\c\\e\\foo.txt", path::Style::windows),
|
||||
testing::ElementsAre("c:", "\\", "c", "e", "foo.txt"));
|
||||
EXPECT_THAT(GetComponents("c:\\c\\e\\foo.txt", path::Style::windows_slash),
|
||||
testing::ElementsAre("c:", "\\", "c", "e", "foo.txt"));
|
||||
EXPECT_THAT(GetComponents("//net/"), testing::ElementsAre("//net", "/"));
|
||||
EXPECT_THAT(GetComponents("//net/c/foo.txt"),
|
||||
testing::ElementsAre("//net", "/", "c", "foo.txt"));
|
||||
|
@ -1425,10 +1436,25 @@ TEST(Support, NormalizePath) {
|
|||
for (auto &T : Tests) {
|
||||
SmallString<64> Win(std::get<0>(T));
|
||||
SmallString<64> Posix(Win);
|
||||
SmallString<64> WinSlash(Win);
|
||||
path::native(Win, path::Style::windows);
|
||||
path::native(Posix, path::Style::posix);
|
||||
path::native(WinSlash, path::Style::windows_slash);
|
||||
EXPECT_EQ(std::get<1>(T), Win);
|
||||
EXPECT_EQ(std::get<2>(T), Posix);
|
||||
EXPECT_EQ(std::get<2>(T), WinSlash);
|
||||
}
|
||||
|
||||
for (auto &T : Tests) {
|
||||
SmallString<64> WinBackslash(std::get<0>(T));
|
||||
SmallString<64> Posix(WinBackslash);
|
||||
SmallString<64> WinSlash(WinBackslash);
|
||||
path::make_preferred(WinBackslash, path::Style::windows_backslash);
|
||||
path::make_preferred(Posix, path::Style::posix);
|
||||
path::make_preferred(WinSlash, path::Style::windows_slash);
|
||||
EXPECT_EQ(std::get<1>(T), WinBackslash);
|
||||
EXPECT_EQ(std::get<0>(T), Posix); // Posix remains unchanged here
|
||||
EXPECT_EQ(std::get<2>(T), WinSlash);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
@ -1437,10 +1463,15 @@ TEST(Support, NormalizePath) {
|
|||
|
||||
const char *Path7a = "~/aaa";
|
||||
SmallString<64> Path7(Path7a);
|
||||
path::native(Path7);
|
||||
path::native(Path7, path::Style::windows_backslash);
|
||||
EXPECT_TRUE(Path7.endswith("\\aaa"));
|
||||
EXPECT_TRUE(Path7.startswith(PathHome));
|
||||
EXPECT_EQ(Path7.size(), PathHome.size() + strlen(Path7a + 1));
|
||||
Path7 = Path7a;
|
||||
path::native(Path7, path::Style::windows_slash);
|
||||
EXPECT_TRUE(Path7.endswith("/aaa"));
|
||||
EXPECT_TRUE(Path7.startswith(PathHome));
|
||||
EXPECT_EQ(Path7.size(), PathHome.size() + strlen(Path7a + 1));
|
||||
|
||||
const char *Path8a = "~";
|
||||
SmallString<64> Path8(Path8a);
|
||||
|
@ -1454,7 +1485,7 @@ TEST(Support, NormalizePath) {
|
|||
|
||||
const char *Path10a = "aaa/~/b";
|
||||
SmallString<64> Path10(Path10a);
|
||||
path::native(Path10);
|
||||
path::native(Path10, path::Style::windows_backslash);
|
||||
EXPECT_EQ(Path10, "aaa\\~\\b");
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue