diff options
author | Timothy Flynn <trflynn89@pm.me> | 2021-08-26 13:55:41 -0400 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-08-26 22:04:09 +0100 |
commit | 262e4126346a650b442363887fe9683c56f71d1f (patch) | |
tree | 49d3bde5daa857fc0e6f76c6b7680a6d58055e4a | |
parent | d2af27d2d046111f3828914257e2f4dff065e365 (diff) | |
download | serenity-262e4126346a650b442363887fe9683c56f71d1f.zip |
AK: Implement method to convert a String/StringView to title case
This implementation preserves consecutive spaces in the orginal string.
-rw-r--r-- | AK/String.cpp | 5 | ||||
-rw-r--r-- | AK/String.h | 1 | ||||
-rw-r--r-- | AK/StringUtils.cpp | 16 | ||||
-rw-r--r-- | AK/StringUtils.h | 1 | ||||
-rw-r--r-- | AK/StringView.cpp | 5 | ||||
-rw-r--r-- | AK/StringView.h | 1 | ||||
-rw-r--r-- | Tests/AK/TestStringUtils.cpp | 14 |
7 files changed, 43 insertions, 0 deletions
diff --git a/AK/String.cpp b/AK/String.cpp index f6635f563f..dae488464c 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -446,6 +446,11 @@ String String::to_snakecase() const return StringUtils::to_snakecase(*this); } +String String::to_titlecase() const +{ + return StringUtils::to_titlecase(*this); +} + bool operator<(const char* characters, const String& string) { if (!characters) diff --git a/AK/String.h b/AK/String.h index e213ec3ebb..9bc3e5e2d1 100644 --- a/AK/String.h +++ b/AK/String.h @@ -120,6 +120,7 @@ public: [[nodiscard]] String to_lowercase() const; [[nodiscard]] String to_uppercase() const; [[nodiscard]] String to_snakecase() const; + [[nodiscard]] String to_titlecase() const; [[nodiscard]] bool is_whitespace() const { return StringUtils::is_whitespace(*this); } diff --git a/AK/StringUtils.cpp b/AK/StringUtils.cpp index 2c99617848..a73abfa09b 100644 --- a/AK/StringUtils.cpp +++ b/AK/StringUtils.cpp @@ -411,6 +411,22 @@ String to_snakecase(const StringView& str) return builder.to_string(); } +String to_titlecase(StringView const& str) +{ + StringBuilder builder; + bool next_is_upper = true; + + for (auto ch : str) { + if (next_is_upper) + builder.append_code_point(to_ascii_uppercase(ch)); + else + builder.append_code_point(to_ascii_lowercase(ch)); + next_is_upper = ch == ' '; + } + + return builder.to_string(); +} + } } diff --git a/AK/StringUtils.h b/AK/StringUtils.h index f123665fd2..df1c13b13b 100644 --- a/AK/StringUtils.h +++ b/AK/StringUtils.h @@ -69,6 +69,7 @@ enum class SearchDirection { Optional<size_t> find_any_of(StringView const& haystack, StringView const& needles, SearchDirection); String to_snakecase(const StringView&); +String to_titlecase(StringView const&); } diff --git a/AK/StringView.cpp b/AK/StringView.cpp index b742864671..0aeb124676 100644 --- a/AK/StringView.cpp +++ b/AK/StringView.cpp @@ -183,6 +183,11 @@ String StringView::to_uppercase_string() const return StringImpl::create_uppercased(characters_without_null_termination(), length()); } +String StringView::to_titlecase_string() const +{ + return StringUtils::to_titlecase(*this); +} + StringView StringView::substring_view_starting_from_substring(const StringView& substring) const { const char* remaining_characters = substring.characters_without_null_termination(); diff --git a/AK/StringView.h b/AK/StringView.h index 0d25fec81b..f98b18ff55 100644 --- a/AK/StringView.h +++ b/AK/StringView.h @@ -85,6 +85,7 @@ public: [[nodiscard]] String to_lowercase_string() const; [[nodiscard]] String to_uppercase_string() const; + [[nodiscard]] String to_titlecase_string() const; [[nodiscard]] Optional<size_t> find(char needle, size_t start = 0) const { return StringUtils::find(*this, needle, start); } [[nodiscard]] Optional<size_t> find(StringView const& needle, size_t start = 0) const { return StringUtils::find(*this, needle, start); } diff --git a/Tests/AK/TestStringUtils.cpp b/Tests/AK/TestStringUtils.cpp index 315c14f1da..948adde861 100644 --- a/Tests/AK/TestStringUtils.cpp +++ b/Tests/AK/TestStringUtils.cpp @@ -304,3 +304,17 @@ TEST_CASE(to_snakecase) EXPECT_EQ(AK::StringUtils::to_snakecase("FBar"), "f_bar"); EXPECT_EQ(AK::StringUtils::to_snakecase("FooB"), "foo_b"); } + +TEST_CASE(to_titlecase) +{ + EXPECT_EQ(AK::StringUtils::to_titlecase(""sv), ""sv); + EXPECT_EQ(AK::StringUtils::to_titlecase("f"sv), "F"sv); + EXPECT_EQ(AK::StringUtils::to_titlecase("foobar"sv), "Foobar"sv); + EXPECT_EQ(AK::StringUtils::to_titlecase("Foobar"sv), "Foobar"sv); + EXPECT_EQ(AK::StringUtils::to_titlecase("FOOBAR"sv), "Foobar"sv); + EXPECT_EQ(AK::StringUtils::to_titlecase("foo bar"sv), "Foo Bar"sv); + EXPECT_EQ(AK::StringUtils::to_titlecase("foo bAR"sv), "Foo Bar"sv); + EXPECT_EQ(AK::StringUtils::to_titlecase("foo bar"sv), "Foo Bar"sv); + EXPECT_EQ(AK::StringUtils::to_titlecase("foo bar"sv), "Foo Bar"sv); + EXPECT_EQ(AK::StringUtils::to_titlecase(" foo bar "sv), " Foo Bar "sv); +} |