]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
C++-ify common_dir_prefix_length
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 19 Feb 2020 18:18:01 +0000 (19:18 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Sun, 23 Feb 2020 20:03:34 +0000 (21:03 +0100)
src/Util.cpp
src/Util.hpp
src/legacy_util.cpp
src/legacy_util.hpp
unittest/test_Util.cpp
unittest/test_legacy_util.cpp

index b75e3d47efcad2c649bb775433c471c51b01d213..e3bf60c36e322939293fb1722bf3c88c603d8c95 100644 (file)
@@ -112,6 +112,33 @@ change_extension(string_view path, string_view new_ext)
   return std::string(without_ext).append(new_ext.data(), new_ext.length());
 }
 
+size_t
+common_dir_prefix_length(string_view dir, string_view path)
+{
+  if (dir.empty() || path.empty() || dir == "/" || path == "/") {
+    return 0;
+  }
+
+  const size_t limit = std::min(dir.length(), path.length());
+  size_t i = 0;
+
+  while (i < limit && dir[i] == path[i]) {
+    ++i;
+  }
+
+  if ((i == dir.length() && i == path.length())
+      || (i == dir.length() && path[i] == '/')
+      || (i == path.length() && dir[i] == '/')) {
+    return i;
+  }
+
+  do {
+    --i;
+  } while (i > 0 && i != string_view::npos && dir[i] != '/' && path[i] != '/');
+
+  return i;
+}
+
 bool
 create_dir(string_view dir)
 {
index 2797f914b69b6e4491879e3cd360f180799bee28..3f6b3be4570c9633e764b078e720fb61142f7363 100644 (file)
@@ -77,6 +77,11 @@ big_endian_to_int(const uint8_t* buffer, uint8_t& value)
 std::string change_extension(nonstd::string_view path,
                              nonstd::string_view new_ext);
 
+// Compute the length of the longest directory path that is common to paths
+// `dir` (a directory) and `path` (any path).
+size_t common_dir_prefix_length(nonstd::string_view dir,
+                                nonstd::string_view path);
+
 // Create a directory if needed, including its parents if needed.
 //
 // Returns true if the directory exists or could be created, otherwise false.
index f7c43b3242e4fc267616f55bf3c77967587cfe82..1b89a18056d0ebe9f5380299bb30d2833ca2ab7a 100644 (file)
@@ -708,29 +708,6 @@ same_executable_name(const char* s1, const char* s2)
 #endif
 }
 
-// Compute the length of the longest directory path that is common to two
-// paths. s1 is assumed to be the path to a directory.
-size_t
-common_dir_prefix_length(const char* s1, const char* s2)
-{
-  const char* p1 = s1;
-  const char* p2 = s2;
-
-  while (*p1 && *p2 && *p1 == *p2) {
-    ++p1;
-    ++p2;
-  }
-  while ((*p1 && *p1 != '/') || (*p2 && *p2 != '/')) {
-    p1--;
-    p2--;
-  }
-  if (!*p1 && !*p2 && p2 == s2 + 1) {
-    // Special case for s1 and s2 both being "/".
-    return 0;
-  }
-  return p1 - s1;
-}
-
 // Compute a relative path from from (an absolute path to a directory) to to (a
 // path). Assumes that both from and to are well-formed and canonical. Caller
 // frees.
@@ -762,7 +739,7 @@ get_relative_path(const char* from, const char* to)
 #endif
 
   result = x_strdup("");
-  common_prefix_len = common_dir_prefix_length(from, to);
+  common_prefix_len = Util::common_dir_prefix_length(from, to);
   if (common_prefix_len > 0 || !str_eq(from, "/")) {
     const char* p;
     for (p = from + common_prefix_len; *p; p++) {
index 9acd09781e71e88c8a0d189bb5e7c14e9d950a51..329d26ffd2f4f7f9d0e211ac95f177c1a82c6a63 100644 (file)
@@ -54,7 +54,6 @@ int create_tmp_fd(char** fname);
 FILE* create_tmp_file(char** fname, const char* mode);
 const char* get_home_directory();
 bool same_executable_name(const char* s1, const char* s2);
-size_t common_dir_prefix_length(const char* s1, const char* s2);
 char* get_relative_path(const char* from, const char* to);
 bool is_full_path(const char* path);
 void update_mtime(const char* path);
index c6de9eda9068ba12fb2fe69bb7d7d06913622aba..97e8cc5bf3fb3d5b8a07f4fdfcb663ebfea39523 100644 (file)
@@ -86,6 +86,24 @@ TEST_CASE("Util::change_extension")
   CHECK(Util::change_extension("foo.bar.txt", ".o") == "foo.bar.o");
 }
 
+TEST_CASE("Util::common_dir_prefix_length")
+{
+  CHECK(Util::common_dir_prefix_length("", "") == 0);
+  CHECK(Util::common_dir_prefix_length("/", "") == 0);
+  CHECK(Util::common_dir_prefix_length("", "/") == 0);
+  CHECK(Util::common_dir_prefix_length("/", "/") == 0);
+  CHECK(Util::common_dir_prefix_length("/", "/b") == 0);
+  CHECK(Util::common_dir_prefix_length("/a", "/") == 0);
+  CHECK(Util::common_dir_prefix_length("/a", "/b") == 0);
+  CHECK(Util::common_dir_prefix_length("/a", "/a") == 2);
+  CHECK(Util::common_dir_prefix_length("/a", "/a/b") == 2);
+  CHECK(Util::common_dir_prefix_length("/a/b", "/a") == 2);
+  CHECK(Util::common_dir_prefix_length("/a/b", "/a/c") == 2);
+  CHECK(Util::common_dir_prefix_length("/a/b", "/a/b") == 4);
+  CHECK(Util::common_dir_prefix_length("/a/bc", "/a/b") == 2);
+  CHECK(Util::common_dir_prefix_length("/a/b", "/a/bc") == 2);
+}
+
 TEST_CASE("Util::create_dir")
 {
   CHECK(Util::create_dir("/"));
index dad59f16bdda03d6140b145677e962c052b73a7d..3dc7338baf85b796c2324ef3d21d506e6692f006 100644 (file)
@@ -35,20 +35,6 @@ TEST(x_dirname)
   CHECK_STR_EQ_FREE2("dir1/dir2", x_dirname("dir1/dir2/"));
 }
 
-TEST(common_dir_prefix_length)
-{
-  CHECK_INT_EQ(0, common_dir_prefix_length("", ""));
-  CHECK_INT_EQ(0, common_dir_prefix_length("/", "/"));
-  CHECK_INT_EQ(0, common_dir_prefix_length("/", "/b"));
-  CHECK_INT_EQ(0, common_dir_prefix_length("/a", "/b"));
-  CHECK_INT_EQ(2, common_dir_prefix_length("/a", "/a"));
-  CHECK_INT_EQ(2, common_dir_prefix_length("/a", "/a/b"));
-  CHECK_INT_EQ(2, common_dir_prefix_length("/a/b", "/a/c"));
-  CHECK_INT_EQ(4, common_dir_prefix_length("/a/b", "/a/b"));
-  CHECK_INT_EQ(2, common_dir_prefix_length("/a/bc", "/a/b"));
-  CHECK_INT_EQ(2, common_dir_prefix_length("/a/b", "/a/bc"));
-}
-
 TEST(get_relative_path)
 {
 #ifdef _WIN32