]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
refactor: Remove now unnecessary util::{starts,ends}_with master
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 4 Feb 2026 20:14:53 +0000 (21:14 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 7 Feb 2026 17:44:49 +0000 (18:44 +0100)
14 files changed:
src/ccache/argprocessing.cpp
src/ccache/ccache.cpp
src/ccache/compiler/msvc.cpp
src/ccache/config.cpp
src/ccache/core/common.cpp
src/ccache/storage/local/util.cpp
src/ccache/storage/remote/helper.cpp
src/ccache/util/args.cpp
src/ccache/util/string.cpp
src/ccache/util/string.hpp
unittest/test_argprocessing.cpp
unittest/test_util_exec.cpp
unittest/test_util_file.cpp
unittest/test_util_string.cpp

index 40461349c44ba7212d7e6ddb0a7a5baeb8b34743..ab16295d5d16f90ee727735690134e8332545ff7 100644 (file)
@@ -276,11 +276,11 @@ process_profiling_option(const Context& ctx,
     return true;
   }
 
-  if (util::starts_with(arg, "-fprofile-update")) {
+  if (arg.starts_with("-fprofile-update")) {
     return true;
   }
 
-  if (util::starts_with(arg, "-fprofile-prefix-path=")) {
+  if (arg.starts_with("-fprofile-prefix-path=")) {
     args_info.profile_prefix_path = arg.substr(arg.find('=') + 1);
     LOG("Set profile prefix path to {}", args_info.profile_prefix_path);
     return true;
@@ -289,7 +289,7 @@ process_profiling_option(const Context& ctx,
   fs::path new_profile_path;
   bool new_profile_use = false;
 
-  if (util::starts_with(arg, "-fprofile-dir=")) {
+  if (arg.starts_with("-fprofile-dir=")) {
     new_profile_path = arg.substr(arg.find('=') + 1);
   } else if (arg == "-fprofile-generate" || arg == "-fprofile-instr-generate") {
     args_info.profile_generate = true;
@@ -299,8 +299,8 @@ process_profiling_option(const Context& ctx,
       // GCC uses $PWD/$(basename $obj).
       new_profile_path = ctx.apparent_cwd;
     }
-  } else if (util::starts_with(arg, "-fprofile-generate=")
-             || util::starts_with(arg, "-fprofile-instr-generate=")) {
+  } else if (arg.starts_with("-fprofile-generate=")
+             || arg.starts_with("-fprofile-instr-generate=")) {
     args_info.profile_generate = true;
     new_profile_path = arg.substr(arg.find('=') + 1);
   } else if (arg == "-fprofile-use" || arg == "-fprofile-instr-use"
@@ -310,10 +310,10 @@ process_profiling_option(const Context& ctx,
     if (args_info.profile_path.empty()) {
       new_profile_path = ".";
     }
-  } else if (util::starts_with(arg, "-fprofile-use=")
-             || util::starts_with(arg, "-fprofile-instr-use=")
-             || util::starts_with(arg, "-fprofile-sample-use=")
-             || util::starts_with(arg, "-fauto-profile=")) {
+  } else if (arg.starts_with("-fprofile-use=")
+             || arg.starts_with("-fprofile-instr-use=")
+             || arg.starts_with("-fprofile-sample-use=")
+             || arg.starts_with("-fauto-profile=")) {
     new_profile_use = true;
     new_profile_path = arg.substr(arg.find('=') + 1);
   } else {
@@ -347,7 +347,7 @@ std::string
 make_dash_option(const Config& config, const std::string& arg)
 {
   std::string new_arg = arg;
-  if (config.is_compiler_group_msvc() && util::starts_with(arg, "/")) {
+  if (config.is_compiler_group_msvc() && arg.starts_with("/")) {
     // MSVC understands both /option and -option, so convert all /option to
     // -option to simplify our handling.
     new_arg[0] = '-';
@@ -419,7 +419,7 @@ process_option_arg(const Context& ctx,
   }
 
   // Handle "@file" argument.
-  if (util::starts_with(arg, "@") || util::starts_with(arg, "-@")) {
+  if (arg.starts_with("@") || arg.starts_with("-@")) {
     const char* argpath = arg.c_str() + 1;
 
     if (argpath[-1] == '-') {
@@ -469,10 +469,9 @@ process_option_arg(const Context& ctx,
   }
 
   // These are always too hard.
-  if (compopt_too_hard(arg) || util::starts_with(arg, "-fdump-")
-      || util::starts_with(arg, "-MJ")
-      || util::starts_with(arg, "--config-system-dir=")
-      || util::starts_with(arg, "--config-user-dir=")) {
+  if (compopt_too_hard(arg) || arg.starts_with("-fdump-")
+      || arg.starts_with("-MJ") || arg.starts_with("--config-system-dir=")
+      || arg.starts_with("--config-user-dir=")) {
     LOG("Compiler option {} is unsupported", args[i]);
     return Statistic::unsupported_compiler_option;
   }
@@ -484,7 +483,7 @@ process_option_arg(const Context& ctx,
   }
 
   // Handle -Xpreprocessor options.
-  if (util::starts_with(arg, "-Xpreprocessor")) {
+  if (arg.starts_with("-Xpreprocessor")) {
     if (i == args.size() - 1) {
       LOG("Missing argument to {}", args[i]);
       return Statistic::bad_compiler_arguments;
@@ -498,7 +497,7 @@ process_option_arg(const Context& ctx,
   }
 
   // Handle -Xarch_* options.
-  if (util::starts_with(arg, "-Xarch_")) {
+  if (arg.starts_with("-Xarch_")) {
     if (i == args.size() - 1) {
       LOG("Missing argument to {}", args[i]);
       return Statistic::bad_compiler_arguments;
@@ -542,9 +541,9 @@ process_option_arg(const Context& ctx,
     arg = make_dash_option(ctx.config, args[i]);
   }
 
-  if (util::starts_with(arg, "-Wa,")) {
+  if (arg.starts_with("-Wa,")) {
     for (const auto part : util::Tokenizer(&arg[4], ",")) {
-      if (util::starts_with(part, "-a")) {
+      if (part.starts_with("-a")) {
         if (state.found_Wa_a_opt) {
           LOG_RAW(
             "Multiple assembler listing options (-Wa,-a) are not supported");
@@ -622,13 +621,13 @@ process_option_arg(const Context& ctx,
 
   if (config.is_compiler_group_msvc()) {
     // MSVC /Fo with no space.
-    if (util::starts_with(arg, "-Fo")) {
+    if (arg.starts_with("-Fo")) {
       args_info.output_obj = arg.substr(3);
       return Statistic::none;
     }
 
     // MSVC /Tc and /Tp options in concatenated form for specifying input file.
-    if (arg.length() > 3 && util::starts_with(arg, "-T")
+    if (arg.length() > 3 && arg.starts_with("-T")
         && (arg[2] == 'c' || arg[2] == 'p')) {
       args_info.input_file_prefix = arg.substr(0, 3);
       state.input_files.emplace_back(arg.substr(3));
@@ -669,7 +668,7 @@ process_option_arg(const Context& ctx,
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "-x")) {
+  if (arg.starts_with("-x")) {
     if (arg.length() >= 3 && !util::is_lower(arg[2])) {
       // -xCODE (where CODE can be e.g. Host or CORE-AVX2, always starting with
       // an uppercase letter) is an ordinary Intel compiler option, not a
@@ -715,30 +714,29 @@ process_option_arg(const Context& ctx,
   // Cl does support it as deprecated, but also has -openmp or -link -out
   // which can confuse this and cause incorrect output_obj (and thus
   // ccache debug file location), so better ignore it.
-  if (util::starts_with(arg, "-o")
-      && config.compiler_type() != CompilerType::nvcc
+  if (arg.starts_with("-o") && config.compiler_type() != CompilerType::nvcc
       && config.compiler_type() != CompilerType::msvc) {
     args_info.output_obj = arg.substr(2);
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "-fdebug-prefix-map=")
-      || util::starts_with(arg, "-ffile-prefix-map=")) {
+  if (arg.starts_with("-fdebug-prefix-map=")
+      || arg.starts_with("-ffile-prefix-map=")) {
     std::string map = arg.substr(arg.find('=') + 1);
     args_info.debug_prefix_maps.push_back(map);
     state.add_common_arg(args[i]);
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "-fcoverage-prefix-map=")) {
+  if (arg.starts_with("-fcoverage-prefix-map=")) {
     std::string map = arg.substr(arg.find('=') + 1);
     args_info.coverage_prefix_maps.push_back(map);
     state.add_common_arg(args[i]);
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "-fdebug-compilation-dir")
-      || util::starts_with(arg, "-ffile-compilation-dir")) {
+  if (arg.starts_with("-fdebug-compilation-dir")
+      || arg.starts_with("-ffile-compilation-dir")) {
     std::string compilation_dir;
     // -ffile-compilation-dir cannot be followed by a space.
     if (arg == "-fdebug-compilation-dir") {
@@ -761,7 +759,7 @@ process_option_arg(const Context& ctx,
   }
 
   if (std::string_view prefix{"-fcoverage-compilation-dir="};
-      util::starts_with(arg, prefix)) {
+      arg.starts_with(prefix)) {
     args_info.coverage_compilation_dir = arg.substr(prefix.length());
     state.add_common_arg(args[i]);
     return Statistic::none;
@@ -769,17 +767,17 @@ process_option_arg(const Context& ctx,
 
   // Debugging is handled specially, so that we know if we can strip line
   // number info.
-  if (util::starts_with(arg, "-g")) {
+  if (arg.starts_with("-g")) {
     state.add_common_arg(args[i]);
 
-    if (util::starts_with(arg, "-gdwarf")) {
+    if (arg.starts_with("-gdwarf")) {
       // Selection of DWARF format (-gdwarf or -gdwarf-<version>) enables
       // debug info on level 2.
       args_info.generating_debuginfo = true;
       return Statistic::none;
     }
 
-    if (util::starts_with(arg, "-gz")) {
+    if (arg.starts_with("-gz")) {
       // -gz[=type] neither disables nor enables debug info.
       return Statistic::none;
     }
@@ -804,13 +802,13 @@ process_option_arg(const Context& ctx,
     return Statistic::none;
   }
 
-  if (config.is_compiler_group_msvc() && util::starts_with(arg, "-Fd")) {
+  if (config.is_compiler_group_msvc() && arg.starts_with("-Fd")) {
     state.add_compiler_only_arg_no_hash(args[i]);
     return Statistic::none;
   }
 
   if (config.is_compiler_group_msvc()
-      && (util::starts_with(arg, "-MP") || arg == "-FS")) {
+      && (arg.starts_with("-MP") || arg == "-FS")) {
     state.add_compiler_only_arg_no_hash(args[i]);
     return Statistic::none;
   }
@@ -830,7 +828,7 @@ process_option_arg(const Context& ctx,
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "-MF")
+  if (arg.starts_with("-MF")
       // nvcc -MF:
       || arg == "--dependency-output") {
     state.found_mf_opt = true;
@@ -865,8 +863,8 @@ process_option_arg(const Context& ctx,
   }
 
   if (!config.is_compiler_group_msvc()
-      && (util::starts_with(arg, "-MQ")
-          || util::starts_with(arg, "-MT")
+      && (arg.starts_with("-MQ")
+          || arg.starts_with("-MT")
           // nvcc -MT:
           || arg == "--dependency-target-name")) {
     const bool is_mq = arg[2] == 'Q';
@@ -904,8 +902,8 @@ process_option_arg(const Context& ctx,
   // MSVC -MD[d], -MT[d] and -LT[d] options are something different than GCC's
   // -MD etc.
   if (config.is_compiler_group_msvc()
-      && (util::starts_with(arg, "-MD") || util::starts_with(arg, "-MT")
-          || util::starts_with(arg, "-LD"))) {
+      && (arg.starts_with("-MD") || arg.starts_with("-MT")
+          || arg.starts_with("-LD"))) {
     // These affect compiler but also #define some things.
     state.add_common_arg(args[i]);
     return Statistic::none;
@@ -938,7 +936,7 @@ process_option_arg(const Context& ctx,
   }
 
   // This covers all the different marker cases
-  if (util::starts_with(arg, "-fcallgraph-info")) {
+  if (arg.starts_with("-fcallgraph-info")) {
     args_info.generating_callgraphinfo = true;
     state.add_common_arg(args[i]);
     return Statistic::none;
@@ -970,8 +968,7 @@ process_option_arg(const Context& ctx,
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "-fprofile-")
-      || util::starts_with(arg, "-fauto-profile")
+  if (arg.starts_with("-fprofile-") || arg.starts_with("-fauto-profile")
       || arg == "-fbranch-probabilities") {
     if (!process_profiling_option(ctx, args_info, arg)) {
       // The failure is logged by process_profiling_option.
@@ -981,7 +978,7 @@ process_option_arg(const Context& ctx,
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "-fsanitize-blacklist=")) {
+  if (arg.starts_with("-fsanitize-blacklist=")) {
     auto path = std::string_view(args[i]).substr(21);
     args_info.sanitize_blacklists.emplace_back(path);
     auto relpath = core::make_relative_path(ctx, path);
@@ -989,7 +986,7 @@ process_option_arg(const Context& ctx,
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "--sysroot=")) {
+  if (arg.starts_with("--sysroot=")) {
     auto path = std::string_view(arg).substr(10);
     auto relpath = core::make_relative_path(ctx, path);
     state.add_common_arg(FMT("--sysroot={}", relpath));
@@ -1028,12 +1025,12 @@ process_option_arg(const Context& ctx,
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "-Wp,")) {
-    if (arg.find(",-P,") != std::string::npos || util::ends_with(arg, ",-P")) {
+  if (arg.starts_with("-Wp,")) {
+    if (arg.find(",-P,") != std::string::npos || arg.ends_with(",-P")) {
       LOG("-P together with other preprocessor options is too hard: {}",
           args[i]);
       return Statistic::unsupported_compiler_option;
-    } else if (util::starts_with(arg, "-Wp,-MD,")
+    } else if (arg.starts_with("-Wp,-MD,")
                && arg.find(',', 8) == std::string::npos) {
       state.found_wp_md_or_mmd_opt = true;
       args_info.generating_dependencies = true;
@@ -1043,7 +1040,7 @@ process_option_arg(const Context& ctx,
       }
       state.add_compiler_only_arg(args[i]);
       return Statistic::none;
-    } else if (util::starts_with(arg, "-Wp,-MMD,")
+    } else if (arg.starts_with("-Wp,-MMD,")
                && arg.find(',', 9) == std::string::npos) {
       state.found_wp_md_or_mmd_opt = true;
       args_info.generating_dependencies = true;
@@ -1053,14 +1050,12 @@ process_option_arg(const Context& ctx,
       }
       state.add_compiler_only_arg(args[i]);
       return Statistic::none;
-    } else if ((util::starts_with(arg, "-Wp,-D")
-                || util::starts_with(arg, "-Wp,-U"))
+    } else if ((arg.starts_with("-Wp,-D") || arg.starts_with("-Wp,-U"))
                && arg.find(',', 6) == std::string::npos) {
       state.add_common_arg(args[i]);
       return Statistic::none;
     } else if (arg == "-Wp,-MP"
-               || (arg.size() > 8 && util::starts_with(arg, "-Wp,-M")
-                   && arg[7] == ','
+               || (arg.size() > 8 && arg.starts_with("-Wp,-M") && arg[7] == ','
                    && (arg[6] == 'F' || arg[6] == 'Q' || arg[6] == 'T')
                    && arg.find(',', 8) == std::string::npos)) {
       state.add_compiler_only_arg(args[i]);
@@ -1085,7 +1080,7 @@ process_option_arg(const Context& ctx,
   }
 
   // Input charset needs to be handled specially.
-  if (util::starts_with(arg, "-finput-charset=")) {
+  if (arg.starts_with("-finput-charset=")) {
     state.input_charset_option = args[i];
     return Statistic::none;
   }
@@ -1104,13 +1099,13 @@ process_option_arg(const Context& ctx,
 
   const std::string_view source_dep_directives_opt =
     "-sourceDependencies:directives";
-  if (util::starts_with(arg, source_dep_directives_opt)) {
+  if (arg.starts_with(source_dep_directives_opt)) {
     LOG("Compiler option {} is unsupported", args[i]);
     return Statistic::unsupported_compiler_option;
   }
 
   const std::string_view source_dep_opt = "-sourceDependencies";
-  if (util::starts_with(arg, source_dep_opt)) {
+  if (arg.starts_with(source_dep_opt)) {
     // The generated file embeds absolute include paths resolved relative to the
     // actual working directory even when -I uses relative paths. To avoid false
     // positive cache hits across different working directories, bind the result
@@ -1198,7 +1193,7 @@ process_option_arg(const Context& ctx,
     return Statistic::none;
   }
 
-  if (util::starts_with(arg, "-fbuild-session-file")
+  if (arg.starts_with("-fbuild-session-file")
       && !(config.sloppiness().contains(core::Sloppy::time_macros))) {
     args_info.build_session_file = arg.substr(arg.find('=') + 1);
   }
@@ -1274,9 +1269,9 @@ process_option_arg(const Context& ctx,
   }
 
   // Detect PCH for options with concatenated path (relative or absolute).
-  if (util::starts_with(arg, "-include") || util::starts_with(arg, "-Fp")
-      || util::starts_with(arg, "-Yu") || util::starts_with(arg, "-Yc")) {
-    const size_t path_pos = util::starts_with(arg, "-include") ? 8 : 3;
+  if (arg.starts_with("-include") || arg.starts_with("-Fp")
+      || arg.starts_with("-Yu") || arg.starts_with("-Yc")) {
+    const size_t path_pos = arg.starts_with("-include") ? 8 : 3;
     if (!detect_pch(arg.substr(0, path_pos),
                     arg.substr(path_pos),
                     args_info,
@@ -1815,8 +1810,7 @@ option_should_be_ignored(const std::string& arg,
     patterns.cbegin(), patterns.cend(), [&arg](const auto& pattern) {
       const auto& prefix =
         std::string_view(pattern).substr(0, pattern.length() - 1);
-      return (
-        pattern == arg
-        || (util::ends_with(pattern, "*") && util::starts_with(arg, prefix)));
+      return (pattern == arg
+              || (pattern.ends_with("*") && arg.starts_with(prefix)));
     });
 }
index a33ad7fea626344d544ca752dd23b5f29a0c1c2a..1debc0ac9c0638ae629761539f1c2c62ef0d349f 100644 (file)
@@ -421,8 +421,7 @@ remember_include_file(Context& ctx,
   if (!ctx.ignore_header_paths.empty()) {
     // Canonicalize path for comparison; Clang uses ./header.h.
     const std::string& canonical_path_str =
-      util::starts_with(path_str.str(), "./") ? path_str.str().substr(2)
-                                              : path_str;
+      path_str.str().starts_with("./") ? path_str.str().substr(2) : path_str;
     for (const auto& ignore_header_path : ctx.ignore_header_paths) {
       if (file_path_matches_dir_prefix_or_file(ignore_header_path,
                                                canonical_path_str)) {
@@ -566,14 +565,14 @@ process_preprocessed_file(Context& ctx, Hash& hash, const fs::path& path)
         // GCC:
         && ((q[1] == ' ' && q[2] >= '0' && q[2] <= '9')
             // GCC precompiled header:
-            || util::starts_with(&q[1], pragma_gcc_pch_preprocess)
+            || std::string_view(&q[1]).starts_with(pragma_gcc_pch_preprocess)
             // HP/AIX:
             || (q[1] == 'l' && q[2] == 'i' && q[3] == 'n' && q[4] == 'e'
                 && q[5] == ' '))
         && (q == data.data() || q[-1] == '\n')) {
       // Workarounds for preprocessor linemarker bugs in GCC version 6.
       if (q[2] == '3') {
-        if (util::starts_with(q, hash_31_command_line_newline)) {
+        if (std::string_view(q).starts_with(hash_31_command_line_newline)) {
           // Bogus extra line with #31, after the regular #1: Ignore the whole
           // line, and continue parsing.
           hash.hash(p, q - p);
@@ -583,7 +582,8 @@ process_preprocessed_file(Context& ctx, Hash& hash, const fs::path& path)
           q++;
           p = q;
           continue;
-        } else if (util::starts_with(q, hash_32_command_line_2_newline)) {
+        } else if (std::string_view(q).starts_with(
+                     hash_32_command_line_2_newline)) {
           // Bogus wrong line with #32, instead of regular #1: Replace the line
           // number with the usual one.
           hash.hash(p, q - p);
@@ -1086,7 +1086,7 @@ rewrite_stdout_from_compiler(const Context& ctx, util::Bytes&& stdout_data)
                                      "\n",
                                      Mode::include_empty,
                                      IncludeDelimiter::yes)) {
-      if (util::starts_with(line, "__________")) {
+      if (line.starts_with("__________")) {
         // distcc-pump outputs lines like this:
         //
         //   __________Using # distcc servers in pump mode
@@ -1095,7 +1095,7 @@ rewrite_stdout_from_compiler(const Context& ctx, util::Bytes&& stdout_data)
         core::send_to_console(ctx, line, STDOUT_FILENO);
       } else if (ctx.config.compiler_type() == CompilerType::msvc
                  && !ctx.config.base_dirs().empty()
-                 && util::starts_with(line, ctx.config.msvc_dep_prefix())) {
+                 && line.starts_with(ctx.config.msvc_dep_prefix())) {
         // Ninja uses the lines with 'Note: including file: ' to determine the
         // used headers. Headers within basedir need to be changed into relative
         // paths because otherwise Ninja will use the abs path to original
@@ -1504,7 +1504,7 @@ hash_compiler(const Context& ctx,
     hash.hash_delimiter("cc_mtime");
     hash.hash(dir_entry.size());
     hash.hash(util::nsec_tot(dir_entry.mtime()));
-  } else if (util::starts_with(ctx.config.compiler_check(), "string:")) {
+  } else if (ctx.config.compiler_check().starts_with("string:")) {
     hash.hash_delimiter("cc_hash");
     hash.hash(&ctx.config.compiler_check()[7]);
   } else if (ctx.config.compiler_check() == "content" || !allow_command) {
@@ -1586,7 +1586,7 @@ apply_prefix_remapping(const std::vector<std::string>& maps, fs::path& path)
 
     const std::string old_prefix{map.substr(0, sep_pos)};
     const std::string new_prefix{map.substr(sep_pos + 1)};
-    if (!util::starts_with(util::pstr(path).str(), old_prefix)) {
+    if (!util::pstr(path).str().starts_with(old_prefix)) {
       continue;
     }
 
@@ -1954,7 +1954,7 @@ get_option_and_value(std::string_view option, const util::Args& args, size_t& i)
     } else {
       return {std::nullopt, std::nullopt};
     }
-  } else if (util::starts_with(args[i], option)) {
+  } else if (args[i].starts_with(option)) {
     return {option, std::string_view(args[i]).substr(option.length())};
   } else {
     return {std::nullopt, std::nullopt};
@@ -1985,16 +1985,16 @@ hash_argument(const Context& ctx,
     i++;
     return {};
   }
-  if (util::starts_with(args[i], "-L") && !is_clang) {
+  if (args[i].starts_with("-L") && !is_clang) {
     return {};
   }
 
   // -Wl,... doesn't affect compilation (except for clang).
-  if (util::starts_with(args[i], "-Wl,") && !is_clang) {
+  if (args[i].starts_with("-Wl,") && !is_clang) {
     return {};
   }
 
-  if (util::starts_with(args[i], "-Wa,")) {
+  if (args[i].starts_with("-Wa,")) {
     // We have to distinguish between three cases:
     //
     // Case 1: -Wa,-a      (write to stdout)
@@ -2013,7 +2013,7 @@ hash_argument(const Context& ctx,
       } else {
         hash.hash(",");
       }
-      if (util::starts_with(part, "-a")) {
+      if (part.starts_with("-a")) {
         const auto eq_pos = part.find('=');
         if (eq_pos < part.size() - 1) {
           // Case 3:
@@ -2032,35 +2032,35 @@ hash_argument(const Context& ctx,
   // CCACHE_BASEDIR to reuse results across different directories. Skip using
   // the value of the option from hashing but still hash the existence of the
   // option.
-  if (util::starts_with(args[i], "-fdebug-prefix-map=")) {
+  if (args[i].starts_with("-fdebug-prefix-map=")) {
     hash.hash_delimiter("arg");
     hash.hash("-fdebug-prefix-map=");
     return {};
   }
-  if (util::starts_with(args[i], "-ffile-prefix-map=")) {
+  if (args[i].starts_with("-ffile-prefix-map=")) {
     hash.hash_delimiter("arg");
     hash.hash("-ffile-prefix-map=");
     return {};
   }
-  if (util::starts_with(args[i], "-fmacro-prefix-map=")) {
+  if (args[i].starts_with("-fmacro-prefix-map=")) {
     hash.hash_delimiter("arg");
     hash.hash("-fmacro-prefix-map=");
     return {};
   }
   // -fprofile-prefix-path can also be used to reuse ccache results
   // across different directories
-  if (util::starts_with(args[i], "-fprofile-prefix-path=")) {
+  if (args[i].starts_with("-fprofile-prefix-path=")) {
     hash.hash_delimiter("arg");
     hash.hash("-fprofile-prefix-path=");
     return {};
   }
-  if (util::starts_with(args[i], "-fcoverage-prefix-map=")) {
+  if (args[i].starts_with("-fcoverage-prefix-map=")) {
     hash.hash_delimiter("arg");
     hash.hash("-fcoverage-prefix-map=");
     return {};
   }
 
-  if (util::starts_with(args[i], "-frandom-seed=")
+  if (args[i].starts_with("-frandom-seed=")
       && ctx.config.sloppiness().contains(core::Sloppy::random_seed)) {
     LOG("Ignoring {} since random_seed sloppiness is requested", args[i]);
     return {};
@@ -2068,7 +2068,7 @@ hash_argument(const Context& ctx,
 
   static const std::string_view frandomize_layout_seed_file =
     "-frandomize-layout-seed-file=";
-  if (util::starts_with(args[i], frandomize_layout_seed_file)) {
+  if (args[i].starts_with(frandomize_layout_seed_file)) {
     hash.hash_delimiter(frandomize_layout_seed_file);
     auto file = args[i].substr(frandomize_layout_seed_file.length());
     if (!hash_binary_file(ctx, hash, file)) {
@@ -2120,13 +2120,13 @@ hash_argument(const Context& ctx,
   }
 
   if (ctx.args_info.generating_dependencies) {
-    if (util::starts_with(args[i], "-Wp,")) {
+    if (args[i].starts_with("-Wp,")) {
       // Skip the dependency filename since it doesn't impact the output.
-      if (util::starts_with(args[i], "-Wp,-MD,")
+      if (args[i].starts_with("-Wp,-MD,")
           && args[i].find(',', 8) == std::string::npos) {
         hash.hash(args[i].data(), 8);
         return {};
-      } else if (util::starts_with(args[i], "-Wp,-MMD,")
+      } else if (args[i].starts_with("-Wp,-MMD,")
                  && args[i].find(',', 9) == std::string::npos) {
         hash.hash(args[i].data(), 9);
         return {};
@@ -2149,8 +2149,8 @@ hash_argument(const Context& ctx,
     }
   }
 
-  if (util::starts_with(args[i], "-specs=") || args[i] == "-specs"
-      || util::starts_with(args[i], "--specs=") || args[i] == "--specs") {
+  if (args[i].starts_with("-specs=") || args[i] == "-specs"
+      || args[i].starts_with("--specs=") || args[i] == "--specs") {
     auto [_option, specs] = util::split_once_into_views(args[i], '=');
     if (!specs) {
       if (i + 1 >= args.size()) {
@@ -2163,7 +2163,7 @@ hash_argument(const Context& ctx,
 
     if (ctx.config.is_compiler_group_clang()) {
       // Clang accepts -specs but ignores it.
-      if (!util::ends_with(args[i], "=")) {
+      if (!args[i].ends_with("=")) {
         hash.hash_delimiter("arg");
         hash.hash(args[i - 1]);
       }
@@ -2188,7 +2188,7 @@ hash_argument(const Context& ctx,
     return {};
   }
 
-  if (args[i] == "--config" || util::starts_with(args[i], "--config=")) {
+  if (args[i] == "--config" || args[i].starts_with("--config=")) {
     // Clang's --config(=)name option behaves like this:
     //
     // --config foo     -> read /usr/lib/llvm-$ver/bin/foo.cfg (ver < 16)
@@ -2228,7 +2228,7 @@ hash_argument(const Context& ctx,
     return {};
   }
 
-  if (util::starts_with(args[i], "-fplugin=")) {
+  if (args[i].starts_with("-fplugin=")) {
     DirEntry dir_entry(&args[i][9], DirEntry::LogOnError::yes);
     if (dir_entry.is_regular_file()) {
       hash.hash_delimiter("plugin");
@@ -3112,7 +3112,7 @@ is_ccache_executable(const fs::path& path)
 #ifdef _WIN32
   name = util::to_lowercase(name);
 #endif
-  return util::starts_with(name, "ccache");
+  return name.starts_with("ccache");
 }
 
 bool
index 05eec4c29b456a6b883c9cb480e92017f0e33522..24cb3581b974c6ff0e05875bc23805bb60d91daa 100644 (file)
@@ -35,7 +35,7 @@ get_includes_from_msvc_show_includes(std::string_view file_content,
   // This will split at each \r or \n, but that simply means there will be empty
   // "lines".
   for (std::string_view line : util::split_into_views(file_content, "\r\n")) {
-    if (util::starts_with(line, prefix)) {
+    if (line.starts_with(prefix)) {
       size_t pos = prefix.size();
       while (pos < line.size() && util::is_space(line[pos])) {
         ++pos;
@@ -67,7 +67,7 @@ strip_includes_from_msvc_show_includes(const Context& ctx,
                                    "\n",
                                    Mode::include_empty,
                                    IncludeDelimiter::yes)) {
-    if (!util::starts_with(line, ctx.config.msvc_dep_prefix())) {
+    if (!line.starts_with(ctx.config.msvc_dep_prefix())) {
       new_stdout_data.insert(new_stdout_data.end(), line.data(), line.size());
     }
   }
index 7ccdf9f3d5ef4a0a1e66528a4a41d87c89a2f645..79c1522b532e8c5acb30e3ea6014210a3b94d625 100644 (file)
@@ -763,7 +763,7 @@ Config::update_from_environment()
   for (char** env = environ; *env; ++env) {
     std::string setting = *env;
     const std::string prefix = "CCACHE_";
-    if (!util::starts_with(setting, prefix)) {
+    if (!setting.starts_with(prefix)) {
       continue;
     }
     size_t equal_pos = setting.find('=');
@@ -773,7 +773,7 @@ Config::update_from_environment()
 
     std::string key = setting.substr(prefix.size(), equal_pos - prefix.size());
     std::string value = setting.substr(equal_pos + 1);
-    bool negate = util::starts_with(key, "NO");
+    bool negate = key.starts_with("NO");
     if (negate) {
       key = key.substr(2);
     }
@@ -884,7 +884,7 @@ Config::get_string_value(const std::string& key) const
   case ConfigItem::max_size: {
     auto result =
       util::format_human_readable_size(m_max_size, m_size_prefix_type);
-    if (util::ends_with(result, " bytes")) {
+    if (result.ends_with(" bytes")) {
       // Special case to make the output parsable by util::parse_size.
       result.resize(result.size() - 6);
     }
index 9106b27f7fa481b9ba183532421260b44562cd13..92ee861622d5e7e733eaba2d1bcc22b91b96ee01 100644 (file)
@@ -98,7 +98,7 @@ parse_inlined_from_msg(std::string_view& line, std::string& result)
   static const std::string_view inlined_from_msg = "    inlined from ";
   static const std::string_view inlined_from_msg_separator = " at ";
 
-  if (!util::starts_with(line, inlined_from_msg)) {
+  if (!line.starts_with(inlined_from_msg)) {
     return false;
   }
 
@@ -131,7 +131,7 @@ parse_in_file_included_from_msg(std::string_view& line, std::string& result)
   };
 
   for (const auto& in_file_included_from : in_file_included_from_msgs) {
-    if (util::starts_with(line, in_file_included_from)) {
+    if (line.starts_with(in_file_included_from)) {
       result += in_file_included_from;
       line = line.substr(in_file_included_from.length());
       return true;
index 984bcea56deb7f62d47dcb48ea836e0be07fd660..495a844abbfbaa9c0209d9db3aefb0ee246dd336 100644 (file)
@@ -79,7 +79,7 @@ get_cache_dir_files(const fs::path& dir)
     util::traverse_directory(dir, [&](const auto& de) {
       std::string name = util::pstr(de.path().filename());
       if (name == "CACHEDIR.TAG" || name == "stats"
-          || util::starts_with(name, ".nfs")) {
+          || name.starts_with(".nfs")) {
         return;
       }
 
index e5e9a2d2edc12b51f29ec82edac4ffafe69e7080..707c4e9a515a34bd8520df11bc8972852fd4f80f 100644 (file)
@@ -184,8 +184,8 @@ is_ccache_crsh_var(std::string_view entry)
 
   return name == "CRSH_IPC_ENDPOINT" || name == "CRSH_URL"
          || name == "CRSH_IDLE_TIMEOUT" || name == "CRSH_NUM_ATTR"
-         || util::starts_with(name, "CRSH_ATTR_KEY_")
-         || util::starts_with(name, "CRSH_ATTR_VALUE_");
+         || name.starts_with("CRSH_ATTR_KEY_")
+         || name.starts_with("CRSH_ATTR_VALUE_");
 }
 
 #ifndef _WIN32
@@ -248,7 +248,7 @@ spawn_helper(const fs::path& helper_path,
 
 #ifdef _WIN32
   // Don't pass \\.\pipe\ prefix on Windows.
-  DEBUG_ASSERT(util::starts_with(endpoint, k_named_pipe_prefix));
+  DEBUG_ASSERT(endpoint.starts_with(k_named_pipe_prefix));
   auto ipc_endpoint = endpoint.substr(k_named_pipe_prefix.length());
 #else
   const auto& ipc_endpoint = endpoint;
index a77ed6112d83b9e3bef70aa71632a7392ebd83da..a3d081e153ea35a552ca8758ce354fb719dbb530 100644 (file)
@@ -224,8 +224,8 @@ Args::erase_last(std::string_view arg)
 void
 Args::erase_with_prefix(std::string_view prefix)
 {
-  std::erase_if(
-    m_args, [&prefix](const auto& s) { return util::starts_with(s, prefix); });
+  std::erase_if(m_args,
+                [&prefix](const auto& s) { return s.starts_with(prefix); });
 }
 
 void
index 423c0f4bf7465454904d16c5eca210d7c6f3a30c..9eca073d9cff88781291ee90163d78d19f6d98cf 100644 (file)
@@ -67,7 +67,8 @@ format_argv_as_win32_command_string(const char* const* argv,
   }
 
   std::string result;
-  if (getenv("_CCACHE_TEST") && argv[0] && util::ends_with(argv[0], ".sh")) {
+  if (getenv("_CCACHE_TEST") && argv[0]
+      && std::string_view(argv[0]).ends_with(".sh")) {
     result += "sh.exe ";
   }
 
@@ -453,7 +454,7 @@ parse_unsigned(std::string_view value,
   size_t end = 0;
   unsigned long long result = 0;
   bool failed = false;
-  if (starts_with(stripped_value, "-")) {
+  if (stripped_value.starts_with("-")) {
     failed = true;
   } else {
     try {
index bc27ded13d5c772542049200cf5c7b2a381c204e..b9bc31bfd38b3d47cc089235ee1ab8b07f38b2c8 100644 (file)
@@ -46,9 +46,6 @@ class Bytes;
 enum class SizeUnitPrefixType { binary, decimal };
 enum class TimeZone { local, utc };
 
-// 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
@@ -226,12 +223,6 @@ split_option_with_concat_path(std::string_view string);
 // %PATH% on Windows platforms) into paths.
 std::vector<std::filesystem::path> split_path_list(std::string_view path_list);
 
-// Return true if `prefix` is a prefix of `string`.
-bool starts_with(const char* string, std::string_view prefix);
-
-// Return true if `prefix` is a prefix of `string`.
-bool starts_with(std::string_view string, std::string_view prefix);
-
 // Strip whitespace from left and right side of a string.
 [[nodiscard]] std::string strip_whitespace(std::string_view string);
 
@@ -243,13 +234,6 @@ char to_lower(char ch);
 
 // --- Inline implementations ---
 
-inline bool
-ends_with(const std::string_view string, const std::string_view suffix)
-{
-  return string.length() >= suffix.length()
-         && string.substr(string.length() - suffix.length()) == suffix;
-}
-
 inline bool
 is_alnum(char ch)
 {
@@ -301,20 +285,6 @@ join(const T& begin, const T& end, const std::string_view delimiter)
   return result;
 }
 
-inline bool
-starts_with(const char* const string, const std::string_view prefix)
-{
-  // Optimized version of starts_with(string_view, string_view): avoid computing
-  // the length of the string argument.
-  return std::strncmp(string, prefix.data(), prefix.length()) == 0;
-}
-
-inline bool
-starts_with(const std::string_view string, const std::string_view prefix)
-{
-  return string.substr(0, prefix.size()) == prefix;
-}
-
 inline char
 to_lower(char ch)
 {
index b2db1eceded0bc0f04f9a3068c0cfe8000790cba..763035f5e4ce437ff880b0352da9af92cbd76952 100644 (file)
@@ -690,8 +690,7 @@ TEST_CASE("-x")
 // MSVC's /U option, so disable the test case there. This will be possible to
 // improve when/if a compiler abstraction is introduced (issue #956).
 TEST_CASE("MSVC options"
-          * doctest::skip(util::starts_with(fs::current_path()->string(),
-                                            "/U")))
+          * doctest::skip(fs::current_path()->string().starts_with("/U")))
 {
   TestContext test_context;
   Context ctx;
index 7c56732c0e8d5abdb034e48d88bbb507e84008a3..42b3da95b585ef090d9ad0f19bde8d35b58cd9dd 100644 (file)
@@ -55,7 +55,7 @@ TEST_CASE("util::exec_to_string")
     auto result = exec_to_string({"doesnotexist"});
     REQUIRE(!result);
 #ifdef _WIN32
-    CHECK(util::starts_with(result.error(), "CreateProcess failure: "));
+    CHECK(result.error().starts_with("CreateProcess failure: "));
 #else
     CHECK(result.error() == "posix_spawnp failed: No such file or directory");
 #endif
index 16ffd7052f1babfc4e3f6669e1d20787928953ac..ec5a24b152e6a57be6e467da4209a4855ebff278 100644 (file)
@@ -181,8 +181,8 @@ TEST_CASE("util::read_file<std::string> with UTF-16 little endian encoding")
   CHECK(util::write_file("test", data));
   read_data = util::read_file<std::string>("test");
   REQUIRE(!read_data);
-  REQUIRE(util::starts_with(read_data.error(),
-                            "Failed to convert test from UTF-16LE to UTF-8:"));
+  REQUIRE(read_data.error().starts_with(
+    "Failed to convert test from UTF-16LE to UTF-8:"));
 }
 #endif
 
index 4b90db0d6b06b209ce5b7045f3c30d3b4a9a98ff..9421dd5b3bd9606a29f60c824f10180387e928e4 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2025 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2026 Joel Rosdahl and other contributors
 //
 // See doc/authors.adoc for a complete list of contributors.
 //
@@ -255,24 +255,6 @@ TEST_CASE("util::format_base32hex")
   CHECK(util::format_base32hex({input, 6}) == "cpnmuoj1e8");
 }
 
-TEST_CASE("util::ends_with")
-{
-  CHECK(util::ends_with("", ""));
-  CHECK(util::ends_with("x", ""));
-  CHECK(util::ends_with("x", "x"));
-  CHECK(util::ends_with("xy", ""));
-  CHECK(util::ends_with("xy", "y"));
-  CHECK(util::ends_with("xy", "xy"));
-  CHECK(util::ends_with("xyz", ""));
-  CHECK(util::ends_with("xyz", "z"));
-  CHECK(util::ends_with("xyz", "yz"));
-  CHECK(util::ends_with("xyz", "xyz"));
-
-  CHECK_FALSE(util::ends_with("", "x"));
-  CHECK_FALSE(util::ends_with("x", "y"));
-  CHECK_FALSE(util::ends_with("x", "xy"));
-}
-
 TEST_CASE("util::format_human_readable_diff")
 {
   using SUPT = util::SizeUnitPrefixType;
@@ -772,41 +754,6 @@ TEST_CASE("util::split_path_list")
   }
 }
 
-TEST_CASE("util::starts_with")
-{
-  // starts_with(const char*, string_view)
-  CHECK(util::starts_with("", ""));
-  CHECK(util::starts_with("x", ""));
-  CHECK(util::starts_with("x", "x"));
-  CHECK(util::starts_with("xy", ""));
-  CHECK(util::starts_with("xy", "x"));
-  CHECK(util::starts_with("xy", "xy"));
-  CHECK(util::starts_with("xyz", ""));
-  CHECK(util::starts_with("xyz", "x"));
-  CHECK(util::starts_with("xyz", "xy"));
-  CHECK(util::starts_with("xyz", "xyz"));
-
-  CHECK_FALSE(util::starts_with("", "x"));
-  CHECK_FALSE(util::starts_with("x", "y"));
-  CHECK_FALSE(util::starts_with("x", "xy"));
-
-  // starts_with(string_view, string_view)
-  CHECK(util::starts_with(std::string(""), ""));
-  CHECK(util::starts_with(std::string("x"), ""));
-  CHECK(util::starts_with(std::string("x"), "x"));
-  CHECK(util::starts_with(std::string("xy"), ""));
-  CHECK(util::starts_with(std::string("xy"), "x"));
-  CHECK(util::starts_with(std::string("xy"), "xy"));
-  CHECK(util::starts_with(std::string("xyz"), ""));
-  CHECK(util::starts_with(std::string("xyz"), "x"));
-  CHECK(util::starts_with(std::string("xyz"), "xy"));
-  CHECK(util::starts_with(std::string("xyz"), "xyz"));
-
-  CHECK_FALSE(util::starts_with(std::string(""), "x"));
-  CHECK_FALSE(util::starts_with(std::string("x"), "y"));
-  CHECK_FALSE(util::starts_with(std::string("x"), "xy"));
-}
-
 TEST_CASE("util::strip_whitespace")
 {
   CHECK(util::strip_whitespace("") == "");