]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
refactor: Move Win32Util::argv_to_string to util
authorJoel Rosdahl <joel@rosdahl.net>
Mon, 2 Oct 2023 16:38:05 +0000 (18:38 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Mon, 2 Oct 2023 19:33:49 +0000 (21:33 +0200)
src/Win32Util.cpp
src/Win32Util.hpp
src/execute.cpp
src/hashutil.cpp
src/util/string.cpp
src/util/string.hpp
unittest/CMakeLists.txt
unittest/test_Win32Util.cpp [deleted file]
unittest/test_util_string.cpp

index 340430b50c2568a7daaf97055d3dd239e61f63ba..d50a4bd63a9ae0044ce88d4235f688f2249162e5 100644 (file)
@@ -49,49 +49,4 @@ error_message(DWORD error_code)
   return message;
 }
 
-std::string
-argv_to_string(const char* const* argv,
-               const std::string& prefix,
-               bool escape_backslashes)
-{
-  std::string result;
-  size_t i = 0;
-  const char* arg = prefix.empty() ? argv[i++] : prefix.c_str();
-
-  do {
-    int bs = 0;
-    result += '"';
-    for (size_t j = 0; arg[j]; ++j) {
-      switch (arg[j]) {
-      case '\\':
-        if (!escape_backslashes) {
-          ++bs;
-          break;
-        }
-        [[fallthrough]];
-
-      case '"':
-        bs = (bs << 1) + 1;
-        [[fallthrough]];
-
-      default:
-        while (bs > 0) {
-          result += '\\';
-          --bs;
-        }
-        result += arg[j];
-      }
-    }
-    bs <<= 1;
-    while (bs > 0) {
-      result += '\\';
-      --bs;
-    }
-    result += "\" ";
-  } while ((arg = argv[i++]));
-
-  result.resize(result.length() - 1);
-  return result;
-}
-
 } // namespace Win32Util
index 0130e90b5e8dd8dff2c0adf0ac42e637a0e82a33..b73224090db9491bc68907ac02eafef85c80df91 100644 (file)
 
 namespace Win32Util {
 
-// Recreate a Windows command line string based on `argv`. If `prefix` is
-// non-empty, add it as the first argument. If `escape_backslashes` is true,
-// emit an additional backslash for each backslash that is not preceding '"' and
-// is not at the end of `argv[i]` either.
-std::string argv_to_string(const char* const* argv,
-                           const std::string& prefix,
-                           bool escape_backslashes = false);
-
 // Return the error message corresponding to `error_code`.
 std::string error_message(DWORD error_code);
 
index 2b23b54b26b83cf8ce579f0a5e970ad8e48d0ddf..6c52fa874ae24fdf5b6bdfdfdbe8ae5f57177352 100644 (file)
@@ -216,7 +216,7 @@ win32execute(const char* path,
     }
   }
 
-  std::string args = Win32Util::argv_to_string(argv, sh);
+  std::string args = util::format_argv_as_win32_command_string(argv, sh);
   std::string full_path = util::add_exe_suffix(path);
   fs::path tmp_file_path;
 
@@ -229,7 +229,7 @@ win32execute(const char* path,
   if (args.length() > 8192) {
     auto tmp_file = util::value_or_throw<core::Fatal>(
       util::TemporaryFile::create(FMT("{}/cmd_args", temp_dir)));
-    args = Win32Util::argv_to_string(argv + 1, sh, true);
+    args = util::format_argv_as_win32_command_string(argv + 1, sh, true);
     util::write_fd(*tmp_file.fd, args.data(), args.length());
     args = FMT(R"("{}" "@{}")", full_path, tmp_file.path);
     tmp_file_path = tmp_file.path;
index ede7732095e003f3c4a9d9d4095422a6c114fb6b..7665c4e00a4fd8cd10265eaa9efa0b4908e1d5f3 100644 (file)
@@ -406,7 +406,7 @@ hash_command_output(Hash& hash,
   if (using_cmd_exe) {
     win32args = adjusted_command; // quoted
   } else {
-    win32args = Win32Util::argv_to_string(argv.data(), sh);
+    win32args = util::format_argv_as_win32_command_string(argv.data(), sh);
   }
   BOOL ret = CreateProcess(path.c_str(),
                            const_cast<char*>(win32args.c_str()),
index 8db2f04642babc2d0fbca9d014c625986392f7a4..45f80dc0269dc22df6b31c630e0fb8c418748344 100644 (file)
@@ -47,6 +47,51 @@ split_into(std::string_view string,
 
 namespace util {
 
+std::string
+format_argv_as_win32_command_string(const char* const* argv,
+                                    const std::string& prefix,
+                                    bool escape_backslashes)
+{
+  std::string result;
+  size_t i = 0;
+  const char* arg = prefix.empty() ? argv[i++] : prefix.c_str();
+
+  do {
+    int bs = 0;
+    result += '"';
+    for (size_t j = 0; arg[j]; ++j) {
+      switch (arg[j]) {
+      case '\\':
+        if (!escape_backslashes) {
+          ++bs;
+          break;
+        }
+        [[fallthrough]];
+
+      case '"':
+        bs = (bs << 1) + 1;
+        [[fallthrough]];
+
+      default:
+        while (bs > 0) {
+          result += '\\';
+          --bs;
+        }
+        result += arg[j];
+      }
+    }
+    bs <<= 1;
+    while (bs > 0) {
+      result += '\\';
+      --bs;
+    }
+    result += "\" ";
+  } while ((arg = argv[i++]));
+
+  result.resize(result.length() - 1);
+  return result;
+}
+
 std::string
 format_argv_for_logging(const char* const* argv)
 {
index 3b263651adf4c684ca77a1cbd154df070bf23e5a..4c981eb3481de375fd3658346384822ba78e3a66 100644 (file)
@@ -45,6 +45,15 @@ enum class SizeUnitPrefixType { binary, decimal };
 // Return true if `suffix` is a suffix of `string`.
 bool ends_with(std::string_view string, std::string_view suffix);
 
+// Recreate a Windows command line string based on `argv`. If `prefix` is
+// non-empty, add it as the first argument. If `escape_backslashes` is true,
+// emit an additional backslash for each backslash that is not preceding '"' and
+// is not at the end of `argv[i]` either.
+std::string
+format_argv_as_win32_command_string(const char* const* argv,
+                                    const std::string& prefix,
+                                    bool escape_backslashes = false);
+
 // Format `argv` as a simple string for logging purposes. That is, the result is
 // not intended to be easily machine parsable. `argv` must be terminated by a
 // nullptr.
index a34c57df3face5a0d203ee242177f8480b557a2b..b2bacc3a682b132c7981724e489218b5012db20b 100644 (file)
@@ -44,7 +44,7 @@ if(INODE_CACHE_SUPPORTED)
 endif()
 
 if(WIN32)
-  list(APPEND source_files test_bsdmkstemp.cpp test_Win32Util.cpp)
+  list(APPEND source_files test_bsdmkstemp.cpp)
 endif()
 
 file(GLOB headers *.hpp)
diff --git a/unittest/test_Win32Util.cpp b/unittest/test_Win32Util.cpp
deleted file mode 100644 (file)
index cff6a7f..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (C) 2020 Joel Rosdahl and other contributors
-//
-// See doc/AUTHORS.adoc for a complete list of contributors.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, write to the Free Software Foundation, Inc., 51
-// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-#include "../src/Win32Util.hpp"
-#include "TestUtil.hpp"
-
-#include "third_party/doctest.h"
-
-#include <iostream>
-
-TEST_SUITE_BEGIN("Win32Util");
-
-TEST_CASE("Win32Util::argv_to_string")
-{
-  {
-    const char* const argv[] = {"a", nullptr};
-    CHECK(Win32Util::argv_to_string(argv, "") == R"("a")");
-  }
-  {
-    const char* const argv[] = {"a", nullptr};
-    CHECK(Win32Util::argv_to_string(argv, "p") == R"("p" "a")");
-  }
-  {
-    const char* const argv[] = {"a", "b c", "\"d\"", "'e'", "\\\"h", nullptr};
-    CHECK(Win32Util::argv_to_string(argv, "")
-          == R"("a" "b c" "\"d\"" "'e'" "\\\"h")");
-  }
-  {
-    const char* const argv[] = {"a\\b\\c", nullptr};
-    CHECK(Win32Util::argv_to_string(argv, "") == R"("a\b\c")");
-  }
-  {
-    const char* const argv[] = {"a\\b\\c", nullptr};
-    CHECK(Win32Util::argv_to_string(argv, "", true) == R"("a\\b\\c")");
-  }
-  {
-    const char* const argv[] = {R"(a\b \"c\" \)", nullptr};
-    CHECK(Win32Util::argv_to_string(argv, "") == R"("a\b \\\"c\\\" \\")");
-  }
-  {
-    const char* const argv[] = {R"(a\b \"c\" \)", nullptr};
-    CHECK(Win32Util::argv_to_string(argv, "", true)
-          == R"("a\\b \\\"c\\\" \\")");
-  }
-}
-
-TEST_SUITE_END();
index 8410c8228fa499ac20eb338e7bc3447a33fa9453..1c49d70d549f2378dc57aa6cc298b76bb5cba378 100644 (file)
@@ -39,6 +39,42 @@ operator==(std::pair<std::string_view, std::optional<std::string_view>> left,
 
 TEST_SUITE_BEGIN("util");
 
+TEST_CASE("util::format_argv_as_win32_command_string")
+{
+  {
+    const char* const argv[] = {"a", nullptr};
+    CHECK(util::format_argv_as_win32_command_string(argv, "") == R"("a")");
+  }
+  {
+    const char* const argv[] = {"a", nullptr};
+    CHECK(util::format_argv_as_win32_command_string(argv, "p") == R"("p" "a")");
+  }
+  {
+    const char* const argv[] = {"a", "b c", "\"d\"", "'e'", "\\\"h", nullptr};
+    CHECK(util::format_argv_as_win32_command_string(argv, "")
+          == R"("a" "b c" "\"d\"" "'e'" "\\\"h")");
+  }
+  {
+    const char* const argv[] = {"a\\b\\c", nullptr};
+    CHECK(util::format_argv_as_win32_command_string(argv, "") == R"("a\b\c")");
+  }
+  {
+    const char* const argv[] = {"a\\b\\c", nullptr};
+    CHECK(util::format_argv_as_win32_command_string(argv, "", true)
+          == R"("a\\b\\c")");
+  }
+  {
+    const char* const argv[] = {R"(a\b \"c\" \)", nullptr};
+    CHECK(util::format_argv_as_win32_command_string(argv, "")
+          == R"("a\b \\\"c\\\" \\")");
+  }
+  {
+    const char* const argv[] = {R"(a\b \"c\" \)", nullptr};
+    CHECK(util::format_argv_as_win32_command_string(argv, "", true)
+          == R"("a\\b \\\"c\\\" \\")");
+  }
+}
+
 TEST_CASE("util::format_argv_for_logging")
 {
   SUBCASE("nullptr")