Merge remote-tracking branch 'origin/topic/timw/cpp20-starts-and-ends-with'

* origin/topic/timw/cpp20-starts-and-ends-with:
  Use std::string/string_view versions of starts_with/ends_with where appropriate
This commit is contained in:
Tim Wojtulewicz 2025-07-17 09:09:28 -07:00
commit beb70e27b5
19 changed files with 40 additions and 56 deletions

View file

@ -62,7 +62,6 @@ Checks: [-*,
# These are features in newer version of C++ that we don't have # These are features in newer version of C++ that we don't have
# access to yet. # access to yet.
-modernize-use-starts-ends-with,
-modernize-use-std-format, -modernize-use-std-format,
-modernize-use-std-numbers, -modernize-use-std-numbers,
-modernize-use-std-print, -modernize-use-std-print,

View file

@ -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 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) * Add nolint for enum size for HILTI_RT_ENUM use (Tim Wojtulewicz, Corelight)

5
NEWS
View file

@ -348,12 +348,17 @@ Deprecated Functionality
tuples. The ConnTuple struct, used by this deprecated Connection constructor, tuples. The ConnTuple struct, used by this deprecated Connection constructor,
is now deprecated as well. is now deprecated as well.
- The ``zeek::filesystem`` namespace alias is deprecated in favor of using - The ``zeek::filesystem`` namespace alias is deprecated in favor of using
``std::filesystem`` directly. Similarly, the ``ghc::filesystem`` submodule stored in ``std::filesystem`` directly. Similarly, the ``ghc::filesystem`` submodule stored in
``auxil/filessytem`` has been removed and the files included from it in the Zeek ``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 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++. ``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 Zeek 7.2.0
========== ==========

View file

@ -1 +1 @@
8.0.0-dev.680 8.0.0-dev.682

View file

@ -111,7 +111,7 @@ void DebugLogger::EnableStreams(const char* s) {
exit(0); 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 // Cannot verify this at this time, plugins may not
// have been loaded. // have been loaded.
enabled_streams.insert(std::move(ltok)); enabled_streams.insert(std::move(ltok));
@ -145,7 +145,7 @@ bool DebugLogger::CheckStreams(const std::set<std::string>& plugin_names) {
available_plugin_streams.insert(PluginStreamName(p)); available_plugin_streams.insert(PluginStreamName(p));
for ( const auto& stream : enabled_streams ) { for ( const auto& stream : enabled_streams ) {
if ( ! util::starts_with(stream, "plugin-") ) if ( ! stream.starts_with("plugin-") )
continue; continue;
if ( available_plugin_streams.count(stream) == 0 ) { if ( available_plugin_streams.count(stream) == 0 ) {

View file

@ -319,13 +319,8 @@ Options parse_cmdline(int argc, char** argv) {
} }
else { else {
if ( argc > 1 ) { 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; 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]); 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 // 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 // directly in the interpreter line of the script won't be broken apart in the
// argv on Linux so we split it up here. // 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]); std::istringstream iss(argv[i]);
for ( std::string s; iss >> s; ) { for ( std::string s; iss >> s; ) {
if ( ! endsWith(s, "--") ) { if ( ! s.ends_with("--") ) {
zeek_args.emplace_back(s); zeek_args.emplace_back(s);
} }
} }
} }
// There is an additional increment here to skip over the "--" if it was found. // 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; ++i;
// The first argument after the double hyphens in implicitly a script name. // The first argument after the double hyphens in implicitly a script name.

View file

@ -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, const IDPtr& lookup_ID(const char* name, const char* curr_module, bool no_global, bool same_module_only,
bool check_export) { 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); 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); reporter->Error("Using GLOBAL:: as a prefix is invalid. Use :: instead (%s)", name);
std::string fullname = make_full_var_name(curr_module, name); std::string fullname = make_full_var_name(curr_module, name);

View file

@ -1053,8 +1053,7 @@ static zeek::expected<ValPtr, std::string> BuildVal(const rapidjson::Value& j, c
candidate.erase(candidate.size() - 1); candidate.erase(candidate.size() - 1);
} }
// Remove any surrounding "^?(" and ")$?", automatically added below. // Remove any surrounding "^?(" and ")$?", automatically added below.
if ( candidate.size() > 6 && candidate.substr(0, 3) == "^?(" && if ( candidate.size() > 6 && candidate.starts_with("^?(") && candidate.ends_with(")$?") ) {
candidate.substr(candidate.size() - 3, 3) == ")$?" ) {
candidate.erase(0, 3); candidate.erase(0, 3);
candidate.erase(candidate.size() - 3); candidate.erase(candidate.size() - 3);
} }

View file

@ -533,7 +533,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) {
message = message.substr(1); // DCC message = message.substr(1); // DCC
// Check for DCC messages. // 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 ) if ( message[message.size() - 1] == 1 )
message = message.substr(0, message.size() - 1); message = message.substr(0, message.size() - 1);

View file

@ -767,7 +767,7 @@ std::optional<broker::data> val_to_data(const Val* v) {
broker::vector rval; broker::vector rval;
rval.emplace_back(f->GetName()); rval.emplace_back(f->GetName());
if ( f->GetName().find("lambda_<") == 0 ) { if ( f->GetName().starts_with("lambda_<") ) {
// Only ScriptFuncs have closures. // Only ScriptFuncs have closures.
if ( auto b = dynamic_cast<const zeek::detail::ScriptFunc*>(f) ) { if ( auto b = dynamic_cast<const zeek::detail::ScriptFunc*>(f) ) {
auto bc = b->SerializeCaptures(); auto bc = b->SerializeCaptures();

View file

@ -241,7 +241,7 @@ bool Ascii::GetLine(string& str) {
if ( str[0] != '#' ) if ( str[0] != '#' )
return true; 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); str = str.substr(8);
return true; return true;
} }

View file

@ -40,7 +40,7 @@ private:
static void RotateLeftoverLogs(); 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 WriteHeader(const std::string& path);
bool WriteHeaderField(const std::string& key, const std::string& value); bool WriteHeaderField(const std::string& key, const std::string& value);
void CloseFile(double t); void CloseFile(double t);

View file

@ -1467,7 +1467,7 @@ std::string func_name_at_loc(std::string fname, const Location* loc) {
auto mod_prefix = module + "::"; 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 fname; // it already has the module name
return mod_prefix + fname; return mod_prefix + fname;

View file

@ -635,7 +635,7 @@ void Redis::HandleInfoResult(redisReply* reply) {
continue; continue;
// We only care about the redis_version entry. Skip anything else. // 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; continue;
auto splits = util::split(e, ':'); auto splits = util::split(e, ':');

View file

@ -189,7 +189,7 @@ RecordValPtr Manager::GetMetricOptsRecord(const prometheus::MetricFamily& metric
record_val->Assign(prefix_idx, make_intrusive<zeek::StringVal>(prefix)); record_val->Assign(prefix_idx, make_intrusive<zeek::StringVal>(prefix));
// Assume that a metric ending with _total is always a summed metric so we can set that. // 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 ) if ( metric_family.type == prometheus::MetricType::Counter )
record_val->Assign(metric_type_idx, zeek::BifType::Enum::Telemetry::MetricType->GetEnumVal( record_val->Assign(metric_type_idx, zeek::BifType::Enum::Telemetry::MetricType->GetEnumVal(

View file

@ -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. // 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'"); 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'"); 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 // We were previously using "1" to mean "no unit value" for whatever reason, so we have to handle that now

View file

@ -91,7 +91,7 @@ std::string extract_ip(const std::string& i) {
if ( s.size() > 0 && s[0] == '[' ) if ( s.size() > 0 && s[0] == '[' )
s.erase(0, 1); s.erase(0, 1);
if ( s.size() > 1 && s.substr(0, 2) == "0x" ) if ( s.starts_with("0x") )
s.erase(0, 2); s.erase(0, 2);
if ( size_t pos = s.find(']'); pos != std::string::npos ) 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 // "//" interferes with std::weakly_canonical
string stringPath = string(path); string stringPath = string(path);
if ( stringPath._Starts_with("//") ) { if ( stringPath.starts_with("//") ) {
stringPath.erase(0, 2); stringPath.erase(0, 2);
} }
return std::filesystem::path(stringPath).lexically_normal().string(); 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 ) { for ( const auto& p : paths ) {
string common = normalize_path(p); string common = normalize_path(p);
if ( rval.find(common) != 0 ) if ( ! rval.starts_with(common) )
continue; continue;
// Found the containing directory. // 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 streq(const char* s1, const char* s2) { return strcmp(s1, s2) == 0; }
bool starts_with(std::string_view s, std::string_view beginning) { bool starts_with(std::string_view s, std::string_view beginning) { return s.starts_with(beginning); }
if ( beginning.size() > s.size() ) bool ends_with(std::string_view s, std::string_view ending) { return s.ends_with(ending); }
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);
}
char* skip_whitespace(char* s) { char* skip_whitespace(char* s) {
while ( *s == ' ' || *s == '\t' ) while ( *s == ' ' || *s == '\t' )

View file

@ -37,7 +37,7 @@ void IdentifierInfo::AddRedef(const string& script, zeek::detail::InitClass ic,
vector<string> comments) { vector<string> comments) {
bool omit_value = false; bool omit_value = false;
for ( auto it = comments.begin(); it != comments.end(); ++it ) { 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); comments.erase(it);
omit_value = true; omit_value = true;
break; break;

View file

@ -173,7 +173,7 @@ std::optional<std::string> source_code_range(const zeek::detail::ID* id) {
if ( id->IsType() ) { if ( id->IsType() ) {
loc = type->GetLocationInfo(); 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 // Source code won't be available to reference, so fall back
// to identifier location which may actually be in a regular // to identifier location which may actually be in a regular
// .zeek script. // .zeek script.