Index: llvm/include/llvm/ADT/StringRef.h =================================================================== --- llvm/include/llvm/ADT/StringRef.h +++ llvm/include/llvm/ADT/StringRef.h @@ -760,7 +760,9 @@ /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1 /// elements are added to A. /// If \p KeepEmpty is false, empty strings are not added to \p A. They - /// still count when considering \p MaxSplit + /// still count when considering \p MaxSplit. The substring has all + /// consecutive occurances of \p TrimChars characters removed from the + /// front and back. /// An useful invariant is that /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true /// @@ -768,9 +770,10 @@ /// \param Separator - The string to split on. /// \param MaxSplit - The maximum number of times the string is split. /// \param KeepEmpty - True if empty substring should be added. - void split(SmallVectorImpl &A, - StringRef Separator, int MaxSplit = -1, - bool KeepEmpty = true) const; + /// \param TrimChars - Chars to remove from front and back of substrings. + void split(SmallVectorImpl &A, StringRef Separator, + int MaxSplit = -1, bool KeepEmpty = true, + StringRef TrimChars = "") const; /// Split into substrings around the occurrences of a separator character. /// @@ -778,7 +781,9 @@ /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1 /// elements are added to A. /// If \p KeepEmpty is false, empty strings are not added to \p A. They - /// still count when considering \p MaxSplit + /// still count when considering \p MaxSplit. The substring has all + /// consecutive occurances of \p TrimChars characters removed from the + /// front and back. /// An useful invariant is that /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true /// @@ -786,8 +791,9 @@ /// \param Separator - The string to split on. /// \param MaxSplit - The maximum number of times the string is split. /// \param KeepEmpty - True if empty substring should be added. + /// \param TrimChars - Chars to remove from front and back of substrings. void split(SmallVectorImpl &A, char Separator, int MaxSplit = -1, - bool KeepEmpty = true) const; + bool KeepEmpty = true, StringRef TrimChars = "") const; /// Split into two substrings around the last occurrence of a separator /// character. Index: llvm/lib/Support/StringRef.cpp =================================================================== --- llvm/lib/Support/StringRef.cpp +++ llvm/lib/Support/StringRef.cpp @@ -311,9 +311,8 @@ return npos; } -void StringRef::split(SmallVectorImpl &A, - StringRef Separator, int MaxSplit, - bool KeepEmpty) const { +void StringRef::split(SmallVectorImpl &A, StringRef Separator, + int MaxSplit, bool KeepEmpty, StringRef TrimChars) const { StringRef S = *this; // Count down from MaxSplit. When MaxSplit is -1, this will just split @@ -325,21 +324,24 @@ if (Idx == npos) break; + StringRef Next = S.slice(0, Idx).trim(TrimChars); + // Push this split. - if (KeepEmpty || Idx > 0) - A.push_back(S.slice(0, Idx)); + if (KeepEmpty || !Next.empty()) + A.push_back(Next); // Jump forward. S = S.slice(Idx + Separator.size(), npos); } + S = S.trim(TrimChars); // Push the tail. if (KeepEmpty || !S.empty()) A.push_back(S); } void StringRef::split(SmallVectorImpl &A, char Separator, - int MaxSplit, bool KeepEmpty) const { + int MaxSplit, bool KeepEmpty, StringRef TrimChars) const { StringRef S = *this; // Count down from MaxSplit. When MaxSplit is -1, this will just split @@ -351,14 +353,17 @@ if (Idx == npos) break; + StringRef Next = S.slice(0, Idx).trim(TrimChars); + // Push this split. - if (KeepEmpty || Idx > 0) - A.push_back(S.slice(0, Idx)); + if (KeepEmpty || !Next.empty()) + A.push_back(Next); // Jump forward. S = S.slice(Idx + 1, npos); } + S = S.trim(TrimChars); // Push the tail. if (KeepEmpty || !S.empty()) A.push_back(S); Index: llvm/unittests/ADT/StringRefTest.cpp =================================================================== --- llvm/unittests/ADT/StringRefTest.cpp +++ llvm/unittests/ADT/StringRefTest.cpp @@ -318,6 +318,41 @@ expected.push_back("c,d"); StringRef("a,,b,c,d").split(parts, ',', 3, true); EXPECT_TRUE(parts == expected); + + expected.clear(); parts.clear(); + expected.push_back("a"); + expected.push_back("b"); + expected.push_back("c"); + expected.push_back("d"); + expected.push_back("e"); + StringRef("a, b ,c , d, e ").split(parts, ',', -1, true, " "); + EXPECT_TRUE(parts == expected); + + expected.clear(); parts.clear(); + expected.push_back("a"); + expected.push_back("b"); + expected.push_back("c"); + expected.push_back("d"); + expected.push_back("e"); + StringRef("af, bf ,c ,f d, fe ").split(parts, ',', -1, true, "f "); + EXPECT_TRUE(parts == expected); + + expected.clear(); parts.clear(); + expected.push_back("a"); + expected.push_back("b"); + expected.push_back("c"); + expected.push_back("d, fe"); + StringRef("af, bf ,c ,f d, fe ").split(parts, ',', 3, true, "f "); + EXPECT_TRUE(parts == expected); + + expected.clear(); parts.clear(); + expected.push_back("a"); + expected.push_back("b"); + expected.push_back("d"); + expected.push_back("e"); + StringRef("af, bf ,fff ,f d, fe ").split(parts, ',', -1, false, "f "); + EXPECT_TRUE(parts == expected); + } TEST(StringRefTest, Trim) {