diff --git a/AK/String.h b/AK/String.h index 9fdb05b68db..1a19b6f429c 100644 --- a/AK/String.h +++ b/AK/String.h @@ -45,10 +45,10 @@ public: // Creates a new String from a sequence of UTF-8 encoded code points. static ErrorOr from_utf8(StringView); - // Creates a new String by transforming this String to lower- or uppercase. Using these methods - // require linking LibUnicode into your application. + // Creates a new String by case-transforming this String. Using these methods require linking LibUnicode into your application. ErrorOr to_lowercase(Optional const& locale = {}) const; ErrorOr to_uppercase(Optional const& locale = {}) const; + ErrorOr to_titlecase(Optional const& locale = {}) const; // Creates a substring with a deep copy of the specified data window. ErrorOr substring_from_byte_offset(size_t start, size_t byte_count) const; diff --git a/Tests/AK/TestString.cpp b/Tests/AK/TestString.cpp index 727b30190ee..42f5ffc63f9 100644 --- a/Tests/AK/TestString.cpp +++ b/Tests/AK/TestString.cpp @@ -163,6 +163,30 @@ TEST_CASE(to_uppercase) } } +TEST_CASE(to_titlecase) +{ + { + auto string = MUST(String::from_utf8("foo bar baz"sv)); + auto result = MUST(string.to_titlecase()); + EXPECT_EQ(result, "Foo Bar Baz"sv); + } + { + auto string = MUST(String::from_utf8("foo \n \r bar \t baz"sv)); + auto result = MUST(string.to_titlecase()); + EXPECT_EQ(result, "Foo \n \r Bar \t Baz"sv); + } + { + auto string = MUST(String::from_utf8("f\"oo\" b'ar'"sv)); + auto result = MUST(string.to_titlecase()); + EXPECT_EQ(result, "F\"Oo\" B'Ar'"sv); + } + { + auto string = MUST(String::from_utf8("123dollars"sv)); + auto result = MUST(string.to_titlecase()); + EXPECT_EQ(result, "123Dollars"sv); + } +} + TEST_CASE(is_one_of) { auto foo = MUST(String::from_utf8("foo"sv)); diff --git a/Userland/Libraries/LibUnicode/String.cpp b/Userland/Libraries/LibUnicode/String.cpp index 4cbc47d5ad8..5251d310bd9 100644 --- a/Userland/Libraries/LibUnicode/String.cpp +++ b/Userland/Libraries/LibUnicode/String.cpp @@ -26,4 +26,11 @@ ErrorOr String::to_uppercase(Optional const& locale) const return builder.to_string(); } +ErrorOr String::to_titlecase(Optional const& locale) const +{ + StringBuilder builder; + TRY(Unicode::Detail::build_titlecase_string(code_points(), builder, locale)); + return builder.to_string(); +} + }