mgorny created this revision.
mgorny added reviewers: labath, teemperor, krytarowski, JDevlieghere, emaste,
lattner, rriddle.
Herald added subscribers: dexonsmith, hiraditya.
mgorny requested review of this revision.
Herald added a project: LLVM.
Add a llvm::split() implementation that can be used via range-for loop,
e.g.:
for (StringRef x : llvm::split("foo,bar,baz", ','))
...
The implementation uses an additional SplittingIterator class that
uses StringRef::split() internally.
https://reviews.llvm.org/D110496
Files:
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
llvm/include/llvm/ADT/StringExtras.h
llvm/lib/IR/DataLayout.cpp
llvm/unittests/ADT/StringExtrasTest.cpp
Index: llvm/unittests/ADT/StringExtrasTest.cpp
===================================================================
--- llvm/unittests/ADT/StringExtrasTest.cpp
+++ llvm/unittests/ADT/StringExtrasTest.cpp
@@ -274,3 +274,35 @@
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 10), "-1");
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 16), "-1");
}
+
+TEST(StringExtrasTest, splitStringRef) {
+ auto spl = split("foo<=>bar<=><=>baz", "<=>");
+ auto it = spl.begin();
+ auto end = spl.end();
+
+ ASSERT_NE(it, end);
+ EXPECT_EQ(*it, StringRef("foo"));
+ ASSERT_NE(++it, end);
+ EXPECT_EQ(*it, StringRef("bar"));
+ ASSERT_NE(++it, end);
+ EXPECT_EQ(*it, StringRef(""));
+ ASSERT_NE(++it, end);
+ EXPECT_EQ(*it, StringRef("baz"));
+ ASSERT_EQ(++it, end);
+}
+
+TEST(StringExtrasTest, splitChar) {
+ auto spl = split("foo,bar,,baz", ',');
+ auto it = spl.begin();
+ auto end = spl.end();
+
+ ASSERT_NE(it, end);
+ EXPECT_EQ(*it, StringRef("foo"));
+ ASSERT_NE(++it, end);
+ EXPECT_EQ(*it, StringRef("bar"));
+ ASSERT_NE(++it, end);
+ EXPECT_EQ(*it, StringRef(""));
+ ASSERT_NE(++it, end);
+ EXPECT_EQ(*it, StringRef("baz"));
+ ASSERT_EQ(++it, end);
+}
Index: llvm/lib/IR/DataLayout.cpp
===================================================================
--- llvm/lib/IR/DataLayout.cpp
+++ llvm/lib/IR/DataLayout.cpp
@@ -216,8 +216,8 @@
}
/// Checked version of split, to ensure mandatory subparts.
-static Error split(StringRef Str, char Separator,
- std::pair<StringRef, StringRef> &Split) {
+static Error dataLayoutSplit(StringRef Str, char Separator,
+ std::pair<StringRef, StringRef> &Split) {
assert(!Str.empty() && "parse error, string can't be empty here");
Split = Str.split(Separator);
if (Split.second.empty() && Split.first != Str)
@@ -260,12 +260,12 @@
while (!Desc.empty()) {
// Split at '-'.
std::pair<StringRef, StringRef> Split;
- if (Error Err = split(Desc, '-', Split))
+ if (Error Err = dataLayoutSplit(Desc, '-', Split))
return Err;
Desc = Split.second;
// Split at ':'.
- if (Error Err = split(Split.first, ':', Split))
+ if (Error Err = dataLayoutSplit(Split.first, ':', Split))
return Err;
// Aliases used below.
@@ -274,7 +274,7 @@
if (Tok == "ni") {
do {
- if (Error Err = split(Rest, ':', Split))
+ if (Error Err = dataLayoutSplit(Rest, ':', Split))
return Err;
Rest = Split.second;
unsigned AS;
@@ -315,7 +315,7 @@
if (Rest.empty())
return reportError(
"Missing size specification for pointer in datalayout string");
- if (Error Err = split(Rest, ':', Split))
+ if (Error Err = dataLayoutSplit(Rest, ':', Split))
return Err;
unsigned PointerMemSize;
if (Error Err = getIntInBytes(Tok, PointerMemSize))
@@ -327,7 +327,7 @@
if (Rest.empty())
return reportError(
"Missing alignment specification for pointer in datalayout string");
- if (Error Err = split(Rest, ':', Split))
+ if (Error Err = dataLayoutSplit(Rest, ':', Split))
return Err;
unsigned PointerABIAlign;
if (Error Err = getIntInBytes(Tok, PointerABIAlign))
@@ -342,7 +342,7 @@
// Preferred alignment.
unsigned PointerPrefAlign = PointerABIAlign;
if (!Rest.empty()) {
- if (Error Err = split(Rest, ':', Split))
+ if (Error Err = dataLayoutSplit(Rest, ':', Split))
return Err;
if (Error Err = getIntInBytes(Tok, PointerPrefAlign))
return Err;
@@ -352,7 +352,7 @@
// Now read the index. It is the second optional parameter here.
if (!Rest.empty()) {
- if (Error Err = split(Rest, ':', Split))
+ if (Error Err = dataLayoutSplit(Rest, ':', Split))
return Err;
if (Error Err = getIntInBytes(Tok, IndexSize))
return Err;
@@ -393,7 +393,7 @@
if (Rest.empty())
return reportError(
"Missing alignment specification in datalayout string");
- if (Error Err = split(Rest, ':', Split))
+ if (Error Err = dataLayoutSplit(Rest, ':', Split))
return Err;
unsigned ABIAlign;
if (Error Err = getIntInBytes(Tok, ABIAlign))
@@ -410,7 +410,7 @@
// Preferred alignment.
unsigned PrefAlign = ABIAlign;
if (!Rest.empty()) {
- if (Error Err = split(Rest, ':', Split))
+ if (Error Err = dataLayoutSplit(Rest, ':', Split))
return Err;
if (Error Err = getIntInBytes(Tok, PrefAlign))
return Err;
@@ -439,7 +439,7 @@
LegalIntWidths.push_back(Width);
if (Rest.empty())
break;
- if (Error Err = split(Rest, ':', Split))
+ if (Error Err = dataLayoutSplit(Rest, ':', Split))
return Err;
}
break;
Index: llvm/include/llvm/ADT/StringExtras.h
===================================================================
--- llvm/include/llvm/ADT/StringExtras.h
+++ llvm/include/llvm/ADT/StringExtras.h
@@ -501,6 +501,62 @@
}
};
+/// A forward iterator over partitions of string over a separator.
+class SplittingIterator
+ : public iterator_facade_base<SplittingIterator, std::forward_iterator_tag,
+ StringRef> {
+ StringRef Current;
+ StringRef Next;
+ StringRef Separator;
+
+public:
+ SplittingIterator(StringRef Str, StringRef Separator)
+ : Next(Str), Separator(Separator) {
+ ++*this;
+ }
+
+ bool operator==(const SplittingIterator &R) const {
+ return Current == R.Current && Next == R.Next && Separator == R.Separator;
+ }
+
+ const StringRef &operator*() const { return Current; }
+
+ StringRef &operator*() { return Current; }
+
+ SplittingIterator &operator++() {
+ std::pair<StringRef, StringRef> res = Next.split(Separator);
+ Current = res.first;
+ Next = res.second;
+ return *this;
+ }
+};
+
+/// Split the specified string over a separator and return a range-compatible
+/// iterable over its partitions. Used to permit conveniently iterating
+/// over separated strings like so:
+///
+/// \code
+/// for (StringRef x : split("foo,bar,baz", ','))
+/// ...;
+/// \end
+///
+/// Note that the passed string must remain valid throuhgout lifetime
+/// of the iterators.
+class split {
+ StringRef Str;
+ std::string SeparatorStr;
+
+public:
+ split(StringRef NewStr, StringRef Separator)
+ : Str(NewStr), SeparatorStr(Separator) {}
+ split(StringRef NewStr, char Separator)
+ : Str(NewStr), SeparatorStr(1, Separator) {}
+
+ SplittingIterator begin() { return SplittingIterator(Str, SeparatorStr); }
+
+ SplittingIterator end() { return SplittingIterator("", SeparatorStr); }
+};
+
} // end namespace llvm
#endif // LLVM_ADT_STRINGEXTRAS_H
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -5121,9 +5121,7 @@
std::string path;
// process the response
- llvm::SmallVector<llvm::StringRef, 1> reply_data;
- response.GetStringRef().split(reply_data, ';');
- for (auto x : reply_data) {
+ for (auto x : llvm::split(response.GetStringRef(), ';')) {
if (x.consume_front("core-path:"))
StringExtractor(x).GetHexByteString(path);
}
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -3656,10 +3656,7 @@
StringRef packet_str{packet.GetStringRef()};
assert(packet_str.startswith("qSaveCore"));
if (packet_str.consume_front("qSaveCore;")) {
- llvm::SmallVector<llvm::StringRef, 2> fields;
- packet_str.split(fields, ';');
-
- for (auto x : fields) {
+ for (auto x : llvm::split(packet_str, ';')) {
if (x.consume_front("path-hint:"))
StringExtractor(x).GetHexByteString(path_hint);
else
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -356,10 +356,7 @@
// configuration of the transport before attaching/launching the process.
m_qSupported_response = response.GetStringRef().str();
- llvm::SmallVector<llvm::StringRef, 16> server_features;
- response.GetStringRef().split(server_features, ';');
-
- for (llvm::StringRef x : server_features) {
+ for (llvm::StringRef x : llvm::split(response.GetStringRef(), ';')) {
if (x == "qXfer:auxv:read+")
m_supports_qXfer_auxv_read = eLazyBoolYes;
else if (x == "qXfer:libraries-svr4:read+")
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits