summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/ADT/StringRef.h27
-rw-r--r--lib/Support/StringExtras.cpp19
-rw-r--r--unittests/ADT/StringRefTest.cpp75
3 files changed, 121 insertions, 0 deletions
diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h
index b07dcc12ce..6ccb37d346 100644
--- a/include/llvm/ADT/StringRef.h
+++ b/include/llvm/ADT/StringRef.h
@@ -15,6 +15,14 @@
#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.
///
diff --git a/lib/Support/StringExtras.cpp b/lib/Support/StringExtras.cpp
index c72f121653..05ba34b2e7 100644
--- a/lib/Support/StringExtras.cpp
+++ b/lib/Support/StringExtras.cpp
@@ -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);
+}
diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp
index 7828b5fadf..3c0cc58ad2 100644
--- a/unittests/ADT/StringRefTest.cpp
+++ b/unittests/ADT/StringRefTest.cpp
@@ -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"));