summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/Support/Path.h23
-rw-r--r--llvm/lib/Support/Path.cpp41
-rw-r--r--llvm/unittests/Support/Path.cpp29
3 files changed, 80 insertions, 13 deletions
diff --git a/llvm/include/llvm/Support/Path.h b/llvm/include/llvm/Support/Path.h
index 488f17427fd..97955f882d5 100644
--- a/llvm/include/llvm/Support/Path.h
+++ b/llvm/include/llvm/Support/Path.h
@@ -152,18 +152,33 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
///
/// @code
/// /foo, /old, /new => /foo
+/// /old, /old, /new => /new
+/// /old, /old/, /new, false => /old
+/// /old, /old/, /new, true => /new
/// /old/foo, /old, /new => /new/foo
+/// /old/foo, /old/, /new => /new/foo
+/// /old/foo, /old/, /new/ => /new/foo
+/// /oldfoo, /old, /new => /oldfoo
/// /foo, <empty>, /new => /new/foo
-/// /old/foo, /old, <empty> => /foo
+/// /foo, <empty>, new => new/foo
+/// /old/foo, /old, <empty>, false => /foo
+/// /old/foo, /old, <empty>, true => foo
/// @endcode
///
/// @param Path If \a Path starts with \a OldPrefix modify to instead
/// start with \a NewPrefix.
-/// @param OldPrefix The path prefix to strip from \a Path.
+/// @param OldPrefix The path prefix to strip from \a Path. Any trailing
+/// path separator is ignored if strict is true.
/// @param NewPrefix The path prefix to replace \a NewPrefix with.
-void replace_path_prefix(SmallVectorImpl<char> &Path,
+/// @param style The path separator style
+/// @param strict If strict is true, a directory separator following
+/// \a OldPrefix will also be stripped. Otherwise, directory
+/// separators will only be matched and stripped when present
+/// in \a OldPrefix.
+/// @result true if \a Path begins with OldPrefix
+bool replace_path_prefix(SmallVectorImpl<char> &Path,
const StringRef &OldPrefix, const StringRef &NewPrefix,
- Style style = Style::native);
+ Style style = Style::native, bool strict = false);
/// Append to path.
///
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index 14def83802d..3c9a08cb407 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -496,27 +496,50 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
path.append(ext.begin(), ext.end());
}
-void replace_path_prefix(SmallVectorImpl<char> &Path,
+bool replace_path_prefix(SmallVectorImpl<char> &Path,
const StringRef &OldPrefix, const StringRef &NewPrefix,
- Style style) {
+ Style style, bool strict) {
if (OldPrefix.empty() && NewPrefix.empty())
- return;
+ return false;
StringRef OrigPath(Path.begin(), Path.size());
- if (!OrigPath.startswith(OldPrefix))
- return;
+ StringRef OldPrefixDir;
+
+ if (!strict && OldPrefix.size() > OrigPath.size())
+ return false;
+
+ // Ensure OldPrefixDir does not have a trailing separator.
+ if (!OldPrefix.empty() && is_separator(OldPrefix.back()))
+ OldPrefixDir = parent_path(OldPrefix, style);
+ else
+ OldPrefixDir = OldPrefix;
+
+ if (!OrigPath.startswith(OldPrefixDir))
+ return false;
+
+ if (OrigPath.size() > OldPrefixDir.size())
+ if (!is_separator(OrigPath[OldPrefixDir.size()], style) && strict)
+ return false;
// If prefixes have the same size we can simply copy the new one over.
- if (OldPrefix.size() == NewPrefix.size()) {
+ if (OldPrefixDir.size() == NewPrefix.size() && !strict) {
llvm::copy(NewPrefix, Path.begin());
- return;
+ return true;
}
- StringRef RelPath = OrigPath.substr(OldPrefix.size());
+ StringRef RelPath = OrigPath.substr(OldPrefixDir.size());
SmallString<256> NewPath;
path::append(NewPath, style, NewPrefix);
- path::append(NewPath, style, RelPath);
+ if (!RelPath.empty()) {
+ if (!is_separator(RelPath[0], style) || !strict)
+ path::append(NewPath, style, RelPath);
+ else
+ path::append(NewPath, style, relative_path(RelPath, style));
+ }
+
Path.swap(NewPath);
+
+ return true;
}
void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
diff --git a/llvm/unittests/Support/Path.cpp b/llvm/unittests/Support/Path.cpp
index 9de46a689cd..1f7a10d94f2 100644
--- a/llvm/unittests/Support/Path.cpp
+++ b/llvm/unittests/Support/Path.cpp
@@ -1230,7 +1230,9 @@ TEST(Support, RemoveDots) {
TEST(Support, ReplacePathPrefix) {
SmallString<64> Path1("/foo");
SmallString<64> Path2("/old/foo");
+ SmallString<64> Path3("/oldnew/foo");
SmallString<64> OldPrefix("/old");
+ SmallString<64> OldPrefixSep("/old/");
SmallString<64> NewPrefix("/new");
SmallString<64> NewPrefix2("/longernew");
SmallString<64> EmptyPrefix("");
@@ -1250,6 +1252,33 @@ TEST(Support, ReplacePathPrefix) {
Path = Path2;
path::replace_path_prefix(Path, OldPrefix, EmptyPrefix);
EXPECT_EQ(Path, "/foo");
+ Path = Path2;
+ path::replace_path_prefix(Path, OldPrefix, EmptyPrefix, true);
+ EXPECT_EQ(Path, "foo");
+ Path = Path3;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix, false);
+ EXPECT_EQ(Path, "/newnew/foo");
+ Path = Path3;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix, true);
+ EXPECT_EQ(Path, "/oldnew/foo");
+ Path = Path3;
+ path::replace_path_prefix(Path, OldPrefixSep, NewPrefix, true);
+ EXPECT_EQ(Path, "/oldnew/foo");
+ Path = Path1;
+ path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
+ EXPECT_EQ(Path, "/new/foo");
+ Path = OldPrefix;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_EQ(Path, "/new");
+ Path = OldPrefixSep;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_EQ(Path, "/new/");
+ Path = OldPrefix;
+ path::replace_path_prefix(Path, OldPrefixSep, NewPrefix, false);
+ EXPECT_EQ(Path, "/old");
+ Path = OldPrefix;
+ path::replace_path_prefix(Path, OldPrefixSep, NewPrefix, true);
+ EXPECT_EQ(Path, "/new");
}
TEST_F(FileSystemTest, OpenFileForRead) {
OpenPOWER on IntegriCloud