zturner updated this revision to Diff 69741.
zturner added a comment.

Rebased after submitting all local changes.  This should apply cleanly on top 
of LLDB r280139.


https://reviews.llvm.org/D24013

Files:
  include/lldb/Core/Event.h
  include/lldb/Core/RegularExpression.h
  include/lldb/Utility/StringExtractor.h
  source/Core/Event.cpp
  source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
  source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
  source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
  source/Utility/StringExtractor.cpp
  source/Utility/StringExtractorGDBRemote.cpp
  source/Utility/StringExtractorGDBRemote.h
  unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
  unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
  unittests/Utility/StringExtractorTest.cpp

Index: unittests/Utility/StringExtractorTest.cpp
===================================================================
--- unittests/Utility/StringExtractorTest.cpp
+++ unittests/Utility/StringExtractorTest.cpp
@@ -17,7 +17,7 @@
 
     ASSERT_EQ (true, ex.IsGood());
     ASSERT_EQ (0u, ex.GetFilePos());
-    ASSERT_STREQ (kEmptyString, ex.GetStringRef().c_str());
+    ASSERT_EQ(kEmptyString, ex.Peek());
     ASSERT_EQ (true, ex.Empty());
     ASSERT_EQ (0u, ex.GetBytesLeft());
 }
@@ -29,12 +29,53 @@
 
     ASSERT_EQ (true, ex.IsGood());
     ASSERT_EQ (0u, ex.GetFilePos());
-    ASSERT_STREQ (kInitMiscString, ex.GetStringRef().c_str());
+    ASSERT_EQ(kInitMiscString, ex.Peek());
     ASSERT_EQ (false, ex.Empty());
     ASSERT_EQ (sizeof(kInitMiscString)-1, ex.GetBytesLeft());
     ASSERT_EQ(kInitMiscString[0], ex.PeekChar());
 }
 
+TEST_F(StringExtractorTest, PeekAndGetSize)
+{
+    llvm::StringRef Str("StringExtractorTest::Size()");
+    StringExtractor ex(Str);
+
+    EXPECT_EQ(true, ex.IsGood());
+    EXPECT_EQ(0u, ex.GetFilePos());
+    EXPECT_EQ(Str.size(), ex.GetTotalBytes());
+    EXPECT_EQ(Str.size(), ex.GetBytesLeft());
+
+    EXPECT_EQ('S', ex.PeekChar());
+    EXPECT_EQ(Str.size(), ex.GetTotalBytes());
+    EXPECT_EQ(Str.size(), ex.GetBytesLeft());
+    EXPECT_EQ(Str, ex.Peek());
+
+    EXPECT_EQ('S', ex.GetChar());
+    EXPECT_EQ(Str.size(), ex.GetTotalBytes());
+    EXPECT_EQ(Str.size() - 1, ex.GetBytesLeft());
+    EXPECT_EQ(Str.drop_front(1), ex.Peek());
+}
+
+TEST_F(StringExtractorTest, Consume)
+{
+    llvm::StringRef Str("StringExtractorTest::Consume()");
+    llvm::StringRef ConsumeStr("String");
+    StringExtractor ex(Str);
+
+    ASSERT_TRUE(ex.IsGood());
+    ASSERT_EQ(0u, ex.GetFilePos());
+
+    EXPECT_EQ(Str.size(), ex.GetBytesLeft());
+    EXPECT_FALSE(ex.Consume("Blah"));
+    EXPECT_EQ(Str.size(), ex.GetBytesLeft());
+    EXPECT_EQ(Str, ex.Peek());
+
+    EXPECT_TRUE(ex.Consume(ConsumeStr));
+    EXPECT_EQ(Str.size() - ConsumeStr.size(), ex.GetBytesLeft());
+    EXPECT_EQ("ExtractorTest::Consume()", ex.Peek());
+    ;
+}
+
 TEST_F (StringExtractorTest, DecodeHexU8_Underflow)
 {
     const char kEmptyString[] = "";
Index: unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
===================================================================
--- unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -41,19 +41,19 @@
 {
     StringExtractorGDBRemote request;
     ASSERT_EQ(PacketResult::Success, server.GetPacket(request));
-    ASSERT_EQ("QThreadSuffixSupported", request.GetStringRef());
+    ASSERT_EQ("QThreadSuffixSupported", request.Peek());
     if (supported)
         ASSERT_EQ(PacketResult::Success, server.SendOKResponse());
     else
-        ASSERT_EQ(PacketResult::Success, server.SendUnimplementedResponse(nullptr));
+        ASSERT_EQ(PacketResult::Success, server.SendUnimplementedResponse(""));
 }
 
 void
 HandlePacket(MockServer &server, llvm::StringRef expected, llvm::StringRef response)
 {
     StringExtractorGDBRemote request;
     ASSERT_EQ(PacketResult::Success, server.GetPacket(request));
-    ASSERT_EQ(expected, request.GetStringRef());
+    ASSERT_EQ(expected, request.Peek());
     ASSERT_EQ(PacketResult::Success, server.SendPacket(response));
 }
 
Index: unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
===================================================================
--- unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
+++ unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
@@ -114,23 +114,23 @@
     // Continue. The inferior will stop with a signal.
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01"));
     ASSERT_EQ(eStateStopped, fix.SendCPacket(response));
-    ASSERT_EQ("T01", response.GetStringRef());
+    ASSERT_EQ("T01", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
 
     // Continue. The inferior will exit.
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("W01"));
     ASSERT_EQ(eStateExited, fix.SendCPacket(response));
-    ASSERT_EQ("W01", response.GetStringRef());
+    ASSERT_EQ("W01", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
 
     // Continue. The inferior will get killed.
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("X01"));
     ASSERT_EQ(eStateExited, fix.SendCPacket(response));
-    ASSERT_EQ("X01", response.GetStringRef());
+    ASSERT_EQ("X01", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
 }
 
 TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal)
@@ -147,25 +147,25 @@
     std::future<StateType> continue_state =
         std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); });
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.Peek());
     fix.WaitForRunEvent();
 
     std::future<bool> async_result = std::async(std::launch::async, [&] { return fix.client.SendAsyncSignal(0x47); });
 
     // First we'll get interrupted.
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("\x03", response.GetStringRef());
+    ASSERT_EQ("\x03", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13"));
 
     // Then we get the signal packet.
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("C47", response.GetStringRef());
+    ASSERT_EQ("C47", response.PeekFullPacket());
     ASSERT_TRUE(async_result.get());
 
     // And we report back a signal stop.
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T47"));
     ASSERT_EQ(eStateStopped, continue_state.get());
-    ASSERT_EQ("T47", continue_response.GetStringRef());
+    ASSERT_EQ("T47", continue_response.Peek());
 }
 
 TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket)
@@ -180,7 +180,7 @@
     std::future<StateType> continue_state =
         std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); });
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
     fix.WaitForRunEvent();
 
     // Sending without async enabled should fail.
@@ -192,24 +192,24 @@
 
     // First we'll get interrupted.
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("\x03", response.GetStringRef());
+    ASSERT_EQ("\x03", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13"));
 
     // Then we get the async packet.
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("qTest2", response.GetStringRef());
+    ASSERT_EQ("qTest2", response.PeekFullPacket());
 
     // Send the response and receive it.
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("QTest2"));
     ASSERT_EQ(PacketResult::Success, async_result.get());
-    ASSERT_EQ("QTest2", async_response.GetStringRef());
+    ASSERT_EQ("QTest2", async_response.PeekFullPacket());
 
     // And we get resumed again.
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01"));
     ASSERT_EQ(eStateStopped, continue_state.get());
-    ASSERT_EQ("T01", continue_response.GetStringRef());
+    ASSERT_EQ("T01", continue_response.PeekFullPacket());
 }
 
 TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt)
@@ -226,19 +226,19 @@
     std::future<StateType> continue_state =
         std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); });
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
     fix.WaitForRunEvent();
 
     std::future<bool> async_result = std::async(std::launch::async, [&] { return fix.client.Interrupt(); });
 
     // We get interrupted.
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("\x03", response.GetStringRef());
+    ASSERT_EQ("\x03", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13"));
 
     // And that's it.
     ASSERT_EQ(eStateStopped, continue_state.get());
-    ASSERT_EQ("T13", continue_response.GetStringRef());
+    ASSERT_EQ("T13", continue_response.PeekFullPacket());
     ASSERT_TRUE(async_result.get());
 }
 
@@ -253,25 +253,25 @@
     std::future<StateType> continue_state =
         std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); });
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
     fix.WaitForRunEvent();
 
     std::future<bool> async_result = std::async(std::launch::async, [&] { return fix.client.Interrupt(); });
 
     // However, the target stops due to a different reason than the original interrupt.
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("\x03", response.GetStringRef());
+    ASSERT_EQ("\x03", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01"));
     ASSERT_EQ(eStateStopped, continue_state.get());
-    ASSERT_EQ("T01", continue_response.GetStringRef());
+    ASSERT_EQ("T01", continue_response.PeekFullPacket());
     ASSERT_TRUE(async_result.get());
 
     // The subsequent continue packet should work normally.
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01"));
     ASSERT_EQ(eStateStopped, fix.SendCPacket(response));
-    ASSERT_EQ("T01", response.GetStringRef());
+    ASSERT_EQ("T01", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
 }
 
 TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug)
@@ -289,31 +289,31 @@
     std::future<StateType> continue_state =
         std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); });
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
     fix.WaitForRunEvent();
 
     std::future<bool> interrupt_result = std::async(std::launch::async, [&] { return fix.client.Interrupt(); });
 
     // We get interrupted. We'll send two packets to simulate a buggy stub.
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("\x03", response.GetStringRef());
+    ASSERT_EQ("\x03", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13"));
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13"));
 
     // We should stop.
     ASSERT_EQ(eStateStopped, continue_state.get());
-    ASSERT_EQ("T13", continue_response.GetStringRef());
+    ASSERT_EQ("T13", continue_response.PeekFullPacket());
     ASSERT_TRUE(interrupt_result.get());
 
     // Packet stream should remain synchronized.
     std::future<PacketResult> send_result = std::async(std::launch::async, [&] {
         return fix.client.SendPacketAndWaitForResponse("qTest", async_response, !send_async);
     });
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("qTest", response.GetStringRef());
+    ASSERT_EQ("qTest", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("QTest"));
     ASSERT_EQ(PacketResult::Success, send_result.get());
-    ASSERT_EQ("QTest", async_response.GetStringRef());
+    ASSERT_EQ("QTest", async_response.PeekFullPacket());
 }
 
 TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateInterface)
@@ -330,9 +330,9 @@
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("Afile"));
     ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01"));
     ASSERT_EQ(eStateStopped, fix.SendCPacket(response));
-    ASSERT_EQ("T01", response.GetStringRef());
+    ASSERT_EQ("T01", response.PeekFullPacket());
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
 
     EXPECT_EQ("ABCD", fix.delegate.output);
     EXPECT_EQ("profile", fix.delegate.misc_data);
@@ -350,14 +350,14 @@
     std::future<StateType> continue_state =
         std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); });
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("c", response.GetStringRef());
+    ASSERT_EQ("c", response.PeekFullPacket());
     fix.WaitForRunEvent();
 
     std::future<bool> async_result = std::async(std::launch::async, [&] { return fix.client.Interrupt(); });
 
     // We get interrupted, but we don't send a stop packet.
     ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response));
-    ASSERT_EQ("\x03", response.GetStringRef());
+    ASSERT_EQ("\x03", response.PeekFullPacket());
 
     // The functions should still terminate (after a timeout).
     ASSERT_TRUE(async_result.get());
Index: source/Utility/StringExtractorGDBRemote.h
===================================================================
--- source/Utility/StringExtractorGDBRemote.h
+++ source/Utility/StringExtractorGDBRemote.h
@@ -24,21 +24,24 @@
 
     StringExtractorGDBRemote() :
         StringExtractor(),
-        m_validator(nullptr)
+        m_validator(nullptr),
+        m_validator_baton(nullptr)
     {
     }
 
-    StringExtractorGDBRemote(llvm::StringRef str) : StringExtractor(str), m_validator(nullptr) {}
+    StringExtractorGDBRemote(llvm::StringRef str) : StringExtractor(str), m_validator(nullptr), m_validator_baton(nullptr) {}
 
     StringExtractorGDBRemote(const char *cstr) :
         StringExtractor(cstr),
-        m_validator(nullptr)
+        m_validator(nullptr),
+        m_validator_baton(nullptr)
     {
     }
 
     StringExtractorGDBRemote(const StringExtractorGDBRemote& rhs) :
         StringExtractor(rhs),
-        m_validator(rhs.m_validator)
+        m_validator(rhs.m_validator),
+        m_validator_baton(rhs.m_validator_baton)
     {
     }
 
Index: source/Utility/StringExtractorGDBRemote.cpp
===================================================================
--- source/Utility/StringExtractorGDBRemote.cpp
+++ source/Utility/StringExtractorGDBRemote.cpp
@@ -427,7 +427,7 @@
             // starts with a '['. This is a quick validator to just make sure the
             // response could be valid JSON without having to validate all of the
             // JSON content.
-            switch (response.GetStringRef()[0])
+            switch (response.PeekChar())
             {
                 case '{': return true;
                 case '[': return true;
@@ -456,7 +456,7 @@
         case StringExtractorGDBRemote::eResponse:
             {
                 uint32_t valid_count = 0;
-                for (const char ch : response.GetStringRef())
+                for (const char ch : response.PeekFullPacket())
                 {
                     if (!isxdigit(ch))
                     {
Index: source/Utility/StringExtractor.cpp
===================================================================
--- source/Utility/StringExtractor.cpp
+++ source/Utility/StringExtractor.cpp
@@ -110,6 +110,15 @@
     return (uint8_t)((hi_nibble << 4) + lo_nibble);
 }
 
+bool
+StringExtractor::Consume(llvm::StringRef str)
+{
+    if (!Peek().startswith(str))
+        return false;
+    m_index += str.size();
+    return true;
+}
+
 //----------------------------------------------------------------------
 // If a pair of valid hex digits exist at the head of the
 // StringExtractor they are decoded into an unsigned byte and returned
Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -407,10 +407,10 @@
     CalculateThreadStopInfo (ThreadGDBRemote *thread);
 
     size_t
-    UpdateThreadPCsFromStopReplyThreadsValue (std::string &value);
+    UpdateThreadPCsFromStopReplyThreadsValue(llvm::StringRef value);
 
     size_t
-    UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);
+    UpdateThreadIDsFromStopReplyThreadsValue(llvm::StringRef value);
 
     bool
     HandleNotifyPacket(StringExtractorGDBRemote &packet);
Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1672,44 +1672,32 @@
 }
 
 size_t
-ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)
+ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(llvm::StringRef value)
 {
     m_thread_ids.clear();
-    m_thread_pcs.clear();
-    size_t comma_pos;
-    lldb::tid_t tid;
-    while ((comma_pos = value.find(',')) != std::string::npos)
-    {
-        value[comma_pos] = '\0';
-        // thread in big endian hex
-        tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
-        if (tid != LLDB_INVALID_THREAD_ID)
-            m_thread_ids.push_back (tid);
-        value.erase(0, comma_pos + 1);
-    }
-    tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
-    if (tid != LLDB_INVALID_THREAD_ID)
-        m_thread_ids.push_back (tid);
+    lldb::addr_t tid;
+    llvm::StringRef tid_str;
+    while (!value.empty())
+    {
+        std::tie(tid_str, value) = value.split(',');
+        if (!tid_str.getAsInteger(16, tid))
+            m_thread_ids.push_back(tid);
+    }
     return m_thread_ids.size();
 }
 
 size_t
-ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value)
+ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue(llvm::StringRef value)
 {
     m_thread_pcs.clear();
-    size_t comma_pos;
     lldb::addr_t pc;
-    while ((comma_pos = value.find(',')) != std::string::npos)
+    llvm::StringRef pc_str;
+    while (!value.empty())
     {
-        value[comma_pos] = '\0';
-        pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
-        if (pc != LLDB_INVALID_ADDRESS)
+        std::tie(pc_str, value) = value.split(',');
+        if (!pc_str.getAsInteger(16, pc))
             m_thread_pcs.push_back (pc);
-        value.erase(0, comma_pos + 1);
     }
-    pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
-    if (pc != LLDB_INVALID_THREAD_ID)
-        m_thread_pcs.push_back (pc);
     return m_thread_pcs.size();
 }
 
@@ -1759,32 +1747,19 @@
             {
                 // Get the thread stop info
                 StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
-                const std::string &stop_info_str = stop_info.GetStringRef();
 
                 m_thread_pcs.clear();
-                const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:");
-                if (thread_pcs_pos != std::string::npos)
+                llvm::StringRef threads_value = stop_info.Peek().split(";thread-pcs:").second
+                                                                .split(";").first;
+                if (!threads_value.empty())
+                    UpdateThreadPCsFromStopReplyThreadsValue(threads_value);
+
+                threads_value = stop_info.Peek().split(";threads:").second
+                                                .split(";").first;
+                if (!threads_value.empty())
                 {
-                    const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
-                    const size_t end = stop_info_str.find(';', start);
-                    if (end != std::string::npos)
-                    {
-                        std::string value = stop_info_str.substr(start, end - start);
-                        UpdateThreadPCsFromStopReplyThreadsValue(value);
-                    }
-                }
-
-                const size_t threads_pos = stop_info_str.find(";threads:");
-                if (threads_pos != std::string::npos)
-                {
-                    const size_t start = threads_pos + strlen(";threads:");
-                    const size_t end = stop_info_str.find(';', start);
-                    if (end != std::string::npos)
-                    {
-                        std::string value = stop_info_str.substr(start, end - start);
-                        if (UpdateThreadIDsFromStopReplyThreadsValue(value))
-                            return true;
-                    }
+                    if (UpdateThreadIDsFromStopReplyThreadsValue(threads_value))
+                        return true;
                 }
             }
         }
@@ -1982,9 +1957,8 @@
 
             for (const auto &pair : expedited_register_map)
             {
-                StringExtractor reg_value_extractor;
-                reg_value_extractor.GetStringRef() = pair.second;
-                DataBufferSP buffer_sp(new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0));
+                StringExtractor reg_value_extractor(pair.second);
+                DataBufferSP buffer_sp(new DataBufferHeap(reg_value_extractor.GetBytesLeft() / 2, 0));
                 reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc');
                 gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData());
             }
@@ -2357,12 +2331,12 @@
                         {
                             if (mem_cache_addr != LLDB_INVALID_ADDRESS)
                             {
-                                StringExtractor bytes;
-                                if (mem_cache_dict->GetValueForKeyAsString("bytes", bytes.GetStringRef()))
+                                std::string bytes_str;
+                                if (mem_cache_dict->GetValueForKeyAsString("bytes", bytes_str))
                                 {
-                                    bytes.SetFilePos(0);
+                                    StringExtractor bytes(bytes_str);
 
-                                    const size_t byte_size = bytes.GetStringRef().size()/2;
+                                    const size_t byte_size = bytes_str.size() / 2;
                                     DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
                                     const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetData(), 0);
                                     if (bytes_copied == byte_size)
@@ -2912,9 +2886,10 @@
                 else
                 {
                     if (log)
-                        log->Printf ("ProcessGDBRemote::DoDestroy - got unexpected response to k packet: %s", response.GetStringRef().c_str());
+                        log->Printf("ProcessGDBRemote::DoDestroy - got unexpected response to k packet: %s",
+                                    response.PeekFullPacket().str().c_str());
                     exit_string.assign("got unexpected response to k packet: ");
-                    exit_string.append(response.GetStringRef());
+                    exit_string.append(response.PeekFullPacket().str());
                 }
             }
             else
@@ -2948,7 +2923,7 @@
 void
 ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
 {
-    const bool did_exec = response.GetStringRef().find(";reason:exec;") != std::string::npos;
+    const bool did_exec = response.Peek().find(";reason:exec;") != llvm::StringRef::npos;
     if (did_exec)
     {
         Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
@@ -3079,7 +3054,7 @@
                     // much data for some reason.
                     data_received_size = size;
                 }
-                memcpy (buf, response.GetStringRef().data(), data_received_size);
+                memcpy(buf, response.Peek().data(), data_received_size);
                 return data_received_size;
             }
             else
@@ -3092,7 +3067,8 @@
         else if (response.IsUnsupportedResponse())
             error.SetErrorStringWithFormat("GDB server does not support reading memory");
         else
-            error.SetErrorStringWithFormat("unexpected response to GDB server memory read packet '%s': '%s'", packet, response.GetStringRef().c_str());
+            error.SetErrorStringWithFormat("unexpected response to GDB server memory read packet '%s': '%s'", packet,
+                                           response.PeekFullPacket().str().c_str());
     }
     else
     {
@@ -3129,7 +3105,8 @@
         else if (response.IsUnsupportedResponse())
             error.SetErrorStringWithFormat("GDB server does not support writing memory");
         else
-            error.SetErrorStringWithFormat("unexpected response to GDB server memory write packet '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str());
+            error.SetErrorStringWithFormat("unexpected response to GDB server memory write packet '%s': '%s'",
+                                           packet.GetString().c_str(), response.PeekFullPacket().str().c_str());
     }
     else
     {
@@ -3831,10 +3808,8 @@
 bool
 ProcessGDBRemote::HandleNotifyPacket (StringExtractorGDBRemote &packet)
 {
-    // get the packet at a string
-    const std::string &pkt = packet.GetStringRef();
     // skip %stop:
-    StringExtractorGDBRemote stop_info(pkt.c_str() + 5);
+    StringExtractorGDBRemote stop_info(packet.Peek().drop_front(5));
 
     // pass as a thread stop info packet
     SetLastStopPacket(stop_info);
@@ -4194,7 +4169,7 @@
             {
                 if (!response.Empty())
                 {
-                    object_sp = StructuredData::ParseJSON (response.GetStringRef());
+                    object_sp = StructuredData::ParseJSON(response.Peek().str());
                 }
             }
         }
@@ -4270,7 +4245,7 @@
             {
                 if (!response.Empty())
                 {
-                    object_sp = StructuredData::ParseJSON (response.GetStringRef());
+                    object_sp = StructuredData::ParseJSON(response.Peek().str());
                 }
             }
         }
@@ -4309,7 +4284,7 @@
             {
                 if (!response.Empty())
                 {
-                    object_sp = StructuredData::ParseJSON (response.GetStringRef());
+                    object_sp = StructuredData::ParseJSON(response.Peek().str());
                 }
             }
         }
@@ -4577,14 +4552,13 @@
             }
             else if (name == "dynamic_size_dwarf_expr_bytes")
             {
-                StringExtractor opcode_extractor;
                 std::string opcode_string = value.str ();
                 size_t dwarf_opcode_len = opcode_string.length () / 2;
                 assert (dwarf_opcode_len > 0);
 
                 dwarf_opcode_bytes.resize (dwarf_opcode_len);
                 reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
-                opcode_extractor.GetStringRef ().swap (opcode_string);
+                StringExtractor opcode_extractor(opcode_string);
                 uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes);
                 assert (dwarf_opcode_len == ret_val);
 
@@ -5426,17 +5400,16 @@
                 result.SetStatus (eReturnStatusSuccessFinishResult);
                 Stream &output_strm = result.GetOutputStream();
                 output_strm.Printf ("  packet: %s\n", packet_cstr);
-                std::string &response_str = response.GetStringRef();
 
                 if (strstr(packet_cstr, "qGetProfileData") != NULL)
                 {
-                    response_str = process->HarmonizeThreadIdsForProfileData(response);
+                    response.SetString(process->HarmonizeThreadIdsForProfileData(response));
                 }
 
-                if (response_str.empty())
+                if (response.GetBytesLeft() == 0)
                     output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
                 else
-                    output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
+                    output_strm.Printf("response: %s\n", response.Peek().str().c_str());
             }
         }
         return true;
@@ -5477,20 +5450,18 @@
             StreamString packet;
             packet.PutCString("qRcmd,");
             packet.PutBytesAsRawHex8(command, strlen(command));
-            const char *packet_cstr = packet.GetString().c_str();
 
             bool send_async = true;
             StringExtractorGDBRemote response;
-            process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
+            process->GetGDBRemote().SendPacketAndWaitForResponse(packet.GetString(), response, send_async);
             result.SetStatus (eReturnStatusSuccessFinishResult);
             Stream &output_strm = result.GetOutputStream();
-            output_strm.Printf ("  packet: %s\n", packet_cstr);
-            const std::string &response_str = response.GetStringRef();
+            output_strm.Printf("  packet: %s\n", packet.GetString().c_str());
 
-            if (response_str.empty())
+            if (response.GetBytesLeft() == 0)
                 output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
             else
-                output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
+                output_strm.Printf("response: %s\n", response.Peek().str().c_str());
         }
         return true;
     }
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -1187,7 +1187,7 @@
     {
         // FIXME add continue at address support for $C{signo}[;{continue-address}].
         if (packet.PeekChar() == ';')
-            return SendUnimplementedResponse (packet.GetStringRef().c_str());
+            return SendUnimplementedResponse(packet.PeekFullPacket());
         else
             return SendIllFormedResponse (packet, "unexpected content after $C{signal-number}");
     }
@@ -1258,7 +1258,7 @@
     {
         if (log)
             log->Printf ("GDBRemoteCommunicationServerLLGS::%s not implemented for c{address} variant [%s remains]", __FUNCTION__, packet.Peek ());
-        return SendUnimplementedResponse (packet.GetStringRef().c_str());
+        return SendUnimplementedResponse(packet.PeekFullPacket());
     }
 
     // Ensure we have a native process.
@@ -1694,7 +1694,9 @@
     if (reg_index == std::numeric_limits<uint32_t>::max ())
     {
         if (log)
-            log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, could not parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
+            log->Printf(
+                "GDBRemoteCommunicationServerLLGS::%s failed, could not parse register number from request \"%s\"",
+                __FUNCTION__, packet.Peek().str().c_str());
         return SendErrorResponse (0x15);
     }
 
@@ -1775,7 +1777,9 @@
     if (reg_index == std::numeric_limits<uint32_t>::max ())
     {
         if (log)
-            log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, could not parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
+            log->Printf(
+                "GDBRemoteCommunicationServerLLGS::%s failed, could not parse register number from request \"%s\"",
+                __FUNCTION__, packet.Peek().str().c_str());
         return SendErrorResponse (0x29);
     }
 
@@ -2772,7 +2776,8 @@
     if (tid == LLDB_INVALID_THREAD_ID)
     {
         if (log)
-            log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, could not parse thread id from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
+            log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not parse thread id from request \"%s\"",
+                        __FUNCTION__, packet.Peek().str().c_str());
         return SendErrorResponse (0x15);
     }
     return SendStopReplyPacketForThread (tid);
@@ -2918,7 +2923,9 @@
     if (packet.GetBytesLeft () < 1 || packet.GetChar () != ';')
     {
         if (log)
-            log->Printf ("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse error: expected ';' prior to start of thread suffix: packet contents = '%s'", __FUNCTION__, packet.GetStringRef ().c_str ());
+            log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse error: expected ';' prior to start of "
+                        "thread suffix: packet contents = '%s'",
+                        __FUNCTION__, packet.Peek().str().c_str());
         return thread_sp;
     }
 
@@ -2929,7 +2936,9 @@
     if (packet.Peek().startswith("thread:"))
     {
         if (log)
-            log->Printf ("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse error: expected 'thread:' but not found, packet contents = '%s'", __FUNCTION__, packet.GetStringRef ().c_str ());
+            log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse error: expected 'thread:' but not "
+                        "found, packet contents = '%s'",
+                        __FUNCTION__, packet.Peek().str().c_str());
         return thread_sp;
     }
     packet.SetFilePos (packet.GetFilePos () + strlen("thread:"));
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -1081,7 +1081,7 @@
 GDBRemoteCommunicationServerCommon::Handle_qEcho (StringExtractorGDBRemote &packet)
 {
     // Just echo back the exact same packet for qEcho...
-    return SendPacketNoLock(packet.GetStringRef());
+    return SendPacketNoLock(packet.PeekFullPacket());
 }
 
 GDBRemoteCommunication::PacketResult
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -60,7 +60,7 @@
     bool m_exit_now; // use in asynchronous handling to indicate process should exit.
 
     PacketResult
-    SendUnimplementedResponse (const char *packet);
+    SendUnimplementedResponse(llvm::StringRef packet);
 
     PacketResult
     SendErrorResponse (uint8_t error);
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -67,13 +67,13 @@
             break;
 
         case StringExtractorGDBRemote::eServerPacketType_unimplemented:
-            packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
+            packet_result = SendUnimplementedResponse(packet.PeekFullPacket());
             break;
 
         default:
             auto handler_it = m_packet_handlers.find(packet_type);
             if (handler_it == m_packet_handlers.end())
-                packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
+                packet_result = SendUnimplementedResponse(packet.PeekFullPacket());
             else
                 packet_result = handler_it->second (packet, error, interrupt, quit);
             break;
@@ -99,8 +99,7 @@
     return packet_result;
 }
 
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
+GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendUnimplementedResponse(llvm::StringRef)
 {
     // TODO: Log the packet we aren't handling...
     return SendPacketNoLock ("");
@@ -121,7 +120,8 @@
 {
     Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
     if (log)
-        log->Printf ("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", __FUNCTION__, failed_packet.GetStringRef ().c_str (), message ? message : "");
+        log->Printf("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", __FUNCTION__,
+                    failed_packet.PeekFullPacket().str().c_str(), message ? message : "");
     return SendErrorResponse (0x03);
 }
 
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -675,7 +675,7 @@
     // Given the list of compression types that the remote debug stub can support,
     // possibly enable compression if we find an encoding we can handle.
     void
-    MaybeEnableCompression (std::vector<std::string> supported_compressions);
+    MaybeEnableCompression(std::vector<llvm::StringRef> supported_compressions);
 
     bool
     DecodeProcessInfoResponse (StringExtractorGDBRemote &response, 
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -42,6 +42,7 @@
 #include "lldb/Host/Config.h"
 
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/raw_ostream.h"
 
 #if defined (HAVE_LIBCOMPRESSION)
 #include <compression.h>
@@ -419,93 +420,57 @@
     }
 
     StringExtractorGDBRemote response;
-    if (SendPacketAndWaitForResponse(packet.GetData(),
-                                     response,
+    if (SendPacketAndWaitForResponse(packet.GetData(), response,
                                      /*send_async=*/false) == PacketResult::Success)
     {
-        const char *response_cstr = response.GetStringRef().c_str();
+        llvm::StringRef response_str = response.Peek();
 
         // Hang on to the qSupported packet, so that platforms can do custom
         // configuration of the transport before attaching/launching the
         // process.
-        m_qSupported_response = response_cstr;
+        m_qSupported_response = response_str;
 
-        if (::strstr (response_cstr, "qXfer:auxv:read+"))
+        if (response_str.contains("qXfer:auxv:read+"))
             m_supports_qXfer_auxv_read = eLazyBoolYes;
-        if (::strstr (response_cstr, "qXfer:libraries-svr4:read+"))
+        if (response_str.contains("qXfer:libraries-svr4:read+"))
             m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
-        if (::strstr (response_cstr, "augmented-libraries-svr4-read"))
+        if (response_str.contains("augmented-libraries-svr4-read"))
         {
             m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;  // implied
             m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
         }
-        if (::strstr (response_cstr, "qXfer:libraries:read+"))
+        if (response_str.contains("qXfer:libraries:read+"))
             m_supports_qXfer_libraries_read = eLazyBoolYes;
-        if (::strstr (response_cstr, "qXfer:features:read+"))
+        if (response_str.contains("qXfer:features:read+"))
             m_supports_qXfer_features_read = eLazyBoolYes;
 
 
         // Look for a list of compressions in the features list e.g.
         // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-deflate,lzma
-        const char *features_list = ::strstr (response_cstr, "qXfer:features:");
-        if (features_list)
+        llvm::StringRef compressions =
+            response_str.split("qXfer:features:").second
+                        .split("SupportedCompressions=").second
+                        .split(";").first;
+        std::vector<llvm::StringRef> supported_compressions;
+        while (!compressions.empty())
         {
-            const char *compressions = ::strstr (features_list, "SupportedCompressions=");
-            if (compressions)
-            {
-                std::vector<std::string> supported_compressions;
-                compressions += sizeof ("SupportedCompressions=") - 1;
-                const char *end_of_compressions = strchr (compressions, ';');
-                if (end_of_compressions == NULL)
-                {
-                    end_of_compressions = strchr (compressions, '\0');
-                }
-                const char *current_compression = compressions;
-                while (current_compression < end_of_compressions)
-                {
-                    const char *next_compression_name = strchr (current_compression, ',');
-                    const char *end_of_this_word = next_compression_name;
-                    if (next_compression_name == NULL || end_of_compressions < next_compression_name)
-                    {
-                        end_of_this_word = end_of_compressions;
-                    }
-
-                    if (end_of_this_word)
-                    {
-                        if (end_of_this_word == current_compression)
-                        {
-                            current_compression++;
-                        }
-                        else
-                        {
-                            std::string this_compression (current_compression, end_of_this_word - current_compression);
-                            supported_compressions.push_back (this_compression);
-                            current_compression = end_of_this_word + 1;
-                        }
-                    }
-                    else
-                    {
-                        supported_compressions.push_back (current_compression);
-                        current_compression = end_of_compressions;
-                    }
-                }
-
-                if (supported_compressions.size() > 0)
-                {
-                    MaybeEnableCompression (supported_compressions);
-                }
-            }
+            llvm::StringRef this_compression;
+            std::tie(this_compression, compressions) = compressions.split(',');
+            supported_compressions.push_back(this_compression);
         }
 
-        if (::strstr (response_cstr, "qEcho"))
+        if (!supported_compressions.empty())
+            MaybeEnableCompression(supported_compressions);
+
+        if (response_str.contains("qEcho"))
             m_supports_qEcho = eLazyBoolYes;
         else
             m_supports_qEcho = eLazyBoolNo;
 
-        const char *packet_size_str = ::strstr (response_cstr, "PacketSize=");
-        if (packet_size_str)
+        llvm::StringRef packet_size_str = response_str.split("PacketSize=").second;
+        if (!packet_size_str.empty())
         {
-            StringExtractorGDBRemote packet_response(packet_size_str + strlen("PacketSize="));
+            StringExtractorGDBRemote packet_response(packet_size_str);
             m_max_packet_size = packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
             if (m_max_packet_size == 0)
             {
@@ -547,17 +512,17 @@
         m_supports_vCont_S = eLazyBoolNo;
         if (SendPacketAndWaitForResponse("vCont?", response, false) == PacketResult::Success)
         {
-            const char *response_cstr = response.GetStringRef().c_str();
-            if (::strstr (response_cstr, ";c"))
+            llvm::StringRef response_str = response.Peek();
+            if (response_str.contains(";c"))
                 m_supports_vCont_c = eLazyBoolYes;
 
-            if (::strstr (response_cstr, ";C"))
+            if (response_str.contains(";C"))
                 m_supports_vCont_C = eLazyBoolYes;
 
-            if (::strstr (response_cstr, ";s"))
+            if (response_str.contains(";s"))
                 m_supports_vCont_s = eLazyBoolYes;
 
-            if (::strstr (response_cstr, ";S"))
+            if (response_str.contains(";S"))
                 m_supports_vCont_S = eLazyBoolYes;
 
             if (m_supports_vCont_c == eLazyBoolYes &&
@@ -658,7 +623,7 @@
             }
             else if (!response.Empty())
             {
-                object_sp = StructuredData::ParseJSON (response.GetStringRef());
+                object_sp = StructuredData::ParseJSON(response.Peek());
             }
         }
     }
@@ -772,16 +737,13 @@
         if (result != PacketResult::Success)
             return result;
 
-        const std::string &this_string = this_response.GetStringRef();
-
         // Check for m or l as first character; l seems to mean this is the last chunk
-        char first_char = *this_string.c_str();
+        char first_char = this_response.GetChar();
         if (first_char != 'm' && first_char != 'l')
-        {
             return PacketResult::ErrorReplyInvalid;
-        }
+
         // Concatenate the result so far (skipping 'm' or 'l')
-        response_string.append(this_string, 1, std::string::npos);
+        response_string.append(this_response.Peek());
         if (first_char == 'l')
             // We're done
             return PacketResult::Success;
@@ -855,7 +817,7 @@
         if (response.GetChar() == 'E')
         {
             // A string the describes what failed when launching...
-            error_str = response.GetStringRef().substr(1);
+            error_str = response.Peek();
         }
         else
         {
@@ -1166,7 +1128,7 @@
 }
 
 void
-GDBRemoteCommunicationClient::MaybeEnableCompression (std::vector<std::string> supported_compressions)
+GDBRemoteCommunicationClient::MaybeEnableCompression(std::vector<llvm::StringRef> supported_compressions)
 {
     CompressionType avail_type = CompressionType::None;
     std::string avail_name;
@@ -2377,8 +2339,7 @@
                 if (!DecodeProcessInfoResponse (response, process_info))
                     break;
                 process_infos.Append(process_info);
-                response.GetStringRef().clear();
-                response.SetFilePos(0);
+                response.Reset();
             } while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false) == PacketResult::Success);
         }
         else
@@ -2407,7 +2368,7 @@
                 // Make sure we parsed the right number of characters. The response is
                 // the hex encoded user name and should make up the entire packet.
                 // If there are any non-hex ASCII bytes, the length won't match below..
-                if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
+                if (response.GetHexByteString(name) && !response.GetBytesLeft())
                     return true;
             }
         }
@@ -2432,14 +2393,14 @@
         StringExtractorGDBRemote response;
         if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
         {
-            if (response.IsNormalResponse())
-            {
-                // Make sure we parsed the right number of characters. The response is
-                // the hex encoded group name and should make up the entire packet.
-                // If there are any non-hex ASCII bytes, the length won't match below..
-                if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
-                    return true;
-            }
+            if (!response.IsNormalResponse())
+                return false;
+
+            // Make sure we parsed the right number of characters. The response is
+            // the hex encoded group name and should make up the entire packet.
+            // If there are any non-hex ASCII bytes, the length won't match below..
+            if (response.GetHexByteString(name) * 2 == response.GetTotalBytes())
+                return true;
         }
         else
         {
@@ -2717,7 +2678,7 @@
     if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != PacketResult::Success)
         return 0;
 
-    StructuredData::ObjectSP data = StructuredData::ParseJSON(response.GetStringRef());
+    StructuredData::ObjectSP data = StructuredData::ParseJSON(response.Peek());
     if (!data)
         return 0;
 
@@ -3479,7 +3440,7 @@
         !response.IsNormalResponse())
         return nullptr;
 
-    DataBufferSP buffer_sp(new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+    DataBufferSP buffer_sp(new DataBufferHeap(response.GetBytesLeft() / 2, 0));
     response.GetHexBytes(buffer_sp->GetData(), '\xcc');
     return buffer_sp;
 }
@@ -3494,7 +3455,7 @@
         !response.IsNormalResponse())
         return nullptr;
 
-    DataBufferSP buffer_sp(new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+    DataBufferSP buffer_sp(new DataBufferHeap(response.GetBytesLeft() / 2, 0));
     response.GetHexBytes(buffer_sp->GetData(), '\xcc');
     return buffer_sp;
 }
@@ -3673,7 +3634,7 @@
                                               std::string & out,
                                               lldb_private::Error & err) {
 
-    std::stringstream output;
+    llvm::raw_string_ostream output(out);
     StringExtractorGDBRemote chunk;
 
     uint64_t size = GetRemoteMaxPacketSize();
@@ -3704,24 +3665,24 @@
             return false;
         }
 
-        const std::string & str = chunk.GetStringRef( );
-        if ( str.length() == 0 ) {
+        if (chunk.GetBytesLeft() == 0)
+        {
             // should have some data in chunk
             err.SetErrorString( "Empty response from $qXfer packet" );
             return false;
         }
 
         // check packet code
-        switch ( str[0] ) {
+        switch (chunk.GetChar())
+        {
             // last chunk
         case ( 'l' ):
             active = false;
             LLVM_FALLTHROUGH;
 
             // more chunks
         case ( 'm' ) :
-            if ( str.length() > 1 )
-                output << &str[1];
+            output << chunk.Peek();
             offset += size;
             break;
 
@@ -3732,7 +3693,7 @@
         }
     }
 
-    out = output.str( );
+    output.flush();
     err.Success( );
     return true;
 }
@@ -3809,10 +3770,8 @@
                 }
                 else
                 {
-                    llvm::StringRef response_str(response.GetStringRef());
-                    if (response_str.startswith("qSymbol:"))
+                    if (response.Consume("qSymbol:"))
                     {
-                        response.SetFilePos(strlen("qSymbol:"));
                         std::string symbol_name;
                         if (response.GetHexByteString(symbol_name))
                         {
@@ -3924,18 +3883,17 @@
         if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response,
                                          send_async) == PacketResult::Success)
         {
-            m_supported_async_json_packets_sp = StructuredData::ParseJSON(
-                response.GetStringRef());
+            m_supported_async_json_packets_sp = StructuredData::ParseJSON(response.Peek());
             if (m_supported_async_json_packets_sp &&
                 !m_supported_async_json_packets_sp->GetAsArray())
             {
                 // We were returned something other than a JSON array.  This
                 // is invalid.  Clear it out.
                 if (log)
                     log->Printf("GDBRemoteCommunicationClient::%s(): "
                                 "QSupportedAsyncJSONPackets returned invalid "
-                                "result: %s", __FUNCTION__,
-                                response.GetStringRef().c_str());
+                                "result: %s",
+                                __FUNCTION__, response.Peek().str().c_str());
                 m_supported_async_json_packets_sp.reset();
             }
         }
@@ -4002,17 +3960,16 @@
     if (result == PacketResult::Success)
     {
         // We failed if the config result comes back other than OK.
-        if (strcmp(response.GetStringRef().c_str(), "OK") == 0)
+        if (response.Peek().equals("OK"))
         {
             // Okay!
             error.Clear();
         }
         else
         {
             error.SetErrorStringWithFormat("configuring StructuredData feature "
                                            "%s failed with error %s",
-                                           type_name.AsCString(),
-                                           response.GetStringRef().c_str());
+                                           type_name.AsCString(), response.Peek().str().c_str());
         }
     }
     else
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -467,7 +467,7 @@
                             if (echo_packet_result == PacketResult::Success)
                             {
                                 ++successful_responses;
-                                if (response_regex.Execute(echo_response.GetStringRef().c_str()))
+                                if (response_regex.Execute(echo_response.Peek().str().c_str()))
                                 {
                                     sync_success = true;
                                     break;
@@ -896,7 +896,6 @@
             size_t content_end = content_start + content_length;
 
             bool success = true;
-            std::string &packet_str = packet.GetStringRef();
             if (log)
             {
                 // If logging was just enabled and we have history, then dump out what
@@ -957,8 +956,7 @@
 
             m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length);
 
-            // Clear packet_str in case there is some existing data in it.
-            packet_str.clear();
+            std::string packet_str;
             // Copy the packet from m_bytes to packet_str expanding the
             // run-length encoding in the process.
             // Reserve enough byte for the most common case (no RLE used)
@@ -1026,9 +1024,9 @@
                         log->Printf ("error: invalid checksum in packet: '%s'\n", m_bytes.c_str());
                 }
             }
-            
+
             m_bytes.erase(0, total_length);
-            packet.SetFilePos(0);
+            packet.SetString(packet_str);
 
             if (isNotifyPacket)
                 return GDBRemoteCommunication::PacketType::Notify;
@@ -1476,14 +1474,9 @@
 
         if (type == PacketType::Notify)
         {
-            // put this packet into an event
-            const char *pdata = packet.GetStringRef().c_str();
-
             // as the communication class, we are a broadcaster and the
             // async thread is tuned to listen to us
-            BroadcastEvent(
-                eBroadcastBitGdbReadThreadGotNotify,
-                new EventDataBytes(pdata));
+            BroadcastEvent(eBroadcastBitGdbReadThreadGotNotify, new EventDataBytes(packet.Peek()));
         }
     }
 }
Index: source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -77,7 +77,8 @@
 
         const char stop_type = response.GetChar();
         if (log)
-            log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str());
+            log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
+                        response.PeekFullPacket().str().c_str());
 
         switch (stop_type)
         {
@@ -99,27 +100,29 @@
                 break;
             }
             case 'A':
-                delegate.HandleAsyncMisc(llvm::StringRef(response.GetStringRef()).substr(1));
+                delegate.HandleAsyncMisc(response.Peek());
                 break;
 
             case 'J':
+            {
                 // Asynchronous JSON packet, destined for a
                 // StructuredDataPlugin.
-            {
-                // Parse the content into a StructuredData instance.
-                auto payload_index = strlen("JSON-async:");
-                StructuredData::ObjectSP json_sp =
-                    StructuredData::ParseJSON(response.GetStringRef()
-                                              .substr(payload_index));
+
+                StructuredData::ObjectSP json_sp;
+                llvm::StringRef json_text;
+                // The 'J' was already consumed.
+                if (response.Consume("SON-async:"))
+                {
+                    // Parse the content into a StructuredData instance.
+                    json_sp = StructuredData::ParseJSON(json_text = response.Peek());
+                }
+
                 if (log)
                 {
                     if (json_sp)
-                        log->Printf(
-                                    "GDBRemoteCommmunicationClientBase::%s() "
+                        log->Printf("GDBRemoteCommmunicationClientBase::%s() "
                                     "received Async StructuredData packet: %s",
-                                    __FUNCTION__,
-                                    response.GetStringRef().
-                                    substr(payload_index).c_str());
+                                    __FUNCTION__, json_text.str().c_str());
                     else
                         log->Printf("GDBRemoteCommmunicationClientBase::%s"
                                     "() received StructuredData packet:"
@@ -171,6 +174,7 @@
                 break;
         }
     }
+    response.SetFilePos(0);
 }
 
 bool
@@ -232,7 +236,7 @@
         Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS);
         if (log)
             log->Printf("error: packet with payload \"%.*s\" got invalid response \"%s\": %s", int(payload.size()),
-                        payload.data(), response.GetStringRef().c_str(),
+                        payload.data(), response.Peek().str().c_str(),
                         (i == (max_response_retries - 1)) ? "using invalid response and giving up"
                                                           : "ignoring response and waiting for another");
     }
Index: source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
===================================================================
--- source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -303,9 +303,7 @@
 
             std::vector<uint8_t> dwarf_opcode_bytes(reg_info.dynamic_size_dwarf_len);
             uint32_t j;
-            StringExtractor opcode_extractor;
-            // Swap "dwarf_opcode_string" over into "opcode_extractor"
-            opcode_extractor.GetStringRef ().swap (dwarf_opcode_string);
+            StringExtractor opcode_extractor(dwarf_opcode_string);
             uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes);
             assert (ret_val == reg_info.dynamic_size_dwarf_len);
 
Index: source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
===================================================================
--- source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -891,7 +891,7 @@
             response.GetResponseType() != response.eResponse)
         return m_remote_signals_sp;
 
-    auto object_sp = StructuredData::ParseJSON(response.GetStringRef());
+    auto object_sp = StructuredData::ParseJSON(response.Peek());
     if (!object_sp || !object_sp->IsValid())
         return m_remote_signals_sp;
 
Index: source/Core/Event.cpp
===================================================================
--- source/Core/Event.cpp
+++ source/Core/Event.cpp
@@ -138,6 +138,11 @@
 {
 }
 
+EventDataBytes::EventDataBytes(llvm::StringRef str) : m_bytes()
+{
+    SetBytes(str.data(), str.size());
+}
+
 EventDataBytes::EventDataBytes (const char *cstr) :
     m_bytes()
 {
Index: include/lldb/Utility/StringExtractor.h
===================================================================
--- include/lldb/Utility/StringExtractor.h
+++ include/lldb/Utility/StringExtractor.h
@@ -44,6 +44,13 @@
     operator=(const StringExtractor& rhs);
 
     void
+    Reset()
+    {
+        m_packet.clear();
+        m_index = 0;
+    }
+
+    void
     Reset(llvm::StringRef str)
     {
         m_packet = str;
@@ -80,16 +87,11 @@
     void
     SkipSpaces ();
 
-    std::string &
-    GetStringRef ()
-    {
-        return m_packet;
-    }
-
-    const std::string &
-    GetStringRef () const
+    void
+    SetString(llvm::StringRef str)
     {
-        return m_packet;
+        m_packet = str;
+        m_index = 0;
     }
 
     bool
@@ -99,18 +101,27 @@
     }
 
     size_t
-    GetBytesLeft ()
+    GetTotalBytes() const
+    {
+        return m_packet.size();
+    }
+
+    size_t
+    GetBytesLeft() const
     {
         if (m_index < m_packet.size())
             return m_packet.size() - m_index;
         return 0;
     }
 
+    bool
+    Consume(llvm::StringRef Str);
+
     char
     GetChar (char fail_value = '\0');
 
     char
-    PeekChar (char fail_value = '\0')
+    PeekChar(char fail_value = '\0') const
     {
         llvm::StringRef str = Peek();
         if (str.empty())
@@ -172,6 +183,12 @@
         return llvm::StringRef(m_packet).drop_front(m_index);
     }
 
+    llvm::StringRef
+    PeekFullPacket() const
+    {
+        return m_packet;
+    }
+
 protected:
     bool
     fail()
Index: include/lldb/Core/RegularExpression.h
===================================================================
--- include/lldb/Core/RegularExpression.h
+++ include/lldb/Core/RegularExpression.h
@@ -11,6 +11,7 @@
 #define liblldb_RegularExpression_h_
 
 #ifdef _WIN32
+// TODO: We should not be including LLDB private headers.
 #include "../lib/Support/regex_impl.h"
 
 typedef llvm_regmatch_t regmatch_t;
Index: include/lldb/Core/Event.h
===================================================================
--- include/lldb/Core/Event.h
+++ include/lldb/Core/Event.h
@@ -24,6 +24,8 @@
 #include "lldb/Host/Predicate.h"
 #include "lldb/Core/Broadcaster.h"
 
+#include "llvm/ADT/StringRef.h"
+
 namespace lldb_private {
 
 //----------------------------------------------------------------------
@@ -65,6 +67,8 @@
     //------------------------------------------------------------------
     EventDataBytes ();
 
+    EventDataBytes::EventDataBytes(llvm::StringRef str);
+
     EventDataBytes (const char *cstr);
 
     EventDataBytes (const void *src, size_t src_len);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to