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
# access to yet.
-modernize-use-starts-ends-with,
-modernize-use-std-format,
-modernize-use-std-numbers,
-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
* 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,
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
==========

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);
}
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<std::string>& 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 ) {

View file

@ -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.

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,
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);

View file

@ -1053,8 +1053,7 @@ static zeek::expected<ValPtr, std::string> 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);
}

View file

@ -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);

View file

@ -767,7 +767,7 @@ std::optional<broker::data> 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<const zeek::detail::ScriptFunc*>(f) ) {
auto bc = b->SerializeCaptures();

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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, ':');

View file

@ -189,7 +189,7 @@ RecordValPtr Manager::GetMetricOptsRecord(const prometheus::MetricFamily& metric
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.
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(

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.
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

View file

@ -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' )

View file

@ -37,7 +37,7 @@ void IdentifierInfo::AddRedef(const string& script, zeek::detail::InitClass ic,
vector<string> 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;

View file

@ -173,7 +173,7 @@ std::optional<std::string> 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.