diff --git a/src/util/StringStrip.cxx b/src/util/StringStrip.cxx index fb201cac8..9ad65cee0 100644 --- a/src/util/StringStrip.cxx +++ b/src/util/StringStrip.cxx @@ -1,5 +1,5 @@ /* - * Copyright 2009-2021 Max Kellermann + * Copyright 2009-2022 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,7 @@ #include "StringStrip.hxx" #include "CharUtil.hxx" +#include #include const char * @@ -50,6 +51,18 @@ StripLeft(const char *p, const char *end) noexcept return p; } +std::string_view +StripLeft(const std::string_view s) noexcept +{ + auto i = std::find_if_not(s.begin(), s.end(), + [](auto ch){ return IsWhitespaceOrNull(ch); }); + + return { + i, + s.end(), + }; +} + const char * StripRight(const char *p, const char *end) noexcept { @@ -76,6 +89,15 @@ StripRight(char *p) noexcept p[new_length] = 0; } +std::string_view +StripRight(std::string_view s) noexcept +{ + auto i = std::find_if_not(s.rbegin(), s.rend(), + [](auto ch){ return IsWhitespaceOrNull(ch); }); + + return s.substr(0, std::distance(i, s.rend())); +} + char * Strip(char *p) noexcept { @@ -83,3 +105,9 @@ Strip(char *p) noexcept StripRight(p); return p; } + +std::string_view +Strip(std::string_view s) noexcept +{ + return StripRight(StripLeft(s)); +} diff --git a/src/util/StringStrip.hxx b/src/util/StringStrip.hxx index e2786fc91..d2400941a 100644 --- a/src/util/StringStrip.hxx +++ b/src/util/StringStrip.hxx @@ -1,5 +1,5 @@ /* - * Copyright 2009-2021 Max Kellermann + * Copyright 2009-2022 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,10 +27,10 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef STRING_STRIP_HXX -#define STRING_STRIP_HXX +#pragma once #include +#include /** * Skips whitespace at the beginning of the string, and returns the @@ -57,6 +57,10 @@ StripLeft(char *p) noexcept const char * StripLeft(const char *p, const char *end) noexcept; +[[gnu::pure]] +std::string_view +StripLeft(std::string_view s) noexcept; + /** * Determine the string's end as if it was stripped on the right side. */ @@ -90,6 +94,10 @@ StripRight(const char *p, std::size_t length) noexcept; void StripRight(char *p) noexcept; +[[gnu::pure]] +std::string_view +StripRight(std::string_view s) noexcept; + /** * Skip whitespace at the beginning and terminate the string after the * last non-whitespace character. @@ -98,4 +106,6 @@ StripRight(char *p) noexcept; char * Strip(char *p) noexcept; -#endif +[[gnu::pure]] +std::string_view +Strip(std::string_view s) noexcept; diff --git a/test/util/TestStringStrip.cxx b/test/util/TestStringStrip.cxx new file mode 100644 index 000000000..57bb70452 --- /dev/null +++ b/test/util/TestStringStrip.cxx @@ -0,0 +1,39 @@ +/* + * Unit tests for src/util/ + */ + +#include "util/StringStrip.hxx" + +#include + +using std::string_view_literals::operator""sv; + +TEST(StringStrip, StripLeft) +{ + EXPECT_EQ(StripLeft(""sv), ""sv); + EXPECT_EQ(StripLeft(" "sv), ""sv); + EXPECT_EQ(StripLeft("\t"sv), ""sv); + EXPECT_EQ(StripLeft("\0"sv), ""sv); + EXPECT_EQ(StripLeft(" a "sv), "a "sv); + EXPECT_EQ(StripLeft("\0a\0"sv), "a\0"sv); +} + +TEST(StringStrip, StripRight) +{ + EXPECT_EQ(StripRight(""sv), ""sv); + EXPECT_EQ(StripRight(" "sv), ""sv); + EXPECT_EQ(StripRight("\t"sv), ""sv); + EXPECT_EQ(StripRight("\0"sv), ""sv); + EXPECT_EQ(StripRight(" a "sv), " a"sv); + EXPECT_EQ(StripRight("\0a\0"sv), "\0a"sv); +} + +TEST(StringStrip, Strip) +{ + EXPECT_EQ(Strip(""sv), ""sv); + EXPECT_EQ(Strip(" "sv), ""sv); + EXPECT_EQ(Strip("\t"sv), ""sv); + EXPECT_EQ(Strip("\0"sv), ""sv); + EXPECT_EQ(Strip(" a "sv), "a"sv); + EXPECT_EQ(Strip("\0a\0"sv), "a"sv); +} diff --git a/test/util/meson.build b/test/util/meson.build index cf0865d9b..23ebab3b9 100644 --- a/test/util/meson.build +++ b/test/util/meson.build @@ -8,6 +8,7 @@ test( 'TestIntrusiveList.cxx', 'TestMimeType.cxx', 'TestSplitString.cxx', + 'TestStringStrip.cxx', 'TestTemplateString.cxx', 'TestUriExtract.cxx', 'TestUriQueryParser.cxx',