diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp index 14eb16b98..eb4df97fa 100644 --- a/adb/socket_spec.cpp +++ b/adb/socket_spec.cpp @@ -118,7 +118,7 @@ static bool tcp_host_is_local(const std::string& hostname) { bool is_socket_spec(const std::string& spec) { for (const auto& it : kLocalSocketTypes) { std::string prefix = it.first + ":"; - if (StartsWith(spec, prefix.c_str())) { + if (StartsWith(spec, prefix)) { return true; } } @@ -128,7 +128,7 @@ bool is_socket_spec(const std::string& spec) { bool is_local_socket_spec(const std::string& spec) { for (const auto& it : kLocalSocketTypes) { std::string prefix = it.first + ":"; - if (StartsWith(spec, prefix.c_str())) { + if (StartsWith(spec, prefix)) { return true; } } @@ -170,7 +170,7 @@ int socket_spec_connect(const std::string& spec, std::string* error) { for (const auto& it : kLocalSocketTypes) { std::string prefix = it.first + ":"; - if (StartsWith(spec, prefix.c_str())) { + if (StartsWith(spec, prefix)) { if (!it.second.available) { *error = StringPrintf("socket type %s is unavailable on this platform", it.first.c_str()); @@ -213,7 +213,7 @@ int socket_spec_listen(const std::string& spec, std::string* error, int* resolve for (const auto& it : kLocalSocketTypes) { std::string prefix = it.first + ":"; - if (StartsWith(spec, prefix.c_str())) { + if (StartsWith(spec, prefix)) { if (!it.second.available) { *error = StringPrintf("attempted to listen on unavailable socket type: '%s'", spec.c_str()); diff --git a/base/include/android-base/strings.h b/base/include/android-base/strings.h index f5f5c1139..c11acb10d 100644 --- a/base/include/android-base/strings.h +++ b/base/include/android-base/strings.h @@ -57,12 +57,18 @@ extern template std::string Join(const std::vector&, const std::str extern template std::string Join(const std::vector&, const std::string&); // Tests whether 's' starts with 'prefix'. +// TODO: string_view bool StartsWith(const std::string& s, const char* prefix); bool StartsWithIgnoreCase(const std::string& s, const char* prefix); +bool StartsWith(const std::string& s, const std::string& prefix); +bool StartsWithIgnoreCase(const std::string& s, const std::string& prefix); // Tests whether 's' ends with 'suffix'. +// TODO: string_view bool EndsWith(const std::string& s, const char* suffix); bool EndsWithIgnoreCase(const std::string& s, const char* suffix); +bool EndsWith(const std::string& s, const std::string& prefix); +bool EndsWithIgnoreCase(const std::string& s, const std::string& prefix); // Tests whether 'lhs' equals 'rhs', ignoring case. bool EqualsIgnoreCase(const std::string& lhs, const std::string& rhs); diff --git a/base/strings.cpp b/base/strings.cpp index bfdaf1244..a8bb2a986 100644 --- a/base/strings.cpp +++ b/base/strings.cpp @@ -91,12 +91,20 @@ bool StartsWith(const std::string& s, const char* prefix) { return strncmp(s.c_str(), prefix, strlen(prefix)) == 0; } +bool StartsWith(const std::string& s, const std::string& prefix) { + return strncmp(s.c_str(), prefix.c_str(), prefix.size()) == 0; +} + bool StartsWithIgnoreCase(const std::string& s, const char* prefix) { return strncasecmp(s.c_str(), prefix, strlen(prefix)) == 0; } -static bool EndsWith(const std::string& s, const char* suffix, bool case_sensitive) { - size_t suffix_length = strlen(suffix); +bool StartsWithIgnoreCase(const std::string& s, const std::string& prefix) { + return strncasecmp(s.c_str(), prefix.c_str(), prefix.size()) == 0; +} + +static bool EndsWith(const std::string& s, const char* suffix, size_t suffix_length, + bool case_sensitive) { size_t string_length = s.size(); if (suffix_length > string_length) { return false; @@ -106,11 +114,19 @@ static bool EndsWith(const std::string& s, const char* suffix, bool case_sensiti } bool EndsWith(const std::string& s, const char* suffix) { - return EndsWith(s, suffix, true); + return EndsWith(s, suffix, strlen(suffix), true); +} + +bool EndsWith(const std::string& s, const std::string& suffix) { + return EndsWith(s, suffix.c_str(), suffix.size(), true); } bool EndsWithIgnoreCase(const std::string& s, const char* suffix) { - return EndsWith(s, suffix, false); + return EndsWith(s, suffix, strlen(suffix), false); +} + +bool EndsWithIgnoreCase(const std::string& s, const std::string& suffix) { + return EndsWith(s, suffix.c_str(), suffix.size(), false); } bool EqualsIgnoreCase(const std::string& lhs, const std::string& rhs) { diff --git a/base/strings_test.cpp b/base/strings_test.cpp index 121197cab..b8639ead4 100644 --- a/base/strings_test.cpp +++ b/base/strings_test.cpp @@ -253,6 +253,26 @@ TEST(strings, EndsWithIgnoreCase_contains_prefix) { ASSERT_FALSE(android::base::EndsWithIgnoreCase("foobar", "FOO")); } +TEST(strings, StartsWith_std_string) { + ASSERT_TRUE(android::base::StartsWith("hello", std::string{"hell"})); + ASSERT_FALSE(android::base::StartsWith("goodbye", std::string{"hell"})); +} + +TEST(strings, StartsWithIgnoreCase_std_string) { + ASSERT_TRUE(android::base::StartsWithIgnoreCase("HeLlO", std::string{"hell"})); + ASSERT_FALSE(android::base::StartsWithIgnoreCase("GoOdByE", std::string{"hell"})); +} + +TEST(strings, EndsWith_std_string) { + ASSERT_TRUE(android::base::EndsWith("hello", std::string{"lo"})); + ASSERT_FALSE(android::base::EndsWith("goodbye", std::string{"lo"})); +} + +TEST(strings, EndsWithIgnoreCase_std_string) { + ASSERT_TRUE(android::base::EndsWithIgnoreCase("HeLlO", std::string{"lo"})); + ASSERT_FALSE(android::base::EndsWithIgnoreCase("GoOdByE", std::string{"lo"})); +} + TEST(strings, EqualsIgnoreCase) { ASSERT_TRUE(android::base::EqualsIgnoreCase("foo", "FOO")); ASSERT_TRUE(android::base::EqualsIgnoreCase("FOO", "foo")); diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp index b19ab781f..f81206a18 100644 --- a/bootstat/bootstat.cpp +++ b/bootstat/bootstat.cpp @@ -315,8 +315,7 @@ bool isStrongRebootReason(const std::string& r) { for (auto& s : knownReasons) { if (s == "cold") break; // Prefix defined as terminated by a nul or comma (,). - if (android::base::StartsWith(r, s.c_str()) && - ((r.length() == s.length()) || (r[s.length()] == ','))) { + if (android::base::StartsWith(r, s) && ((r.length() == s.length()) || (r[s.length()] == ','))) { return true; } } @@ -328,8 +327,7 @@ bool isKernelRebootReason(const std::string& r) { for (auto& s : knownReasons) { if (s == "recovery") break; // Prefix defined as terminated by a nul or comma (,). - if (android::base::StartsWith(r, s.c_str()) && - ((r.length() == s.length()) || (r[s.length()] == ','))) { + if (android::base::StartsWith(r, s) && ((r.length() == s.length()) || (r[s.length()] == ','))) { return true; } } @@ -340,8 +338,7 @@ bool isKernelRebootReason(const std::string& r) { bool isKnownRebootReason(const std::string& r) { for (auto& s : knownReasons) { // Prefix defined as terminated by a nul or comma (,). - if (android::base::StartsWith(r, s.c_str()) && - ((r.length() == s.length()) || (r[s.length()] == ','))) { + if (android::base::StartsWith(r, s) && ((r.length() == s.length()) || (r[s.length()] == ','))) { return true; } } diff --git a/init/action.cpp b/init/action.cpp index 5fa6becf8..ab51eeae7 100644 --- a/init/action.cpp +++ b/init/action.cpp @@ -358,7 +358,7 @@ Result ActionParser::ParseSection(std::vector&& args, Subcontext* action_subcontext = nullptr; if (subcontexts_) { for (auto& subcontext : *subcontexts_) { - if (StartsWith(filename, subcontext.path_prefix().c_str())) { + if (StartsWith(filename, subcontext.path_prefix())) { action_subcontext = &subcontext; break; } diff --git a/init/devices.cpp b/init/devices.cpp index af6b50acb..8d27f4f09 100644 --- a/init/devices.cpp +++ b/init/devices.cpp @@ -127,7 +127,7 @@ Permissions::Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t } bool Permissions::Match(const std::string& path) const { - if (prefix_) return StartsWith(path, name_.c_str()); + if (prefix_) return StartsWith(path, name_); if (wildcard_) return fnmatch(name_.c_str(), path.c_str(), FNM_PATHNAME) == 0; return path == name_; } @@ -300,9 +300,9 @@ std::vector DeviceHandler::GetBlockDeviceSymlinks(const Uevent& uev static const std::string devices_platform_prefix = "/devices/platform/"; static const std::string devices_prefix = "/devices/"; - if (StartsWith(device, devices_platform_prefix.c_str())) { + if (StartsWith(device, devices_platform_prefix)) { device = device.substr(devices_platform_prefix.length()); - } else if (StartsWith(device, devices_prefix.c_str())) { + } else if (StartsWith(device, devices_prefix)) { device = device.substr(devices_prefix.length()); } diff --git a/init/parser.cpp b/init/parser.cpp index 6ddb09f2b..4c69bac3f 100644 --- a/init/parser.cpp +++ b/init/parser.cpp @@ -76,7 +76,7 @@ void Parser::ParseData(const std::string& filename, const std::string& data) { // current section parsers. This is meant for /sys/ and /dev/ line entries for // uevent. for (const auto& [prefix, callback] : line_callbacks_) { - if (android::base::StartsWith(args[0], prefix.c_str())) { + if (android::base::StartsWith(args[0], prefix)) { end_section(); if (auto result = callback(std::move(args)); !result) { diff --git a/init/service.cpp b/init/service.cpp index 331b859b7..a4e33f7ec 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -1125,7 +1125,7 @@ Result ServiceParser::ParseSection(std::vector&& args, Subcontext* restart_action_subcontext = nullptr; if (subcontexts_) { for (auto& subcontext : *subcontexts_) { - if (StartsWith(filename, subcontext.path_prefix().c_str())) { + if (StartsWith(filename, subcontext.path_prefix())) { restart_action_subcontext = &subcontext; break; } diff --git a/libcutils/tests/fs_config.cpp b/libcutils/tests/fs_config.cpp index 391adb64b..d5dc66a97 100644 --- a/libcutils/tests/fs_config.cpp +++ b/libcutils/tests/fs_config.cpp @@ -81,7 +81,7 @@ static bool check_unique(std::vector& paths, const std::string& con } // check if path is / - if (android::base::StartsWith(path, prefix.c_str())) { + if (android::base::StartsWith(path, prefix)) { // rebuild path to be system//... to check for alias path = alternate + path.substr(prefix.size()); for (second = 0; second < paths.size(); ++second) { @@ -97,7 +97,7 @@ static bool check_unique(std::vector& paths, const std::string& con } // check if path is system// - if (android::base::StartsWith(path, alternate.c_str())) { + if (android::base::StartsWith(path, alternate)) { // rebuild path to be /... to check for alias path = prefix + path.substr(alternate.size()); for (second = 0; second < paths.size(); ++second) { diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp index 8c8d064a2..e9f0c0fca 100644 --- a/libnativeloader/native_loader.cpp +++ b/libnativeloader/native_loader.cpp @@ -382,7 +382,7 @@ class LibraryNamespaces { config_file_path, &sonames, [&company_name](const std::string& soname, std::string* error_msg) { if (android::base::StartsWith(soname, "lib") && - android::base::EndsWith(soname, ("." + company_name + ".so").c_str())) { + android::base::EndsWith(soname, "." + company_name + ".so")) { return true; } else { *error_msg = "Library name \"" + soname +