Explorar o código

AK: Implement method to convert a String/StringView to title case

This implementation preserves consecutive spaces in the orginal string.
Timothy Flynn %!s(int64=3) %!d(string=hai) anos
pai
achega
262e412634
Modificáronse 7 ficheiros con 43 adicións e 0 borrados
  1. 5 0
      AK/String.cpp
  2. 1 0
      AK/String.h
  3. 16 0
      AK/StringUtils.cpp
  4. 1 0
      AK/StringUtils.h
  5. 5 0
      AK/StringView.cpp
  6. 1 0
      AK/StringView.h
  7. 14 0
      Tests/AK/TestStringUtils.cpp

+ 5 - 0
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)

+ 1 - 0
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); }
 

+ 16 - 0
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();
+}
+
 }
 
 }

+ 1 - 0
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&);
 
 }
 

+ 5 - 0
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();

+ 1 - 0
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); }

+ 14 - 0
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);
+}