Author: Michał Górny Date: 2021-09-27T10:43:09+02:00 New Revision: f4b71e3479bfaec71ba5f4bb56c6a34357a7f938
URL: https://github.com/llvm/llvm-project/commit/f4b71e3479bfaec71ba5f4bb56c6a34357a7f938 DIFF: https://github.com/llvm/llvm-project/commit/f4b71e3479bfaec71ba5f4bb56c6a34357a7f938.diff LOG: [llvm] [ADT] Add a range/iterator-based Split() 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. Differential Revision: https://reviews.llvm.org/D110496 Added: Modified: 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/unittests/ADT/StringExtrasTest.cpp Removed: ################################################################################ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 6d2a267f294c..805a836942d6 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -355,10 +355,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { // 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+") @@ -1659,10 +1656,8 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo( error_extractor.GetHexByteString(error_string); error.SetErrorString(error_string.c_str()); } else if (name.equals("dirty-pages")) { - llvm::SmallVector<llvm::StringRef, 16> split_value; std::vector<addr_t> dirty_page_list; - value.split(split_value, ','); - for (llvm::StringRef x : split_value) { + for (llvm::StringRef x : llvm::Split(value, ',')) { addr_t page; x.consume_front("0x"); if (llvm::to_integer(x, page, 16)) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 1ad838b51c26..cd8537812eff 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -3656,10 +3656,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qSaveCore( 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 diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 2c1b4fa319ff..fdedb9b83416 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -383,9 +383,7 @@ static size_t SplitCommaSeparatedRegisterNumberString( const llvm::StringRef &comma_separated_register_numbers, std::vector<uint32_t> ®nums, int base) { regnums.clear(); - llvm::SmallVector<llvm::StringRef, 4> split_string; - comma_separated_register_numbers.split(split_string, ','); - for (llvm::StringRef x : split_string) { + for (llvm::StringRef x : llvm::Split(comma_separated_register_numbers, ',')) { uint32_t reg; if (llvm::to_integer(x, reg, base)) regnums.push_back(reg); @@ -1457,9 +1455,7 @@ size_t ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue( size_t ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue( llvm::StringRef value) { m_thread_pcs.clear(); - llvm::SmallVector<llvm::StringRef, 16> split_value; - value.split(split_value, ','); - for (llvm::StringRef x : split_value) { + for (llvm::StringRef x : llvm::Split(value, ',')) { lldb::addr_t pc; if (llvm::to_integer(x, pc, 16)) m_thread_pcs.push_back(pc); @@ -5111,9 +5107,7 @@ llvm::Expected<bool> ProcessGDBRemote::SaveCore(llvm::StringRef outfile) { 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); } diff --git a/llvm/include/llvm/ADT/StringExtras.h b/llvm/include/llvm/ADT/StringExtras.h index 6bda25b85313..41dc7e291916 100644 --- a/llvm/include/llvm/ADT/StringExtras.h +++ b/llvm/include/llvm/ADT/StringExtras.h @@ -501,6 +501,62 @@ class ListSeparator { } }; +/// 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 : llvm::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 diff --git a/llvm/unittests/ADT/StringExtrasTest.cpp b/llvm/unittests/ADT/StringExtrasTest.cpp index 3918a35fcef3..35d3535ec268 100644 --- a/llvm/unittests/ADT/StringExtrasTest.cpp +++ b/llvm/unittests/ADT/StringExtrasTest.cpp @@ -274,3 +274,35 @@ TEST(StringExtrasTest, toStringAPSInt) { 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); +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits