diff --git a/.clang-tidy b/.clang-tidy index 9bc2fc61ac..c466a45ca3 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -62,7 +62,6 @@ Checks: [-*, # These are features in newer version of C++ that we don't have # access to yet. - -modernize-use-starts-ends-with, -modernize-use-std-format, -modernize-use-std-numbers, -modernize-use-std-print, diff --git a/CHANGES b/CHANGES index 00015a9145..f76e9a3a51 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,12 @@ +8.0.0-dev.682 | 2025-07-17 09:09:28 -0700 + + * Use std::string/string_view versions of starts_with/ends_with where appropriate (Tim Wojtulewicz, Corelight) + + The util:: versions of these methods remain as a thin wrapper around them so + they can be used with const char* arguments. Otherwise callers have to manually + make string_view objects from the input. + s Please enter the commit message for your changes. Lines starting + 8.0.0-dev.680 | 2025-07-17 08:40:49 -0700 * Add nolint for enum size for HILTI_RT_ENUM use (Tim Wojtulewicz, Corelight) diff --git a/NEWS b/NEWS index 1905b117f6..8114393870 100644 --- a/NEWS +++ b/NEWS @@ -348,12 +348,17 @@ Deprecated Functionality tuples. The ConnTuple struct, used by this deprecated Connection constructor, is now deprecated as well. + - The ``zeek::filesystem`` namespace alias is deprecated in favor of using ``std::filesystem`` directly. Similarly, the ``ghc::filesystem`` submodule stored in ``auxil/filessytem`` has been removed and the files included from it in the Zeek installation will no longer be installed. Builds won't warn about the deprecation of ``zeek::filesystem`` due to limitations of how we can mark deprecations in C++. +- The ``zeek::util::starts_with`` and ``zeek::util::ends_with`` functions are deprecated. + ``std::string`` and ``std::string_view`` added ``begins_with`` and ``ends_with`` methods + in C++ 20, and those should be used instead. + Zeek 7.2.0 ========== diff --git a/VERSION b/VERSION index a379598ad0..08dd6bee6b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.0.0-dev.680 +8.0.0-dev.682 diff --git a/src/DebugLogger.cc b/src/DebugLogger.cc index a21392f769..28602e6d5b 100644 --- a/src/DebugLogger.cc +++ b/src/DebugLogger.cc @@ -111,7 +111,7 @@ void DebugLogger::EnableStreams(const char* s) { exit(0); } - if ( util::starts_with(ltok, "plugin-") ) { + if ( std::string_view{ltok}.starts_with("plugin-") ) { // Cannot verify this at this time, plugins may not // have been loaded. enabled_streams.insert(std::move(ltok)); @@ -145,7 +145,7 @@ bool DebugLogger::CheckStreams(const std::set& plugin_names) { available_plugin_streams.insert(PluginStreamName(p)); for ( const auto& stream : enabled_streams ) { - if ( ! util::starts_with(stream, "plugin-") ) + if ( ! stream.starts_with("plugin-") ) continue; if ( available_plugin_streams.count(stream) == 0 ) { diff --git a/src/Options.cc b/src/Options.cc index b01e859087..59322131f7 100644 --- a/src/Options.cc +++ b/src/Options.cc @@ -319,13 +319,8 @@ Options parse_cmdline(int argc, char** argv) { } else { if ( argc > 1 ) { - auto endsWith = [](const std::string& str, const std::string& suffix) { - return str.size() >= suffix.size() && - 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix); - }; - auto i = 0; - for ( ; i < argc && ! endsWith(argv[i], "--"); ++i ) { + for ( ; i < argc && ! util::ends_with(argv[i], "--"); ++i ) { zeek_args.emplace_back(argv[i]); } @@ -333,17 +328,17 @@ Options parse_cmdline(int argc, char** argv) { // If a script is invoked with Zeek as the interpreter, the arguments provided // directly in the interpreter line of the script won't be broken apart in the // argv on Linux so we split it up here. - if ( endsWith(argv[i], "--") && zeek_args.size() == 1 ) { + if ( util::ends_with(argv[i], "--") && zeek_args.size() == 1 ) { std::istringstream iss(argv[i]); for ( std::string s; iss >> s; ) { - if ( ! endsWith(s, "--") ) { + if ( ! s.ends_with("--") ) { zeek_args.emplace_back(s); } } } // There is an additional increment here to skip over the "--" if it was found. - if ( endsWith(argv[i], "--") ) + if ( util::ends_with(argv[i], "--") ) ++i; // The first argument after the double hyphens in implicitly a script name. diff --git a/src/Scope.cc b/src/Scope.cc index b97dbe77d2..c6fb7d118e 100644 --- a/src/Scope.cc +++ b/src/Scope.cc @@ -91,10 +91,10 @@ TraversalCode Scope::Traverse(TraversalCallback* cb) const { const IDPtr& lookup_ID(const char* name, const char* curr_module, bool no_global, bool same_module_only, bool check_export) { - bool explicit_global = zeek::util::starts_with(name, "::"); + bool explicit_global = std::string_view{name}.starts_with("::"); static std::string global_prefix = util::fmt("%s::", GLOBAL_MODULE_NAME); - if ( zeek::util::starts_with(name, global_prefix) ) + if ( std::string_view{name}.starts_with(global_prefix) ) reporter->Error("Using GLOBAL:: as a prefix is invalid. Use :: instead (%s)", name); std::string fullname = make_full_var_name(curr_module, name); diff --git a/src/Val.cc b/src/Val.cc index dfb36dcae3..35b088870c 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -1053,8 +1053,7 @@ static zeek::expected BuildVal(const rapidjson::Value& j, c candidate.erase(candidate.size() - 1); } // Remove any surrounding "^?(" and ")$?", automatically added below. - if ( candidate.size() > 6 && candidate.substr(0, 3) == "^?(" && - candidate.substr(candidate.size() - 3, 3) == ")$?" ) { + if ( candidate.size() > 6 && candidate.starts_with("^?(") && candidate.ends_with(")$?") ) { candidate.erase(0, 3); candidate.erase(candidate.size() - 3); } diff --git a/src/analyzer/protocol/irc/IRC.cc b/src/analyzer/protocol/irc/IRC.cc index e5aaca7ac5..d636319a09 100644 --- a/src/analyzer/protocol/irc/IRC.cc +++ b/src/analyzer/protocol/irc/IRC.cc @@ -533,7 +533,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { message = message.substr(1); // DCC // Check for DCC messages. - if ( message.size() > 3 && message.substr(0, 3) == "DCC" ) { + if ( message.size() > 3 && message.starts_with("DCC") ) { if ( message[message.size() - 1] == 1 ) message = message.substr(0, message.size() - 1); diff --git a/src/broker/Data.cc b/src/broker/Data.cc index e888c14034..bc3db0007e 100644 --- a/src/broker/Data.cc +++ b/src/broker/Data.cc @@ -767,7 +767,7 @@ std::optional val_to_data(const Val* v) { broker::vector rval; rval.emplace_back(f->GetName()); - if ( f->GetName().find("lambda_<") == 0 ) { + if ( f->GetName().starts_with("lambda_<") ) { // Only ScriptFuncs have closures. if ( auto b = dynamic_cast(f) ) { auto bc = b->SerializeCaptures(); diff --git a/src/input/readers/ascii/Ascii.cc b/src/input/readers/ascii/Ascii.cc index b4ec9f8ca9..81fca8ef63 100644 --- a/src/input/readers/ascii/Ascii.cc +++ b/src/input/readers/ascii/Ascii.cc @@ -241,7 +241,7 @@ bool Ascii::GetLine(string& str) { if ( str[0] != '#' ) return true; - if ( (str.length() > 8) && (str.compare(0, 7, "#fields") == 0) && (str[7] == separator[0]) ) { + if ( (str.length() > 8) && str.starts_with("#fields") && (str[7] == separator[0]) ) { str = str.substr(8); return true; } diff --git a/src/logging/writers/ascii/Ascii.h b/src/logging/writers/ascii/Ascii.h index 6ae5ba0cb9..0bbf185082 100644 --- a/src/logging/writers/ascii/Ascii.h +++ b/src/logging/writers/ascii/Ascii.h @@ -40,7 +40,7 @@ private: static void RotateLeftoverLogs(); - bool IsSpecial(const std::string& path) { return path.find("/dev/") == 0; } + bool IsSpecial(const std::string& path) { return path.starts_with("/dev/"); } bool WriteHeader(const std::string& path); bool WriteHeaderField(const std::string& key, const std::string& value); void CloseFile(double t); diff --git a/src/script_opt/ProfileFunc.cc b/src/script_opt/ProfileFunc.cc index c3636819f8..e7e432d66f 100644 --- a/src/script_opt/ProfileFunc.cc +++ b/src/script_opt/ProfileFunc.cc @@ -1467,7 +1467,7 @@ std::string func_name_at_loc(std::string fname, const Location* loc) { auto mod_prefix = module + "::"; - if ( fname.find(mod_prefix) == 0 ) + if ( fname.starts_with(mod_prefix) ) return fname; // it already has the module name return mod_prefix + fname; diff --git a/src/storage/backend/redis/Redis.cc b/src/storage/backend/redis/Redis.cc index 97fd4f3c3e..a57090e1ec 100644 --- a/src/storage/backend/redis/Redis.cc +++ b/src/storage/backend/redis/Redis.cc @@ -635,7 +635,7 @@ void Redis::HandleInfoResult(redisReply* reply) { continue; // We only care about the redis_version entry. Skip anything else. - if ( ! util::starts_with(e, "redis_version:") ) + if ( ! e.starts_with("redis_version:") ) continue; auto splits = util::split(e, ':'); diff --git a/src/telemetry/Manager.cc b/src/telemetry/Manager.cc index 51424fe7a3..7159361cfb 100644 --- a/src/telemetry/Manager.cc +++ b/src/telemetry/Manager.cc @@ -189,7 +189,7 @@ RecordValPtr Manager::GetMetricOptsRecord(const prometheus::MetricFamily& metric record_val->Assign(prefix_idx, make_intrusive(prefix)); // Assume that a metric ending with _total is always a summed metric so we can set that. - record_val->Assign(is_total_idx, val_mgr->Bool(util::ends_with(metric_family.name, "_total"))); + record_val->Assign(is_total_idx, val_mgr->Bool(metric_family.name.ends_with("_total"))); if ( metric_family.type == prometheus::MetricType::Counter ) record_val->Assign(metric_type_idx, zeek::BifType::Enum::Telemetry::MetricType->GetEnumVal( diff --git a/src/telemetry/Utils.cc b/src/telemetry/Utils.cc index 25e195b812..b5505e2f66 100644 --- a/src/telemetry/Utils.cc +++ b/src/telemetry/Utils.cc @@ -26,9 +26,9 @@ std::string BuildFullPrometheusName(std::string_view prefix, std::string_view na }); // Suffixes of full metric names of _total are reserved by Prometheus. Disallow their use here. - if ( util::ends_with(fn, "_total") ) + if ( fn.ends_with("_total") ) reporter->FatalError("Metric names cannot end with '_total'"); - else if ( unit == "total" || util::ends_with(unit, "_total") ) + else if ( unit == "total" || unit.ends_with("_total") ) reporter->FatalError("Metric units cannot end with '_total'"); // We were previously using "1" to mean "no unit value" for whatever reason, so we have to handle that now diff --git a/src/util.cc b/src/util.cc index 9e0083ee5a..4c0f46c2ea 100644 --- a/src/util.cc +++ b/src/util.cc @@ -91,7 +91,7 @@ std::string extract_ip(const std::string& i) { if ( s.size() > 0 && s[0] == '[' ) s.erase(0, 1); - if ( s.size() > 1 && s.substr(0, 2) == "0x" ) + if ( s.starts_with("0x") ) s.erase(0, 2); if ( size_t pos = s.find(']'); pos != std::string::npos ) @@ -599,7 +599,7 @@ string normalize_path(std::string_view path) { } // "//" interferes with std::weakly_canonical string stringPath = string(path); - if ( stringPath._Starts_with("//") ) { + if ( stringPath.starts_with("//") ) { stringPath.erase(0, 2); } return std::filesystem::path(stringPath).lexically_normal().string(); @@ -672,7 +672,7 @@ string without_zeekpath_component(std::string_view path) { for ( const auto& p : paths ) { string common = normalize_path(p); - if ( rval.find(common) != 0 ) + if ( ! rval.starts_with(common) ) continue; // Found the containing directory. @@ -1034,31 +1034,8 @@ TEST_CASE("util streq") { bool streq(const char* s1, const char* s2) { return strcmp(s1, s2) == 0; } -bool starts_with(std::string_view s, std::string_view beginning) { - if ( beginning.size() > s.size() ) - return false; - - return std::equal(beginning.begin(), beginning.end(), s.begin()); -} - -TEST_CASE("util starts_with") { - CHECK(starts_with("abcde", "ab") == true); - CHECK(starts_with("abcde", "de") == false); - CHECK(starts_with("abcde", "abcedf") == false); -} - -bool ends_with(std::string_view s, std::string_view ending) { - if ( ending.size() > s.size() ) - return false; - - return std::equal(ending.rbegin(), ending.rend(), s.rbegin()); -} - -TEST_CASE("util ends_with") { - CHECK(ends_with("abcde", "de") == true); - CHECK(ends_with("abcde", "fg") == false); - CHECK(ends_with("abcde", "abcedf") == false); -} +bool starts_with(std::string_view s, std::string_view beginning) { return s.starts_with(beginning); } +bool ends_with(std::string_view s, std::string_view ending) { return s.ends_with(ending); } char* skip_whitespace(char* s) { while ( *s == ' ' || *s == '\t' ) diff --git a/src/zeekygen/IdentifierInfo.cc b/src/zeekygen/IdentifierInfo.cc index 40ad06bbbe..582ab262ff 100644 --- a/src/zeekygen/IdentifierInfo.cc +++ b/src/zeekygen/IdentifierInfo.cc @@ -37,7 +37,7 @@ void IdentifierInfo::AddRedef(const string& script, zeek::detail::InitClass ic, vector comments) { bool omit_value = false; for ( auto it = comments.begin(); it != comments.end(); ++it ) { - if ( it->find("@docs-omit-value") == 0 ) { + if ( it->starts_with("@docs-omit-value") ) { comments.erase(it); omit_value = true; break; diff --git a/src/zeekygen/utils.cc b/src/zeekygen/utils.cc index 26c63819e8..60ab773528 100644 --- a/src/zeekygen/utils.cc +++ b/src/zeekygen/utils.cc @@ -173,7 +173,7 @@ std::optional source_code_range(const zeek::detail::ID* id) { if ( id->IsType() ) { loc = type->GetLocationInfo(); - if ( zeek::util::ends_with(loc->FileName(), ".bif.zeek") ) + if ( std::string_view{loc->FileName()}.ends_with(".bif.zeek") ) // Source code won't be available to reference, so fall back // to identifier location which may actually be in a regular // .zeek script.