[PATCH] support: add a utility function to canonicalise path separators

Saleem Abdulrasool abdulras at fb.com
Thu Mar 6 14:30:27 PST 2014


Hi majnemer,

Add a utility function to convert the Windows path separator to Unix style path
separators.  This is used by a subsequent change in clang to enable the use of
Windows SDK on Linux.


http://llvm-reviews.chandlerc.com/D2995

Files:
  include/llvm/Support/FileSystem.h
  lib/Support/Path.cpp
  unittests/Support/Path.cpp

Index: include/llvm/Support/FileSystem.h
===================================================================
--- include/llvm/Support/FileSystem.h
+++ include/llvm/Support/FileSystem.h
@@ -270,6 +270,13 @@
 ///          platform specific error_code.
 error_code make_absolute(SmallVectorImpl<char> &path);
 
+/// @brief Normalize path separators in \a Path
+///
+/// If the path contains any '\' seprators, they are transformed into '/'.  This
+/// is particularly useful when cross-compiling Windows on Linux, but is safe to
+/// do on Windows, which accepts both characters as a path separtor.
+error_code normalise_separators(SmallVectorImpl<char> &Path);
+
 /// @brief Create all the non-existent directories in path.
 ///
 /// @param path Directories to create.
Index: lib/Support/Path.cpp
===================================================================
--- lib/Support/Path.cpp
+++ lib/Support/Path.cpp
@@ -818,6 +818,20 @@
                    "occurred above!");
 }
 
+error_code normalise_separators(SmallVectorImpl<char> &Path) {
+#if defined(LLVM_ON_WIN32)
+  (void) Path;
+#else
+  for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
+    if (*PI == '\\' && *(PI + 1) == '\\')
+      ++PI; // increment once, the for loop will increment over the escaped slash
+    else if (*PI == '\\')
+      *PI = '/';
+  }
+#endif
+  return error_code::success();
+}
+
 error_code create_directories(const Twine &Path, bool IgnoreExisting) {
   SmallString<128> PathStorage;
   StringRef P = Path.toStringRef(PathStorage);
Index: unittests/Support/Path.cpp
===================================================================
--- unittests/Support/Path.cpp
+++ unittests/Support/Path.cpp
@@ -591,4 +591,35 @@
   fs::mapped_file_region mfrrv(std::move(m));
   EXPECT_EQ(mfrrv.const_data(), Data);
 }
+
+TEST(Support, NormalizePath) {
+#if defined(LLVM_ON_WIN32)
+#define EXPECT_PATH_IS(path__, windows__, not_windows__)                        \
+  EXPECT_EQ(path__, windows__);
+#else
+#define EXPECT_PATH_IS(path__, windows__, not_windows__)                        \
+  EXPECT_EQ(path__, not_windows__);
+#endif
+
+  SmallString<64> Path1("a");
+  SmallString<64> Path2("a/b");
+  SmallString<64> Path3("a\\b");
+  SmallString<64> Path4("a\\\\b");
+  SmallString<64> Path5("\\a");
+  SmallString<64> Path6("a\\");
+  ASSERT_NO_ERROR(fs::normalise_separators(Path1));
+  EXPECT_PATH_IS(Path1, "a", "a");
+  ASSERT_NO_ERROR(fs::normalise_separators(Path2));
+  EXPECT_PATH_IS(Path2, "a/b", "a/b");
+  ASSERT_NO_ERROR(fs::normalise_separators(Path3));
+  EXPECT_PATH_IS(Path3, "a\b", "a/b");
+  ASSERT_NO_ERROR(fs::normalise_separators(Path4));
+  EXPECT_PATH_IS(Path4, "a\\\\b", "a\\\\b");
+  ASSERT_NO_ERROR(fs::normalise_separators(Path5));
+  EXPECT_PATH_IS(Path5, "\\a", "/a");
+  ASSERT_NO_ERROR(fs::normalise_separators(Path6));
+  EXPECT_PATH_IS(Path6, "a\\", "a/");
+
+#undef EXPECT_PATH_IS
+}
 } // anonymous namespace
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2995.1.patch
Type: text/x-patch
Size: 2938 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140306/cbd05f59/attachment.bin>


More information about the llvm-commits mailing list