srctree

Robin Linden parent fac0f15e 3f97e8f3
util/string: Support trimming things that aren't whitespace as well

inlinesplit
util/string.h added: 43, removed: 9, total 34
@@ -113,26 +113,38 @@ constexpr bool is_whitespace(char ch) {
return std::ranges::any_of(kWsChars, [ch](char ws_ch) { return ch == ws_ch; });
}
 
constexpr std::string_view trim_start(std::string_view s) {
constexpr std::string_view trim_start(std::string_view s, std::predicate<char> auto should_trim) {
// clang-tidy says this is pointer-ish, but msvc disagrees.
// NOLINTNEXTLINE(readability-qualified-auto)
auto it = std::ranges::find_if(s, [](char ch) { return !is_whitespace(ch); });
auto it = std::ranges::find_if(s, [&](char ch) { return !should_trim(ch); });
s.remove_prefix(std::distance(cbegin(s), it));
return s;
}
 
constexpr std::string_view trim_end(std::string_view s) {
auto it = std::find_if(crbegin(s), crend(s), [](char ch) { return !is_whitespace(ch); });
constexpr std::string_view trim_start(std::string_view s) {
return trim_start(s, is_whitespace);
}
 
constexpr std::string_view trim_end(std::string_view s, std::predicate<char> auto should_trim) {
auto it = std::find_if(crbegin(s), crend(s), [&](char ch) { return !should_trim(ch); });
s.remove_suffix(std::distance(crbegin(s), it));
return s;
}
 
constexpr std::string_view trim(std::string_view s) {
s = trim_start(s);
s = trim_end(s);
constexpr std::string_view trim_end(std::string_view s) {
return trim_end(s, is_whitespace);
}
 
constexpr std::string_view trim(std::string_view s, std::predicate<char> auto should_trim) {
s = trim_start(s, should_trim);
s = trim_end(s, should_trim);
return s;
}
 
constexpr std::string_view trim(std::string_view s) {
return trim(s, is_whitespace);
}
 
// https://url.spec.whatwg.org/#concept-ipv4-serializer
constexpr std::string ipv4_serialize(std::uint32_t addr) {
std::string out;
 
util/string_test.cpp added: 43, removed: 9, total 34
@@ -232,6 +232,14 @@ int main() {
expect_eq(trim_start("\r\n"sv), ""sv);
});
 
etest::test("trim start, should_trim", [] {
expect_eq(trim_start(" abc "sv, [](char c) { return c == ' '; }), "abc "sv);
expect_eq(trim_start(" abc "sv, [](char c) { return c <= 'a'; }), "bc "sv);
expect_eq(trim_start(" abc "sv, [](char c) { return c <= 'b'; }), "c "sv);
expect_eq(trim_start(" abc "sv, [](char c) { return c <= 'c'; }), ""sv);
expect_eq(trim_start(" abc "sv, [](char c) { return c == '\t'; }), " abc "sv);
});
 
etest::test("trim end", [] {
expect_eq(trim_end("abc "sv), "abc"sv);
expect_eq(trim_end("53 \r\n"sv), "53"sv);
@@ -240,6 +248,13 @@ int main() {
expect_eq(trim_end("\r\n"sv), ""sv);
});
 
etest::test("trim end, should_trim", [] {
expect_eq(trim_end(" abc "sv, [](char c) { return c == ' '; }), " abc"sv);
expect_eq(trim_end(" abc "sv, [](char c) { return c <= 'c'; }), ""sv);
expect_eq(trim_end(" abc "sv, [](char c) { return c == ' ' || c >= 'b'; }), " a"sv);
expect_eq(trim_end(" abc "sv, [](char c) { return c == '\t'; }), " abc "sv);
});
 
etest::test("trim", [] {
expect_eq(trim("abc"sv), "abc"sv);
expect_eq(trim("\t431"sv), "431"sv);
@@ -249,6 +264,13 @@ int main() {
expect_eq(trim("\r\n"sv), ""sv);
});
 
etest::test("trim, should_trim", [] {
expect_eq(trim("abcba"sv, [](char c) { return c == ' '; }), "abcba"sv);
expect_eq(trim("abcba"sv, [](char c) { return c <= 'a'; }), "bcb"sv);
expect_eq(trim("abcba"sv, [](char c) { return c <= 'b'; }), "c"sv);
expect_eq(trim("abcba"sv, [](char c) { return c <= 'c'; }), ""sv);
});
 
etest::test("trim with non-ascii characters", [] {
expect_eq(trim("Ö"sv), "Ö"sv);
expect_eq(trim(" Ö "sv), "Ö"sv);