[libc-commits] [libc] eebe9b2 - Revert "[reland][NFC][libc] standardize string_view"

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Tue Aug 23 05:41:01 PDT 2022


Author: Guillaume Chatelet
Date: 2022-08-23T12:40:48Z
New Revision: eebe9b2964032336087fdec8c5c3a0be163a34fa

URL: https://github.com/llvm/llvm-project/commit/eebe9b2964032336087fdec8c5c3a0be163a34fa
DIFF: https://github.com/llvm/llvm-project/commit/eebe9b2964032336087fdec8c5c3a0be163a34fa.diff

LOG: Revert "[reland][NFC][libc] standardize string_view"

This reverts commit df99774ef7d9c910941fe915689f9126258800ee.

Added: 
    

Modified: 
    libc/src/__support/CPP/string_view.h
    libc/src/stdio/printf_core/core_structs.h
    libc/test/src/__support/CPP/stringview_test.cpp
    libc/test/src/dirent/dirent_test.cpp
    libc/utils/MPFRWrapper/MPFRUtils.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CPP/string_view.h b/libc/src/__support/CPP/string_view.h
index a1aae8dff401e..6c17e9b3dbe0c 100644
--- a/libc/src/__support/CPP/string_view.h
+++ b/libc/src/__support/CPP/string_view.h
@@ -33,41 +33,30 @@ class string_view {
     return 0;
   }
 
-  static constexpr size_t length(const char *Str) {
-    for (const char *End = Str;; ++End)
-      if (*End == '\0')
-        return End - Str;
-  }
-
-  bool equals(string_view Other) const {
-    return (Len == Other.Len &&
-            compareMemory(Data, Other.Data, Other.Len) == 0);
-  }
-
 public:
-  using value_type = char;
-  using size_type = size_t;
-  using 
diff erence_type = ptr
diff _t;
-  using pointer = char *;
-  using const_pointer = const char *;
-  using reference = char &;
-  using const_reference = const char &;
-  using const_iterator = char *;
-  using iterator = const_iterator;
-
   // special value equal to the maximum value representable by the type
   // size_type.
-  inline static constexpr size_t npos = -1;
+  static constexpr size_t npos = -1;
 
   constexpr string_view() : Data(nullptr), Len(0) {}
 
   // Assumes Str is a null-terminated string. The length of the string does
   // not include the terminating null character.
-  // Preconditions: [Str, Str + ​length(Str)) is a valid range.
-  constexpr string_view(const char *Str) : Data(Str), Len(length(Str)) {}
+  explicit constexpr string_view(const char *Str) : Data(Str), Len(0) {
+    if (Str == nullptr)
+      return;
+    for (const char *D = Data; *D != '\0'; ++D, ++Len)
+      ;
+    if (Len == 0)
+      Data = nullptr;
+  }
+
+  explicit constexpr string_view(const char *Str, size_t N)
+      : Data(N ? Str : nullptr), Len(Str == nullptr ? 0 : N) {}
 
-  // Preconditions: [Str, Str + N) is a valid range.
-  constexpr string_view(const char *Str, size_t N) : Data(Str), Len(N) {}
+  // Ctor for raw literal.
+  template <size_t N>
+  constexpr string_view(const char (&Str)[N]) : string_view(Str, N - 1) {}
 
   constexpr const char *data() const { return Data; }
 
@@ -101,14 +90,16 @@ class string_view {
     return Len < Other.Len ? -1 : 1;
   }
 
+  // An equivalent method is not available in std::string_view.
+  bool equals(string_view Other) const {
+    return (Len == Other.Len &&
+            compareMemory(Data, Other.Data, Other.Len) == 0);
+  }
+
   inline bool operator==(string_view Other) const { return equals(Other); }
   inline bool operator!=(string_view Other) const { return !(*this == Other); }
-  inline bool operator<(string_view Other) const {
-    return compare(Other) == -1;
-  }
-  inline bool operator<=(string_view Other) const {
-    return compare(Other) != 1;
-  }
+  inline bool operator<(string_view Other) const { return compare(Other) == -1; }
+  inline bool operator<=(string_view Other) const { return compare(Other) != 1; }
   inline bool operator>(string_view Other) const { return compare(Other) == 1; }
   inline bool operator>=(string_view Other) const {
     return compare(Other) != -1;
@@ -125,6 +116,16 @@ class string_view {
   // The behavior is undefined if n > size().
   void remove_suffix(size_t N) { Len -= N; }
 
+  // An equivalent method is not available in std::string_view.
+  string_view trim(const char C) const {
+    string_view Copy = *this;
+    while (Copy.starts_with(C))
+      Copy = Copy.drop_front();
+    while (Copy.ends_with(C))
+      Copy = Copy.drop_back();
+    return Copy;
+  }
+
   // Check if this string starts with the given Prefix.
   bool starts_with(string_view Prefix) const {
     return Len >= Prefix.Len &&
@@ -161,27 +162,129 @@ class string_view {
     return string_view(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 {
+    string_view S = drop_front(From);
+    while (!S.empty()) {
+      if (S.front() == c)
+        return size() - S.size();
+      S = S.drop_front();
+    }
+    return npos;
+  }
+
+  // Search for the last character matching the character
+  //
+  // Return the index of the last character equal to the |c| before End.
+  size_t find_last_of(const char c, size_t End = npos) const {
+    End = End > size() ? size() : End + 1;
+    string_view S = drop_back(size() - End);
+    while (!S.empty()) {
+      if (S.back() == c)
+        return S.size() - 1;
+      S = S.drop_back();
+    }
+    return npos;
+  }
+
+  // Search for the first character satisfying the predicate Function
+  //
+  // Returns The index of the first character satisfying Function starting from
+  // From, or npos if not found.
+  template <typename F> size_t find_if(F Function, size_t From = 0) const {
+    string_view S = drop_front(From);
+    while (!S.empty()) {
+      if (Function(S.front()))
+        return size() - S.size();
+      S = S.drop_front();
+    }
+    return npos;
+  }
+
+  // Search for the first character not satisfying the predicate Function
+  // Returns The index of the first character not satisfying Function starting
+  // from From, or npos if not found.
+  template <typename F> size_t find_if_not(F Function, size_t From = 0) const {
+    return find_if([Function](char c) { return !Function(c); }, From);
+  }
+
   // front - Get the first character in the string.
   char front() const { return Data[0]; }
 
   // back - Get the last character in the string.
   char back() const { return Data[Len - 1]; }
 
-  // Finds the first occurence of c in this view, starting at position From.
-  size_t find_first_of(const char c, size_t From = 0) const {
-    for (size_t Pos = From; Pos < size(); ++Pos)
-      if ((*this)[Pos] == c)
-        return Pos;
-    return npos;
+  // Return a string_view equal to 'this' but with the first N elements
+  // dropped.
+  string_view drop_front(size_t N = 1) const { return substr(N); }
+
+  // Return a string_view equal to 'this' but with the last N elements
+  // dropped.
+  string_view drop_back(size_t N = 1) const { return substr(0, size() - N); }
+
+  // Return a string_view equal to 'this' but with only the first N
+  // elements remaining.  If N is greater than the length of the
+  // string, the entire string is returned.
+  string_view take_front(size_t N = 1) const {
+    if (N >= size())
+      return *this;
+    return drop_back(size() - N);
   }
 
-  // Finds the last occurence of c in this view, ending at position End.
-  size_t find_last_of(const char c, size_t End = npos) const {
-    End = End >= size() ? size() : End + 1;
-    for (; End > 0; --End)
-      if ((*this)[End - 1] == c)
-        return End - 1;
-    return npos;
+  // Return a string_view equal to 'this' but with only the last N
+  // elements remaining.  If N is greater than the length of the
+  // string, the entire string is returned.
+  string_view take_back(size_t N = 1) const {
+    if (N >= size())
+      return *this;
+    return drop_front(size() - N);
+  }
+
+  // Return the longest prefix of 'this' such that every character
+  // in the prefix satisfies the given predicate.
+  template <typename F> string_view take_while(F Function) const {
+    return substr(0, find_if_not(Function));
+  }
+
+  // Return the longest prefix of 'this' such that no character in
+  // the prefix satisfies the given predicate.
+  template <typename F> string_view take_until(F Function) const {
+    return substr(0, find_if(Function));
+  }
+
+  // Return a string_view equal to 'this', but with all characters satisfying
+  // the given predicate dropped from the beginning of the string.
+  template <typename F> string_view drop_while(F Function) const {
+    return substr(find_if_not(Function));
+  }
+
+  // Return a string_view equal to 'this', but with all characters not
+  // satisfying the given predicate dropped from the beginning of the string.
+  template <typename F> string_view drop_until(F Function) const {
+    return substr(find_if(Function));
+  }
+
+  // Returns true if this string_view has the given prefix and removes that
+  // prefix.
+  bool consume_front(string_view Prefix) {
+    if (!starts_with(Prefix))
+      return false;
+
+    *this = drop_front(Prefix.size());
+    return true;
+  }
+
+  // Returns true if this string_view has the given suffix and removes that
+  // suffix.
+  bool consume_back(string_view Suffix) {
+    if (!ends_with(Suffix))
+      return false;
+
+    *this = drop_back(Suffix.size());
+    return true;
   }
 };
 

diff  --git a/libc/src/stdio/printf_core/core_structs.h b/libc/src/stdio/printf_core/core_structs.h
index 25e530337eec4..c229096039feb 100644
--- a/libc/src/stdio/printf_core/core_structs.h
+++ b/libc/src/stdio/printf_core/core_structs.h
@@ -58,8 +58,8 @@ struct FormatSection {
     if (has_conv != other.has_conv)
       return false;
 
-    if (cpp::string_view(raw_string, raw_len) !=
-        cpp::string_view(other.raw_string, other.raw_len))
+    if (!cpp::string_view(raw_string, raw_len)
+             .equals(cpp::string_view(other.raw_string, other.raw_len)))
       return false;
 
     if (has_conv) {

diff  --git a/libc/test/src/__support/CPP/stringview_test.cpp b/libc/test/src/__support/CPP/stringview_test.cpp
index bd6b614218bb4..87853d8b1cfc7 100644
--- a/libc/test/src/__support/CPP/stringview_test.cpp
+++ b/libc/test/src/__support/CPP/stringview_test.cpp
@@ -1,5 +1,4 @@
-//===-- Unittests for string_view
-//------------------------------------------===//
+//===-- Unittests for string_view ------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -19,11 +18,19 @@ TEST(LlvmLibcStringViewTest, InitializeCheck) {
 
   v = string_view("");
   ASSERT_EQ(v.size(), size_t(0));
-  ASSERT_TRUE(v.data() != nullptr);
+  ASSERT_TRUE(v.data() == nullptr);
+
+  v = string_view(nullptr);
+  ASSERT_EQ(v.size(), size_t(0));
+  ASSERT_TRUE(v.data() == nullptr);
+
+  v = string_view(nullptr, 10);
+  ASSERT_EQ(v.size(), size_t(0));
+  ASSERT_TRUE(v.data() == nullptr);
 
   v = string_view("abc", 0);
   ASSERT_EQ(v.size(), size_t(0));
-  ASSERT_TRUE(v.data() != nullptr);
+  ASSERT_TRUE(v.data() == nullptr);
 
   v = string_view("123456789");
   ASSERT_EQ(v.size(), size_t(9));
@@ -31,13 +38,13 @@ TEST(LlvmLibcStringViewTest, InitializeCheck) {
 
 TEST(LlvmLibcStringViewTest, Equals) {
   string_view v("abc");
-  ASSERT_EQ(v, string_view("abc"));
-  ASSERT_NE(v, string_view());
-  ASSERT_NE(v, string_view(""));
-  ASSERT_NE(v, string_view("123"));
-  ASSERT_NE(v, string_view("abd"));
-  ASSERT_NE(v, string_view("aaa"));
-  ASSERT_NE(v, string_view("abcde"));
+  ASSERT_TRUE(v.equals(string_view("abc")));
+  ASSERT_FALSE(v.equals(string_view()));
+  ASSERT_FALSE(v.equals(string_view("")));
+  ASSERT_FALSE(v.equals(string_view("123")));
+  ASSERT_FALSE(v.equals(string_view("abd")));
+  ASSERT_FALSE(v.equals(string_view("aaa")));
+  ASSERT_FALSE(v.equals(string_view("abcde")));
 }
 
 TEST(LlvmLibcStringViewTest, startsWith) {
@@ -74,12 +81,12 @@ TEST(LlvmLibcStringViewTest, RemovePrefix) {
   string_view a("123456789");
   a.remove_prefix(0);
   ASSERT_EQ(a.size(), size_t(9));
-  ASSERT_TRUE(a == "123456789");
+  ASSERT_TRUE(a.equals(string_view("123456789")));
 
   string_view b("123456789");
   b.remove_prefix(4);
   ASSERT_EQ(b.size(), size_t(5));
-  ASSERT_TRUE(b == "56789");
+  ASSERT_TRUE(b.equals(string_view("56789")));
 
   string_view c("123456789");
   c.remove_prefix(9);
@@ -90,18 +97,59 @@ TEST(LlvmLibcStringViewTest, RemoveSuffix) {
   string_view a("123456789");
   a.remove_suffix(0);
   ASSERT_EQ(a.size(), size_t(9));
-  ASSERT_TRUE(a == "123456789");
+  ASSERT_TRUE(a.equals(string_view("123456789")));
 
   string_view b("123456789");
   b.remove_suffix(4);
   ASSERT_EQ(b.size(), size_t(5));
-  ASSERT_TRUE(b == "12345");
+  ASSERT_TRUE(b.equals(string_view("12345")));
 
   string_view c("123456789");
   c.remove_suffix(9);
   ASSERT_EQ(c.size(), size_t(0));
 }
 
+TEST(LlvmLibcStringViewTest, TrimSingleChar) {
+  string_view v("     123456789   ");
+  auto t = v.trim(' ');
+  ASSERT_EQ(t.size(), size_t(9));
+  ASSERT_TRUE(t.equals(string_view("123456789")));
+
+  v = string_view("====12345==");
+  t = v.trim(' ');
+  ASSERT_EQ(v.size(), size_t(11));
+  ASSERT_TRUE(t.equals(string_view("====12345==")));
+
+  t = v.trim('=');
+  ASSERT_EQ(t.size(), size_t(5));
+  ASSERT_TRUE(t.equals(string_view("12345")));
+
+  v = string_view("12345===");
+  t = v.trim('=');
+  ASSERT_EQ(t.size(), size_t(5));
+  ASSERT_TRUE(t.equals(string_view("12345")));
+
+  v = string_view("===========12345");
+  t = v.trim('=');
+  ASSERT_EQ(t.size(), size_t(5));
+  ASSERT_TRUE(t.equals(string_view("12345")));
+
+  v = string_view("============");
+  t = v.trim('=');
+  ASSERT_EQ(t.size(), size_t(0));
+  ASSERT_TRUE(t.data() == nullptr);
+
+  v = string_view();
+  t = v.trim(' ');
+  ASSERT_EQ(t.size(), size_t(0));
+  ASSERT_TRUE(t.data() == nullptr);
+
+  v = string_view("");
+  t = v.trim(' ');
+  ASSERT_EQ(t.size(), size_t(0));
+  ASSERT_TRUE(t.data() == nullptr);
+}
+
 TEST(LlvmLibcStringViewTest, Observer) {
   string_view ABC("abc");
   ASSERT_EQ(ABC.size(), size_t(3));
@@ -112,6 +160,32 @@ TEST(LlvmLibcStringViewTest, Observer) {
 
 bool isDigit(char c) { return c >= '0' && c <= '9'; }
 
+TEST(LlvmLibcStringViewTest, Transform) {
+  ASSERT_TRUE(string_view("123abc").drop_back(3).equals("123"));
+  ASSERT_TRUE(string_view("123abc").drop_front(3).equals("abc"));
+  ASSERT_TRUE(string_view("123abc").take_back(3).equals("abc"));
+  ASSERT_TRUE(string_view("123abc").take_front(3).equals("123"));
+
+  ASSERT_TRUE(string_view("123abc").take_while(&isDigit).equals("123"));
+  ASSERT_TRUE(string_view("abc123").take_until(&isDigit).equals("abc"));
+  ASSERT_TRUE(string_view("123abc").drop_while(&isDigit).equals("abc"));
+  ASSERT_TRUE(string_view("abc123").drop_until(&isDigit).equals("123"));
+}
+
+TEST(LlvmLibcStringViewTest, ConsumeFront) {
+  string_view Tmp("abc");
+  ASSERT_FALSE(Tmp.consume_front("###"));
+  ASSERT_TRUE(Tmp.consume_front("ab"));
+  ASSERT_TRUE(Tmp.equals("c"));
+}
+
+TEST(LlvmLibcStringViewTest, ConsumeBack) {
+  string_view Tmp("abc");
+  ASSERT_FALSE(Tmp.consume_back("###"));
+  ASSERT_TRUE(Tmp.consume_back("bc"));
+  ASSERT_TRUE(Tmp.equals("a"));
+}
+
 TEST(LlvmLibcStringViewTest, FindFirstOf) {
   string_view Tmp("abca");
   ASSERT_TRUE(Tmp.find_first_of('a') == 0);

diff  --git a/libc/test/src/dirent/dirent_test.cpp b/libc/test/src/dirent/dirent_test.cpp
index 82fb09acedd56..5fb32052ce032 100644
--- a/libc/test/src/dirent/dirent_test.cpp
+++ b/libc/test/src/dirent/dirent_test.cpp
@@ -33,13 +33,13 @@ TEST(LlvmLibcDirentTest, SimpleOpenAndRead) {
     struct ::dirent *d = __llvm_libc::readdir(dir);
     if (d == nullptr)
       break;
-    if (string_view(&d->d_name[0]) == "file1.txt")
+    if (string_view(&d->d_name[0]).equals("file1.txt"))
       file1 = d;
-    if (string_view(&d->d_name[0]) == "file2.txt")
+    if (string_view(&d->d_name[0]).equals("file2.txt"))
       file2 = d;
-    if (string_view(&d->d_name[0]) == "dir1")
+    if (string_view(&d->d_name[0]).equals("dir1"))
       dir1 = d;
-    if (string_view(&d->d_name[0]) == "dir2")
+    if (string_view(&d->d_name[0]).equals("dir2"))
       dir2 = d;
   }
 

diff  --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 54c0939929576..60651dacd7421 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -380,12 +380,7 @@ class MPFRNumber {
     char buffer[printBufSize];
     mpfr_snprintf(buffer, printBufSize, "%100.50Rf", value);
     cpp::string_view view(buffer);
-    // Trim whitespaces
-    const char whitespace = ' ';
-    while (!view.empty() && view.front() == whitespace)
-      view.remove_prefix(1);
-    while (!view.empty() && view.back() == whitespace)
-      view.remove_suffix(1);
+    view = view.trim(' ');
     return std::string(view.data());
   }
 


        


More information about the libc-commits mailing list