Add a new split method to StringRef that puts the substrings in a vector.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 13 Nov 2009 01:24:40 +0000 (01:24 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 13 Nov 2009 01:24:40 +0000 (01:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@87058 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/StringRef.h
lib/Support/StringExtras.cpp
unittests/ADT/StringRefTest.cpp

index b07dcc12ced310f5ac4a3079590deb1b0a5ea28f..6ccb37d346c236b19ef6639fabbc58b9b99b4cca 100644 (file)
 #include <cstring>
 #include <string>
 
+namespace std {
+ template<typename _Tp>
+ class allocator;
+
+ template<typename _Tp, typename _Alloc>
+ class vector;
+}
+
 namespace llvm {
 
   /// StringRef - Represent a constant reference to a string, i.e. a character
@@ -314,6 +322,25 @@ namespace llvm {
       return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos));
     }
 
+    /// split - Split into substrings around the occurences of a separator
+    /// string.
+    ///
+    /// Each substring is stored in \arg A. If \arg MaxSplit is >= 0, at most
+    /// \arg MaxSplit splits are done and consequently <= \arg MaxSplit
+    /// elements are added to A.
+    /// If \arg KeepEmpty is false, empty strings are not added to \arg A. They
+    /// still count when considering \arg MaxSplit
+    /// An useful invariant is that
+    /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true
+    ///
+    /// \param A - Where to put the substrings.
+    /// \param Separator - The string to split on.
+    /// \param MaxSplit - The maximum number of times the string is split.
+    /// \parm KeepEmpty - True if empty substring should be added.
+    void split(std::vector<StringRef, std::allocator<StringRef> > &A,
+               StringRef Separator, unsigned MaxSplit = -1,
+               bool KeepEmpty = true) const;
+
     /// rsplit - Split into two substrings around the last occurence of a
     /// separator character.
     ///
index c72f12165343116fcdf8c0496d0023cf7c1ee651..05ba34b2e7b08cfe7ac689daa1d66ed1b981224e 100644 (file)
@@ -56,3 +56,22 @@ void llvm::SplitString(const std::string &Source,
     S2 = getToken(S, Delimiters);
   }
 }
+
+void llvm::StringRef::split(std::vector<StringRef> &A,
+                            StringRef Separators, unsigned MaxSplit,
+                            bool KeepEmpty) const {
+  StringRef rest = *this;
+
+  for (unsigned splits = 0;
+       rest.size() != 0 && (MaxSplit < 0 || splits < MaxSplit);
+       ++splits) {
+    std::pair<llvm::StringRef, llvm::StringRef> p = rest.split(Separators);
+
+    if (p.first.size() != 0 || KeepEmpty)
+      A.push_back(p.first);
+    rest = p.second;
+  }
+
+  if (rest.size() != 0 || KeepEmpty)
+    A.push_back(rest);
+}
index 7828b5fadf2c1ace4ec6273be7e89c45fc3b4cf0..3c0cc58ad2d5c3a110376e3ccdd0fe06f738d963 100644 (file)
@@ -110,6 +110,81 @@ TEST(StringRefTest, Split) {
             Str.rsplit('o'));
 }
 
+TEST(StringRefTest, Split2) {
+  std::vector<StringRef> parts;
+  std::vector<StringRef> expected;
+
+  expected.push_back("ab"); expected.push_back("c");
+  StringRef(",ab,,c,").split(parts, ",", -1, false);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back(""); expected.push_back("ab"); expected.push_back("");
+  expected.push_back("c"); expected.push_back("");
+  StringRef(",ab,,c,").split(parts, ",", -1, true);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back("");
+  StringRef("").split(parts, ",", -1, true);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  StringRef("").split(parts, ",", -1, false);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  StringRef(",").split(parts, ",", -1, false);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back(""); expected.push_back("");
+  StringRef(",").split(parts, ",", -1, true);
+  EXPECT_TRUE(parts == expected);
+
+  // Test MaxSplit
+  expected.clear(); parts.clear();
+  expected.push_back("a,,b,c");
+  StringRef("a,,b,c").split(parts, ",", 0, true);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back("a,,b,c");
+  StringRef("a,,b,c").split(parts, ",", 0, false);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back("a"); expected.push_back(",b,c");
+  StringRef("a,,b,c").split(parts, ",", 1, true);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back("a"); expected.push_back(",b,c");
+  StringRef("a,,b,c").split(parts, ",", 1, false);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back("a"); expected.push_back(""); expected.push_back("b,c");
+  StringRef("a,,b,c").split(parts, ",", 2, true);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back("a"); expected.push_back("b,c");
+  StringRef("a,,b,c").split(parts, ",", 2, false);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back("a"); expected.push_back(""); expected.push_back("b");
+  expected.push_back("c");
+  StringRef("a,,b,c").split(parts, ",", 3, true);
+  EXPECT_TRUE(parts == expected);
+
+  expected.clear(); parts.clear();
+  expected.push_back("a"); expected.push_back("b"); expected.push_back("c");
+  StringRef("a,,b,c").split(parts, ",", 3, false);
+  EXPECT_TRUE(parts == expected);
+}
+
 TEST(StringRefTest, StartsWith) {
   StringRef Str("hello");
   EXPECT_TRUE(Str.startswith("he"));