From f0e0201c2da3c3e4969fc911f8e302c5469c5423 Mon Sep 17 00:00:00 2001 From: Dmitry-Me Date: Mon, 16 Feb 2015 13:11:13 +0300 Subject: [PATCH] Better handle double slashes, more tests --- lib/path.cpp | 18 ++++++++++++++++-- test/testpath.cpp | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/path.cpp b/lib/path.cpp index 569818653..e9359c026 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -60,6 +60,8 @@ std::string Path::fromNativeSeparators(std::string path) std::string Path::simplifyPath(std::string originalPath) { + const bool isUnc = originalPath.size() > 2 && originalPath[0] == '/' && originalPath[1] == '/'; + // Remove ./, .//, ./// etc. at the beginning if (originalPath.size() > 2 && originalPath[0] == '.' && originalPath[1] == '/') { @@ -90,6 +92,14 @@ std::string Path::simplifyPath(std::string originalPath) if (subPath.length() > 0) pathParts.push_back(subPath); + // First filter out all double slashes + for (unsigned int i = 1; i < pathParts.size(); ++i) { + if (i > 0 && pathParts[i] == "/" && pathParts[i-1] == "/") { + pathParts.erase(pathParts.begin() + static_cast(i) - 1); + --i; + } + } + for (unsigned int i = 1; i < pathParts.size(); ++i) { if (i > 1 && pathParts[i-2] != ".." && pathParts[i] == ".." && pathParts.size() > i + 1) { pathParts.erase(pathParts.begin() + static_cast(i) + 1); @@ -100,13 +110,17 @@ std::string Path::simplifyPath(std::string originalPath) } else if (i > 0 && pathParts[i] == ".") { pathParts.erase(pathParts.begin() + static_cast(i)); i = 0; - // Don't touch leading "//" which means a UNC path - } else if (i > 1 && pathParts[i] == "/" && pathParts[i-1] == "/") { + } else if (i > 0 && pathParts[i] == "/" && pathParts[i-1] == "/") { pathParts.erase(pathParts.begin() + static_cast(i) - 1); i = 0; } } + if (isUnc) { + // Restore the leading double slash + pathParts.insert(pathParts.begin(), "/"); + } + std::ostringstream oss; for (std::vector::size_type i = 0; i < pathParts.size(); ++i) { oss << pathParts[i]; diff --git a/test/testpath.cpp b/test/testpath.cpp index c26e6977d..fb61a5d00 100644 --- a/test/testpath.cpp +++ b/test/testpath.cpp @@ -40,13 +40,33 @@ private: // Path::simplifyPath() ASSERT_EQUALS("index.h", Path::simplifyPath("index.h")); ASSERT_EQUALS("index.h", Path::simplifyPath("./index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath(".//index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath(".///index.h")); ASSERT_EQUALS("/index.h", Path::simplifyPath("/index.h")); ASSERT_EQUALS("/path/", Path::simplifyPath("/path/")); ASSERT_EQUALS("/", Path::simplifyPath("/")); + ASSERT_EQUALS("/", Path::simplifyPath("/.")); + ASSERT_EQUALS("/", Path::simplifyPath("/./")); + ASSERT_EQUALS("/index.h", Path::simplifyPath("/./index.h")); + ASSERT_EQUALS("/", Path::simplifyPath("/.//")); + ASSERT_EQUALS("/index.h", Path::simplifyPath("/.//index.h")); ASSERT_EQUALS("../index.h", Path::simplifyPath("../index.h")); ASSERT_EQUALS("/index.h", Path::simplifyPath("/path/../index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath("./path/../index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath("path/../index.h")); + ASSERT_EQUALS("/index.h", Path::simplifyPath("/path//../index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath("./path//../index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath("path//../index.h")); + ASSERT_EQUALS("/index.h", Path::simplifyPath("/path/..//index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath("./path/..//index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath("path/..//index.h")); + ASSERT_EQUALS("/index.h", Path::simplifyPath("/path//..//index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath("./path//..//index.h")); + ASSERT_EQUALS("index.h", Path::simplifyPath("path//..//index.h")); ASSERT_EQUALS("/index.h", Path::simplifyPath("/path/../other/../index.h")); ASSERT_EQUALS("/index.h", Path::simplifyPath("/path/../other///././../index.h")); + ASSERT_EQUALS("/index.h", Path::simplifyPath("/path/../other/././..///index.h")); + ASSERT_EQUALS("/index.h", Path::simplifyPath("/path/../other///././..///index.h")); ASSERT_EQUALS("../path/index.h", Path::simplifyPath("../path/other/../index.h")); ASSERT_EQUALS("a/index.h", Path::simplifyPath("a/../a/index.h")); ASSERT_EQUALS("a/..", Path::simplifyPath("a/.."));