Add support for three more string_view functions
authorJeff Bailey <jeffbailey@google.com>
Wed, 13 Jul 2022 06:00:25 +0000 (06:00 +0000)
committerJeff Bailey <jeffbailey@google.com>
Thu, 14 Jul 2022 14:20:20 +0000 (14:20 +0000)
Add support for three more string_view functions

1) starts_with(char)
2) ends_with(char)
3) find_first_of(char, size_t)

Reimplemented trim in terms of the new starts_with and ends_with.

Tested:
New unit tests.

Reviewed By: gchatelet

Differential Revision: https://reviews.llvm.org/D129618

libc/src/__support/CPP/StringView.h
libc/test/src/__support/CPP/stringview_test.cpp

index 4caec80..0f2b728 100644 (file)
@@ -122,11 +122,11 @@ public:
   }
 
   // An equivalent method is not available in std::string_view.
-  StringView trim(char C) const {
+  StringView trim(const char C) const {
     StringView Copy = *this;
-    while (!Copy.empty() && Copy.front() == C)
+    while (Copy.starts_with(C))
       Copy = Copy.drop_front();
-    while (!Copy.empty() && Copy.back() == C)
+    while (Copy.ends_with(C))
       Copy = Copy.drop_back();
     return Copy;
   }
@@ -137,6 +137,16 @@ public:
            compareMemory(Data, Prefix.Data, Prefix.Len) == 0;
   }
 
+  // Check if this string starts with the given Prefix.
+  bool starts_with(const char Prefix) const {
+    return !empty() && front() == Prefix;
+  }
+
+  // Check if this string ends with the given Prefix.
+  bool ends_with(const char Suffix) const {
+    return !empty() && back() == Suffix;
+  }
+
   // Check if this string ends with the given Suffix.
   bool ends_with(StringView Suffix) const {
     return Len >= Suffix.Len &&
@@ -157,6 +167,20 @@ public:
     return StringView(Data + Start, min(N, Len - Start));
   }
 
+  // Search for the first character matching the character
+  //
+  // Returns The index of the first character satisfying the character starting
+  // from From, or npos if not found.
+  size_t find_first_of(const char c, size_t From = 0) const noexcept {
+    StringView S = drop_front(From);
+    while (!S.empty()) {
+      if (S.front() == c)
+        return size() - S.size();
+      S = S.drop_front();
+    }
+    return npos;
+  }
+
   // Search for the first character satisfying the predicate Function
   //
   // Returns The index of the first character satisfying Function starting from
index 9f90ead..5ea7b9f 100644 (file)
@@ -49,17 +49,34 @@ TEST(LlvmLibcStringViewTest, Equals) {
 
 TEST(LlvmLibcStringViewTest, startsWith) {
   StringView v("abc");
+  ASSERT_TRUE(v.starts_with('a'));
   ASSERT_TRUE(v.starts_with(StringView("a")));
   ASSERT_TRUE(v.starts_with(StringView("ab")));
   ASSERT_TRUE(v.starts_with(StringView("abc")));
   ASSERT_TRUE(v.starts_with(StringView()));
   ASSERT_TRUE(v.starts_with(StringView("")));
+  ASSERT_FALSE(v.starts_with('1'));
   ASSERT_FALSE(v.starts_with(StringView("123")));
   ASSERT_FALSE(v.starts_with(StringView("abd")));
   ASSERT_FALSE(v.starts_with(StringView("aaa")));
   ASSERT_FALSE(v.starts_with(StringView("abcde")));
 }
 
+TEST(LlvmLibcStringViewTest, endsWith) {
+  StringView v("abc");
+  ASSERT_TRUE(v.ends_with('c'));
+  ASSERT_TRUE(v.ends_with(StringView("c")));
+  ASSERT_TRUE(v.ends_with(StringView("bc")));
+  ASSERT_TRUE(v.ends_with(StringView("abc")));
+  ASSERT_TRUE(v.ends_with(StringView()));
+  ASSERT_TRUE(v.ends_with(StringView("")));
+  ASSERT_FALSE(v.ends_with('1'));
+  ASSERT_FALSE(v.ends_with(StringView("123")));
+  ASSERT_FALSE(v.ends_with(StringView("abd")));
+  ASSERT_FALSE(v.ends_with(StringView("aaa")));
+  ASSERT_FALSE(v.ends_with(StringView("abcde")));
+}
+
 TEST(LlvmLibcStringViewTest, RemovePrefix) {
   StringView v("123456789");
 
@@ -176,3 +193,17 @@ TEST(LlvmLibcStringViewTest, ConsumeBack) {
   ASSERT_TRUE(Tmp.consume_back("bc"));
   ASSERT_TRUE(Tmp.equals("a"));
 }
+
+TEST(LlvmLibcStringViewTest, FindFirstOf) {
+  StringView Tmp("abca");
+  ASSERT_TRUE(Tmp.find_first_of('a') == 0);
+  ASSERT_TRUE(Tmp.find_first_of('d') == StringView::npos);
+  ASSERT_TRUE(Tmp.find_first_of('b') == 1);
+  ASSERT_TRUE(Tmp.find_first_of('a', 0) == 0);
+  ASSERT_TRUE(Tmp.find_first_of('b', 1) == 1);
+  ASSERT_TRUE(Tmp.find_first_of('a', 1) == 3);
+  ASSERT_TRUE(Tmp.find_first_of('a', 42) == StringView::npos);
+  ASSERT_FALSE(Tmp.find_first_of('c') == 1);
+  ASSERT_FALSE(Tmp.find_first_of('c', 0) == 1);
+  ASSERT_FALSE(Tmp.find_first_of('c', 1) == 1);
+}