Move StdStringExtractor to tools/debugserver
authorPavel Labath <labath@google.com>
Mon, 12 Sep 2016 16:13:05 +0000 (16:13 +0000)
committerPavel Labath <labath@google.com>
Mon, 12 Sep 2016 16:13:05 +0000 (16:13 +0000)
The class is only used in the debugserver. The rest of lldb has the StringExtractor class.

Xcode project will need to be updated after this.

llvm-svn: 281226

lldb/include/lldb/Utility/StdStringExtractor.h [deleted file]
lldb/source/Utility/CMakeLists.txt
lldb/source/Utility/StdStringExtractor.cpp [deleted file]
lldb/tools/debugserver/source/CMakeLists.txt
lldb/tools/debugserver/source/JSON.h
lldb/tools/debugserver/source/RNBRemote.cpp
lldb/tools/debugserver/source/StdStringExtractor.cpp [new file with mode: 0644]
lldb/tools/debugserver/source/StdStringExtractor.h [new file with mode: 0644]

diff --git a/lldb/include/lldb/Utility/StdStringExtractor.h b/lldb/include/lldb/Utility/StdStringExtractor.h
deleted file mode 100644 (file)
index c46978b..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-//===-- StdStringExtractor.h ------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef utility_StdStringExtractor_h_
-#define utility_StdStringExtractor_h_
-
-// C Includes
-// C++ Includes
-#include <stdint.h>
-#include <string>
-
-// Other libraries and framework includes
-// Project includes
-
-// Based on StringExtractor, with the added limitation that this file should not
-// take a dependency on LLVM, as it is used from debugserver.
-class StdStringExtractor {
-public:
-  enum { BigEndian = 0, LittleEndian = 1 };
-  //------------------------------------------------------------------
-  // Constructors and Destructors
-  //------------------------------------------------------------------
-  StdStringExtractor();
-  StdStringExtractor(const char *packet_cstr);
-  StdStringExtractor(const StdStringExtractor &rhs);
-  virtual ~StdStringExtractor();
-
-  //------------------------------------------------------------------
-  // Operators
-  //------------------------------------------------------------------
-  const StdStringExtractor &operator=(const StdStringExtractor &rhs);
-
-  // Returns true if the file position is still valid for the data
-  // contained in this string extractor object.
-  bool IsGood() const { return m_index != UINT64_MAX; }
-
-  uint64_t GetFilePos() const { return m_index; }
-
-  void SetFilePos(uint32_t idx) { m_index = idx; }
-
-  void Clear() {
-    m_packet.clear();
-    m_index = 0;
-  }
-
-  void SkipSpaces();
-
-  std::string &GetStringRef() { return m_packet; }
-
-  const std::string &GetStringRef() const { return m_packet; }
-
-  bool Empty() { return m_packet.empty(); }
-
-  size_t GetBytesLeft() {
-    if (m_index < m_packet.size())
-      return m_packet.size() - m_index;
-    return 0;
-  }
-
-  char GetChar(char fail_value = '\0');
-
-  char PeekChar(char fail_value = '\0') {
-    const char *cstr = Peek();
-    if (cstr)
-      return cstr[0];
-    return fail_value;
-  }
-
-  int DecodeHexU8();
-
-  uint8_t GetHexU8(uint8_t fail_value = 0, bool set_eof_on_fail = true);
-
-  bool GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail = true);
-
-  bool GetNameColonValue(std::string &name, std::string &value);
-
-  int32_t GetS32(int32_t fail_value, int base = 0);
-
-  uint32_t GetU32(uint32_t fail_value, int base = 0);
-
-  int64_t GetS64(int64_t fail_value, int base = 0);
-
-  uint64_t GetU64(uint64_t fail_value, int base = 0);
-
-  uint32_t GetHexMaxU32(bool little_endian, uint32_t fail_value);
-
-  uint64_t GetHexMaxU64(bool little_endian, uint64_t fail_value);
-
-  size_t GetHexBytes(void *dst, size_t dst_len, uint8_t fail_fill_value);
-
-  size_t GetHexBytesAvail(void *dst, size_t dst_len);
-
-  uint64_t GetHexWithFixedSize(uint32_t byte_size, bool little_endian,
-                               uint64_t fail_value);
-
-  size_t GetHexByteString(std::string &str);
-
-  size_t GetHexByteStringFixedLength(std::string &str, uint32_t nibble_length);
-
-  size_t GetHexByteStringTerminatedBy(std::string &str, char terminator);
-
-  const char *Peek() {
-    if (m_index < m_packet.size())
-      return m_packet.c_str() + m_index;
-    return nullptr;
-  }
-
-protected:
-  //------------------------------------------------------------------
-  // For StdStringExtractor only
-  //------------------------------------------------------------------
-  std::string m_packet; // The string in which to extract data.
-  uint64_t m_index;     // When extracting data from a packet, this index
-                        // will march along as things get extracted. If set
-                        // to UINT64_MAX the end of the packet data was
-                        // reached when decoding information
-};
-
-#endif // utility_StringExtractor_h_
index 72c38b2135f51a4119ac8e085bd71c94f5f89f3e..90aff225fe39eca4f5109f628b16f2ade86761bc 100644 (file)
@@ -12,7 +12,6 @@ add_lldb_library(lldbUtility
   RegisterNumber.cpp
   SelectHelper.cpp
   SharingPtr.cpp
-  StdStringExtractor.cpp
   StringExtractor.cpp
   StringExtractorGDBRemote.cpp
   StringLexer.cpp
diff --git a/lldb/source/Utility/StdStringExtractor.cpp b/lldb/source/Utility/StdStringExtractor.cpp
deleted file mode 100644 (file)
index c439edd..0000000
+++ /dev/null
@@ -1,405 +0,0 @@
-//===-- StdStringExtractor.cpp ----------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Utility/StdStringExtractor.h"
-
-// C Includes
-#include <stdlib.h>
-
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-
-static inline int xdigit_to_sint(char ch) {
-  if (ch >= 'a' && ch <= 'f')
-    return 10 + ch - 'a';
-  if (ch >= 'A' && ch <= 'F')
-    return 10 + ch - 'A';
-  if (ch >= '0' && ch <= '9')
-    return ch - '0';
-  return -1;
-}
-
-//----------------------------------------------------------------------
-// StdStringExtractor constructor
-//----------------------------------------------------------------------
-StdStringExtractor::StdStringExtractor() : m_packet(), m_index(0) {}
-
-StdStringExtractor::StdStringExtractor(const char *packet_cstr)
-    : m_packet(), m_index(0) {
-  if (packet_cstr)
-    m_packet.assign(packet_cstr);
-}
-
-//----------------------------------------------------------------------
-// StdStringExtractor copy constructor
-//----------------------------------------------------------------------
-StdStringExtractor::StdStringExtractor(const StdStringExtractor &rhs)
-    : m_packet(rhs.m_packet), m_index(rhs.m_index) {}
-
-//----------------------------------------------------------------------
-// StdStringExtractor assignment operator
-//----------------------------------------------------------------------
-const StdStringExtractor &StdStringExtractor::
-operator=(const StdStringExtractor &rhs) {
-  if (this != &rhs) {
-    m_packet = rhs.m_packet;
-    m_index = rhs.m_index;
-  }
-  return *this;
-}
-
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-StdStringExtractor::~StdStringExtractor() {}
-
-char StdStringExtractor::GetChar(char fail_value) {
-  if (m_index < m_packet.size()) {
-    char ch = m_packet[m_index];
-    ++m_index;
-    return ch;
-  }
-  m_index = UINT64_MAX;
-  return fail_value;
-}
-
-//----------------------------------------------------------------------
-// If a pair of valid hex digits exist at the head of the
-// StdStringExtractor they are decoded into an unsigned byte and returned
-// by this function
-//
-// If there is not a pair of valid hex digits at the head of the
-// StdStringExtractor, it is left unchanged and -1 is returned
-//----------------------------------------------------------------------
-int StdStringExtractor::DecodeHexU8() {
-  SkipSpaces();
-  if (GetBytesLeft() < 2) {
-    return -1;
-  }
-  const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
-  const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
-  if (hi_nibble == -1 || lo_nibble == -1) {
-    return -1;
-  }
-  m_index += 2;
-  return (uint8_t)((hi_nibble << 4) + lo_nibble);
-}
-
-//----------------------------------------------------------------------
-// Extract an unsigned character from two hex ASCII chars in the packet
-// string, or return fail_value on failure
-//----------------------------------------------------------------------
-uint8_t StdStringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
-  // On success, fail_value will be overwritten with the next
-  // character in the stream
-  GetHexU8Ex(fail_value, set_eof_on_fail);
-  return fail_value;
-}
-
-bool StdStringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
-  int byte = DecodeHexU8();
-  if (byte == -1) {
-    if (set_eof_on_fail || m_index >= m_packet.size())
-      m_index = UINT64_MAX;
-    // ch should not be changed in case of failure
-    return false;
-  }
-  ch = (uint8_t)byte;
-  return true;
-}
-
-uint32_t StdStringExtractor::GetU32(uint32_t fail_value, int base) {
-  if (m_index < m_packet.size()) {
-    char *end = nullptr;
-    const char *start = m_packet.c_str();
-    const char *cstr = start + m_index;
-    uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
-
-    if (end && end != cstr) {
-      m_index = end - start;
-      return result;
-    }
-  }
-  return fail_value;
-}
-
-int32_t StdStringExtractor::GetS32(int32_t fail_value, int base) {
-  if (m_index < m_packet.size()) {
-    char *end = nullptr;
-    const char *start = m_packet.c_str();
-    const char *cstr = start + m_index;
-    int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
-
-    if (end && end != cstr) {
-      m_index = end - start;
-      return result;
-    }
-  }
-  return fail_value;
-}
-
-uint64_t StdStringExtractor::GetU64(uint64_t fail_value, int base) {
-  if (m_index < m_packet.size()) {
-    char *end = nullptr;
-    const char *start = m_packet.c_str();
-    const char *cstr = start + m_index;
-    uint64_t result = ::strtoull(cstr, &end, base);
-
-    if (end && end != cstr) {
-      m_index = end - start;
-      return result;
-    }
-  }
-  return fail_value;
-}
-
-int64_t StdStringExtractor::GetS64(int64_t fail_value, int base) {
-  if (m_index < m_packet.size()) {
-    char *end = nullptr;
-    const char *start = m_packet.c_str();
-    const char *cstr = start + m_index;
-    int64_t result = ::strtoll(cstr, &end, base);
-
-    if (end && end != cstr) {
-      m_index = end - start;
-      return result;
-    }
-  }
-  return fail_value;
-}
-
-uint32_t StdStringExtractor::GetHexMaxU32(bool little_endian,
-                                          uint32_t fail_value) {
-  uint32_t result = 0;
-  uint32_t nibble_count = 0;
-
-  SkipSpaces();
-  if (little_endian) {
-    uint32_t shift_amount = 0;
-    while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
-      // Make sure we don't exceed the size of a uint32_t...
-      if (nibble_count >= (sizeof(uint32_t) * 2)) {
-        m_index = UINT64_MAX;
-        return fail_value;
-      }
-
-      uint8_t nibble_lo;
-      uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
-      ++m_index;
-      if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
-        nibble_lo = xdigit_to_sint(m_packet[m_index]);
-        ++m_index;
-        result |= ((uint32_t)nibble_hi << (shift_amount + 4));
-        result |= ((uint32_t)nibble_lo << shift_amount);
-        nibble_count += 2;
-        shift_amount += 8;
-      } else {
-        result |= ((uint32_t)nibble_hi << shift_amount);
-        nibble_count += 1;
-        shift_amount += 4;
-      }
-    }
-  } else {
-    while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
-      // Make sure we don't exceed the size of a uint32_t...
-      if (nibble_count >= (sizeof(uint32_t) * 2)) {
-        m_index = UINT64_MAX;
-        return fail_value;
-      }
-
-      uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
-      // Big Endian
-      result <<= 4;
-      result |= nibble;
-
-      ++m_index;
-      ++nibble_count;
-    }
-  }
-  return result;
-}
-
-uint64_t StdStringExtractor::GetHexMaxU64(bool little_endian,
-                                          uint64_t fail_value) {
-  uint64_t result = 0;
-  uint32_t nibble_count = 0;
-
-  SkipSpaces();
-  if (little_endian) {
-    uint32_t shift_amount = 0;
-    while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
-      // Make sure we don't exceed the size of a uint64_t...
-      if (nibble_count >= (sizeof(uint64_t) * 2)) {
-        m_index = UINT64_MAX;
-        return fail_value;
-      }
-
-      uint8_t nibble_lo;
-      uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
-      ++m_index;
-      if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
-        nibble_lo = xdigit_to_sint(m_packet[m_index]);
-        ++m_index;
-        result |= ((uint64_t)nibble_hi << (shift_amount + 4));
-        result |= ((uint64_t)nibble_lo << shift_amount);
-        nibble_count += 2;
-        shift_amount += 8;
-      } else {
-        result |= ((uint64_t)nibble_hi << shift_amount);
-        nibble_count += 1;
-        shift_amount += 4;
-      }
-    }
-  } else {
-    while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
-      // Make sure we don't exceed the size of a uint64_t...
-      if (nibble_count >= (sizeof(uint64_t) * 2)) {
-        m_index = UINT64_MAX;
-        return fail_value;
-      }
-
-      uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
-      // Big Endian
-      result <<= 4;
-      result |= nibble;
-
-      ++m_index;
-      ++nibble_count;
-    }
-  }
-  return result;
-}
-
-size_t StdStringExtractor::GetHexBytes(void *dst_void, size_t dst_len,
-                                       uint8_t fail_fill_value) {
-  uint8_t *dst = (uint8_t *)dst_void;
-  size_t bytes_extracted = 0;
-  while (bytes_extracted < dst_len && GetBytesLeft()) {
-    dst[bytes_extracted] = GetHexU8(fail_fill_value);
-    if (IsGood())
-      ++bytes_extracted;
-    else
-      break;
-  }
-
-  for (size_t i = bytes_extracted; i < dst_len; ++i)
-    dst[i] = fail_fill_value;
-
-  return bytes_extracted;
-}
-
-//----------------------------------------------------------------------
-// Decodes all valid hex encoded bytes at the head of the
-// StdStringExtractor, limited by dst_len.
-//
-// Returns the number of bytes successfully decoded
-//----------------------------------------------------------------------
-size_t StdStringExtractor::GetHexBytesAvail(void *dst_void, size_t dst_len) {
-  uint8_t *dst = (uint8_t *)dst_void;
-  size_t bytes_extracted = 0;
-  while (bytes_extracted < dst_len) {
-    int decode = DecodeHexU8();
-    if (decode == -1) {
-      break;
-    }
-    dst[bytes_extracted++] = (uint8_t)decode;
-  }
-  return bytes_extracted;
-}
-
-// Consume ASCII hex nibble character pairs until we have decoded byte_size
-// bytes of data.
-
-uint64_t StdStringExtractor::GetHexWithFixedSize(uint32_t byte_size,
-                                                 bool little_endian,
-                                                 uint64_t fail_value) {
-  if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) {
-    uint64_t result = 0;
-    uint32_t i;
-    if (little_endian) {
-      // Little Endian
-      uint32_t shift_amount;
-      for (i = 0, shift_amount = 0; i < byte_size && IsGood();
-           ++i, shift_amount += 8) {
-        result |= ((uint64_t)GetHexU8() << shift_amount);
-      }
-    } else {
-      // Big Endian
-      for (i = 0; i < byte_size && IsGood(); ++i) {
-        result <<= 8;
-        result |= GetHexU8();
-      }
-    }
-  }
-  m_index = UINT64_MAX;
-  return fail_value;
-}
-
-size_t StdStringExtractor::GetHexByteString(std::string &str) {
-  str.clear();
-  str.reserve(GetBytesLeft() / 2);
-  char ch;
-  while ((ch = GetHexU8()) != '\0')
-    str.append(1, ch);
-  return str.size();
-}
-
-size_t StdStringExtractor::GetHexByteStringFixedLength(std::string &str,
-                                                       uint32_t nibble_length) {
-  str.clear();
-
-  uint32_t nibble_count = 0;
-  for (const char *pch = Peek();
-       (nibble_count < nibble_length) && (pch != nullptr);
-       str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
-  }
-
-  return str.size();
-}
-
-size_t StdStringExtractor::GetHexByteStringTerminatedBy(std::string &str,
-                                                        char terminator) {
-  str.clear();
-  char ch;
-  while ((ch = GetHexU8(0, false)) != '\0')
-    str.append(1, ch);
-  if (Peek() && *Peek() == terminator)
-    return str.size();
-
-  str.clear();
-  return str.size();
-}
-
-bool StdStringExtractor::GetNameColonValue(std::string &name,
-                                           std::string &value) {
-  // Read something in the form of NNNN:VVVV; where NNNN is any character
-  // that is not a colon, followed by a ':' character, then a value (one or
-  // more ';' chars), followed by a ';'
-  if (m_index < m_packet.size()) {
-    const size_t colon_idx = m_packet.find(':', m_index);
-    if (colon_idx != std::string::npos) {
-      const size_t semicolon_idx = m_packet.find(';', colon_idx);
-      if (semicolon_idx != std::string::npos) {
-        name.assign(m_packet, m_index, colon_idx - m_index);
-        value.assign(m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
-        m_index = semicolon_idx + 1;
-        return true;
-      }
-    }
-  }
-  m_index = UINT64_MAX;
-  return false;
-}
-
-void StdStringExtractor::SkipSpaces() {
-  const size_t n = m_packet.size();
-  while (m_index < n && isspace(m_packet[m_index]))
-    ++m_index;
-}
index 9bd518e37729d1b44ec557ce165c3c965347c156..43479bd36435b0ef3954fdf7b56a22e70c6611b7 100644 (file)
@@ -44,9 +44,9 @@ add_library(lldbDebugserverCommon
   DNBRegisterInfo.cpp
   DNBThreadResumeActions.cpp
   JSON.cpp
+  StdStringExtractor.cpp
   # JSON reader depends on the following LLDB-common files
   ${LLDB_SOURCE_DIR}/source/Host/common/StringConvert.cpp
-  ${LLDB_SOURCE_DIR}/source/Utility/StdStringExtractor.cpp
   # end JSON reader dependencies
   libdebugserver.cpp
   PseudoTerminal.cpp
index d3951776cac835002dd64fb470b8d3f551706796..eee62f4533279b35c8e91850e9c4d1881230c2f9 100644 (file)
@@ -10,9 +10,7 @@
 #ifndef utility_JSON_h_
 #define utility_JSON_h_
 
-// This cross-project usage is fine as StdStringExtractor.h is entirely
-// self-contained.
-#include "lldb/Utility/StdStringExtractor.h"
+#include "StdStringExtractor.h"
 
 // C includes
 #include <inttypes.h>
index 6ee84eed27dde6ab59e530b27003d6e327355f46..71c6f717cadf15cbf3eea9386bfe9d2455f92777 100644 (file)
@@ -40,7 +40,7 @@
 #include "RNBContext.h"
 #include "RNBServices.h"
 #include "RNBSocket.h"
-#include "lldb/Utility/StdStringExtractor.h"
+#include "StdStringExtractor.h"
 
 #if defined(HAVE_LIBCOMPRESSION)
 #include <compression.h>
diff --git a/lldb/tools/debugserver/source/StdStringExtractor.cpp b/lldb/tools/debugserver/source/StdStringExtractor.cpp
new file mode 100644 (file)
index 0000000..d23f931
--- /dev/null
@@ -0,0 +1,405 @@
+//===-- StdStringExtractor.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StdStringExtractor.h"
+
+// C Includes
+#include <stdlib.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+static inline int xdigit_to_sint(char ch) {
+  if (ch >= 'a' && ch <= 'f')
+    return 10 + ch - 'a';
+  if (ch >= 'A' && ch <= 'F')
+    return 10 + ch - 'A';
+  if (ch >= '0' && ch <= '9')
+    return ch - '0';
+  return -1;
+}
+
+//----------------------------------------------------------------------
+// StdStringExtractor constructor
+//----------------------------------------------------------------------
+StdStringExtractor::StdStringExtractor() : m_packet(), m_index(0) {}
+
+StdStringExtractor::StdStringExtractor(const char *packet_cstr)
+    : m_packet(), m_index(0) {
+  if (packet_cstr)
+    m_packet.assign(packet_cstr);
+}
+
+//----------------------------------------------------------------------
+// StdStringExtractor copy constructor
+//----------------------------------------------------------------------
+StdStringExtractor::StdStringExtractor(const StdStringExtractor &rhs)
+    : m_packet(rhs.m_packet), m_index(rhs.m_index) {}
+
+//----------------------------------------------------------------------
+// StdStringExtractor assignment operator
+//----------------------------------------------------------------------
+const StdStringExtractor &StdStringExtractor::
+operator=(const StdStringExtractor &rhs) {
+  if (this != &rhs) {
+    m_packet = rhs.m_packet;
+    m_index = rhs.m_index;
+  }
+  return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+StdStringExtractor::~StdStringExtractor() {}
+
+char StdStringExtractor::GetChar(char fail_value) {
+  if (m_index < m_packet.size()) {
+    char ch = m_packet[m_index];
+    ++m_index;
+    return ch;
+  }
+  m_index = UINT64_MAX;
+  return fail_value;
+}
+
+//----------------------------------------------------------------------
+// If a pair of valid hex digits exist at the head of the
+// StdStringExtractor they are decoded into an unsigned byte and returned
+// by this function
+//
+// If there is not a pair of valid hex digits at the head of the
+// StdStringExtractor, it is left unchanged and -1 is returned
+//----------------------------------------------------------------------
+int StdStringExtractor::DecodeHexU8() {
+  SkipSpaces();
+  if (GetBytesLeft() < 2) {
+    return -1;
+  }
+  const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
+  const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
+  if (hi_nibble == -1 || lo_nibble == -1) {
+    return -1;
+  }
+  m_index += 2;
+  return (uint8_t)((hi_nibble << 4) + lo_nibble);
+}
+
+//----------------------------------------------------------------------
+// Extract an unsigned character from two hex ASCII chars in the packet
+// string, or return fail_value on failure
+//----------------------------------------------------------------------
+uint8_t StdStringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
+  // On success, fail_value will be overwritten with the next
+  // character in the stream
+  GetHexU8Ex(fail_value, set_eof_on_fail);
+  return fail_value;
+}
+
+bool StdStringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
+  int byte = DecodeHexU8();
+  if (byte == -1) {
+    if (set_eof_on_fail || m_index >= m_packet.size())
+      m_index = UINT64_MAX;
+    // ch should not be changed in case of failure
+    return false;
+  }
+  ch = (uint8_t)byte;
+  return true;
+}
+
+uint32_t StdStringExtractor::GetU32(uint32_t fail_value, int base) {
+  if (m_index < m_packet.size()) {
+    char *end = nullptr;
+    const char *start = m_packet.c_str();
+    const char *cstr = start + m_index;
+    uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
+
+    if (end && end != cstr) {
+      m_index = end - start;
+      return result;
+    }
+  }
+  return fail_value;
+}
+
+int32_t StdStringExtractor::GetS32(int32_t fail_value, int base) {
+  if (m_index < m_packet.size()) {
+    char *end = nullptr;
+    const char *start = m_packet.c_str();
+    const char *cstr = start + m_index;
+    int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
+
+    if (end && end != cstr) {
+      m_index = end - start;
+      return result;
+    }
+  }
+  return fail_value;
+}
+
+uint64_t StdStringExtractor::GetU64(uint64_t fail_value, int base) {
+  if (m_index < m_packet.size()) {
+    char *end = nullptr;
+    const char *start = m_packet.c_str();
+    const char *cstr = start + m_index;
+    uint64_t result = ::strtoull(cstr, &end, base);
+
+    if (end && end != cstr) {
+      m_index = end - start;
+      return result;
+    }
+  }
+  return fail_value;
+}
+
+int64_t StdStringExtractor::GetS64(int64_t fail_value, int base) {
+  if (m_index < m_packet.size()) {
+    char *end = nullptr;
+    const char *start = m_packet.c_str();
+    const char *cstr = start + m_index;
+    int64_t result = ::strtoll(cstr, &end, base);
+
+    if (end && end != cstr) {
+      m_index = end - start;
+      return result;
+    }
+  }
+  return fail_value;
+}
+
+uint32_t StdStringExtractor::GetHexMaxU32(bool little_endian,
+                                          uint32_t fail_value) {
+  uint32_t result = 0;
+  uint32_t nibble_count = 0;
+
+  SkipSpaces();
+  if (little_endian) {
+    uint32_t shift_amount = 0;
+    while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+      // Make sure we don't exceed the size of a uint32_t...
+      if (nibble_count >= (sizeof(uint32_t) * 2)) {
+        m_index = UINT64_MAX;
+        return fail_value;
+      }
+
+      uint8_t nibble_lo;
+      uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
+      ++m_index;
+      if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+        nibble_lo = xdigit_to_sint(m_packet[m_index]);
+        ++m_index;
+        result |= ((uint32_t)nibble_hi << (shift_amount + 4));
+        result |= ((uint32_t)nibble_lo << shift_amount);
+        nibble_count += 2;
+        shift_amount += 8;
+      } else {
+        result |= ((uint32_t)nibble_hi << shift_amount);
+        nibble_count += 1;
+        shift_amount += 4;
+      }
+    }
+  } else {
+    while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+      // Make sure we don't exceed the size of a uint32_t...
+      if (nibble_count >= (sizeof(uint32_t) * 2)) {
+        m_index = UINT64_MAX;
+        return fail_value;
+      }
+
+      uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
+      // Big Endian
+      result <<= 4;
+      result |= nibble;
+
+      ++m_index;
+      ++nibble_count;
+    }
+  }
+  return result;
+}
+
+uint64_t StdStringExtractor::GetHexMaxU64(bool little_endian,
+                                          uint64_t fail_value) {
+  uint64_t result = 0;
+  uint32_t nibble_count = 0;
+
+  SkipSpaces();
+  if (little_endian) {
+    uint32_t shift_amount = 0;
+    while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+      // Make sure we don't exceed the size of a uint64_t...
+      if (nibble_count >= (sizeof(uint64_t) * 2)) {
+        m_index = UINT64_MAX;
+        return fail_value;
+      }
+
+      uint8_t nibble_lo;
+      uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
+      ++m_index;
+      if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+        nibble_lo = xdigit_to_sint(m_packet[m_index]);
+        ++m_index;
+        result |= ((uint64_t)nibble_hi << (shift_amount + 4));
+        result |= ((uint64_t)nibble_lo << shift_amount);
+        nibble_count += 2;
+        shift_amount += 8;
+      } else {
+        result |= ((uint64_t)nibble_hi << shift_amount);
+        nibble_count += 1;
+        shift_amount += 4;
+      }
+    }
+  } else {
+    while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+      // Make sure we don't exceed the size of a uint64_t...
+      if (nibble_count >= (sizeof(uint64_t) * 2)) {
+        m_index = UINT64_MAX;
+        return fail_value;
+      }
+
+      uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
+      // Big Endian
+      result <<= 4;
+      result |= nibble;
+
+      ++m_index;
+      ++nibble_count;
+    }
+  }
+  return result;
+}
+
+size_t StdStringExtractor::GetHexBytes(void *dst_void, size_t dst_len,
+                                       uint8_t fail_fill_value) {
+  uint8_t *dst = (uint8_t *)dst_void;
+  size_t bytes_extracted = 0;
+  while (bytes_extracted < dst_len && GetBytesLeft()) {
+    dst[bytes_extracted] = GetHexU8(fail_fill_value);
+    if (IsGood())
+      ++bytes_extracted;
+    else
+      break;
+  }
+
+  for (size_t i = bytes_extracted; i < dst_len; ++i)
+    dst[i] = fail_fill_value;
+
+  return bytes_extracted;
+}
+
+//----------------------------------------------------------------------
+// Decodes all valid hex encoded bytes at the head of the
+// StdStringExtractor, limited by dst_len.
+//
+// Returns the number of bytes successfully decoded
+//----------------------------------------------------------------------
+size_t StdStringExtractor::GetHexBytesAvail(void *dst_void, size_t dst_len) {
+  uint8_t *dst = (uint8_t *)dst_void;
+  size_t bytes_extracted = 0;
+  while (bytes_extracted < dst_len) {
+    int decode = DecodeHexU8();
+    if (decode == -1) {
+      break;
+    }
+    dst[bytes_extracted++] = (uint8_t)decode;
+  }
+  return bytes_extracted;
+}
+
+// Consume ASCII hex nibble character pairs until we have decoded byte_size
+// bytes of data.
+
+uint64_t StdStringExtractor::GetHexWithFixedSize(uint32_t byte_size,
+                                                 bool little_endian,
+                                                 uint64_t fail_value) {
+  if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) {
+    uint64_t result = 0;
+    uint32_t i;
+    if (little_endian) {
+      // Little Endian
+      uint32_t shift_amount;
+      for (i = 0, shift_amount = 0; i < byte_size && IsGood();
+           ++i, shift_amount += 8) {
+        result |= ((uint64_t)GetHexU8() << shift_amount);
+      }
+    } else {
+      // Big Endian
+      for (i = 0; i < byte_size && IsGood(); ++i) {
+        result <<= 8;
+        result |= GetHexU8();
+      }
+    }
+  }
+  m_index = UINT64_MAX;
+  return fail_value;
+}
+
+size_t StdStringExtractor::GetHexByteString(std::string &str) {
+  str.clear();
+  str.reserve(GetBytesLeft() / 2);
+  char ch;
+  while ((ch = GetHexU8()) != '\0')
+    str.append(1, ch);
+  return str.size();
+}
+
+size_t StdStringExtractor::GetHexByteStringFixedLength(std::string &str,
+                                                       uint32_t nibble_length) {
+  str.clear();
+
+  uint32_t nibble_count = 0;
+  for (const char *pch = Peek();
+       (nibble_count < nibble_length) && (pch != nullptr);
+       str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
+  }
+
+  return str.size();
+}
+
+size_t StdStringExtractor::GetHexByteStringTerminatedBy(std::string &str,
+                                                        char terminator) {
+  str.clear();
+  char ch;
+  while ((ch = GetHexU8(0, false)) != '\0')
+    str.append(1, ch);
+  if (Peek() && *Peek() == terminator)
+    return str.size();
+
+  str.clear();
+  return str.size();
+}
+
+bool StdStringExtractor::GetNameColonValue(std::string &name,
+                                           std::string &value) {
+  // Read something in the form of NNNN:VVVV; where NNNN is any character
+  // that is not a colon, followed by a ':' character, then a value (one or
+  // more ';' chars), followed by a ';'
+  if (m_index < m_packet.size()) {
+    const size_t colon_idx = m_packet.find(':', m_index);
+    if (colon_idx != std::string::npos) {
+      const size_t semicolon_idx = m_packet.find(';', colon_idx);
+      if (semicolon_idx != std::string::npos) {
+        name.assign(m_packet, m_index, colon_idx - m_index);
+        value.assign(m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
+        m_index = semicolon_idx + 1;
+        return true;
+      }
+    }
+  }
+  m_index = UINT64_MAX;
+  return false;
+}
+
+void StdStringExtractor::SkipSpaces() {
+  const size_t n = m_packet.size();
+  while (m_index < n && isspace(m_packet[m_index]))
+    ++m_index;
+}
diff --git a/lldb/tools/debugserver/source/StdStringExtractor.h b/lldb/tools/debugserver/source/StdStringExtractor.h
new file mode 100644 (file)
index 0000000..c46978b
--- /dev/null
@@ -0,0 +1,125 @@
+//===-- StdStringExtractor.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_StdStringExtractor_h_
+#define utility_StdStringExtractor_h_
+
+// C Includes
+// C++ Includes
+#include <stdint.h>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+
+// Based on StringExtractor, with the added limitation that this file should not
+// take a dependency on LLVM, as it is used from debugserver.
+class StdStringExtractor {
+public:
+  enum { BigEndian = 0, LittleEndian = 1 };
+  //------------------------------------------------------------------
+  // Constructors and Destructors
+  //------------------------------------------------------------------
+  StdStringExtractor();
+  StdStringExtractor(const char *packet_cstr);
+  StdStringExtractor(const StdStringExtractor &rhs);
+  virtual ~StdStringExtractor();
+
+  //------------------------------------------------------------------
+  // Operators
+  //------------------------------------------------------------------
+  const StdStringExtractor &operator=(const StdStringExtractor &rhs);
+
+  // Returns true if the file position is still valid for the data
+  // contained in this string extractor object.
+  bool IsGood() const { return m_index != UINT64_MAX; }
+
+  uint64_t GetFilePos() const { return m_index; }
+
+  void SetFilePos(uint32_t idx) { m_index = idx; }
+
+  void Clear() {
+    m_packet.clear();
+    m_index = 0;
+  }
+
+  void SkipSpaces();
+
+  std::string &GetStringRef() { return m_packet; }
+
+  const std::string &GetStringRef() const { return m_packet; }
+
+  bool Empty() { return m_packet.empty(); }
+
+  size_t GetBytesLeft() {
+    if (m_index < m_packet.size())
+      return m_packet.size() - m_index;
+    return 0;
+  }
+
+  char GetChar(char fail_value = '\0');
+
+  char PeekChar(char fail_value = '\0') {
+    const char *cstr = Peek();
+    if (cstr)
+      return cstr[0];
+    return fail_value;
+  }
+
+  int DecodeHexU8();
+
+  uint8_t GetHexU8(uint8_t fail_value = 0, bool set_eof_on_fail = true);
+
+  bool GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail = true);
+
+  bool GetNameColonValue(std::string &name, std::string &value);
+
+  int32_t GetS32(int32_t fail_value, int base = 0);
+
+  uint32_t GetU32(uint32_t fail_value, int base = 0);
+
+  int64_t GetS64(int64_t fail_value, int base = 0);
+
+  uint64_t GetU64(uint64_t fail_value, int base = 0);
+
+  uint32_t GetHexMaxU32(bool little_endian, uint32_t fail_value);
+
+  uint64_t GetHexMaxU64(bool little_endian, uint64_t fail_value);
+
+  size_t GetHexBytes(void *dst, size_t dst_len, uint8_t fail_fill_value);
+
+  size_t GetHexBytesAvail(void *dst, size_t dst_len);
+
+  uint64_t GetHexWithFixedSize(uint32_t byte_size, bool little_endian,
+                               uint64_t fail_value);
+
+  size_t GetHexByteString(std::string &str);
+
+  size_t GetHexByteStringFixedLength(std::string &str, uint32_t nibble_length);
+
+  size_t GetHexByteStringTerminatedBy(std::string &str, char terminator);
+
+  const char *Peek() {
+    if (m_index < m_packet.size())
+      return m_packet.c_str() + m_index;
+    return nullptr;
+  }
+
+protected:
+  //------------------------------------------------------------------
+  // For StdStringExtractor only
+  //------------------------------------------------------------------
+  std::string m_packet; // The string in which to extract data.
+  uint64_t m_index;     // When extracting data from a packet, this index
+                        // will march along as things get extracted. If set
+                        // to UINT64_MAX the end of the packet data was
+                        // reached when decoding information
+};
+
+#endif // utility_StringExtractor_h_