summaryrefslogtreecommitdiffstats
path: root/lldb/source/Utility/StringExtractor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Utility/StringExtractor.cpp')
-rw-r--r--lldb/source/Utility/StringExtractor.cpp218
1 files changed, 156 insertions, 62 deletions
diff --git a/lldb/source/Utility/StringExtractor.cpp b/lldb/source/Utility/StringExtractor.cpp
index 1c40a30847c..f62c8363700 100644
--- a/lldb/source/Utility/StringExtractor.cpp
+++ b/lldb/source/Utility/StringExtractor.cpp
@@ -16,8 +16,6 @@
#include <tuple>
// Other libraries and framework includes
// Project includes
-#include "llvm/ADT/Optional.h"
-#include "llvm/Support/Endian.h"
static inline int
xdigit_to_sint (char ch)
@@ -100,16 +98,6 @@ StringExtractor::GetChar (char fail_value)
return fail_value;
}
-static llvm::Optional<uint8_t>
-translateHexChar(char ch1, char ch2)
-{
- const int hi_nibble = xdigit_to_sint(ch1);
- const int lo_nibble = xdigit_to_sint(ch2);
- if (hi_nibble == -1 || lo_nibble == -1)
- return llvm::None;
- return (uint8_t)((hi_nibble << 4) + lo_nibble);
-}
-
//----------------------------------------------------------------------
// If a pair of valid hex digits exist at the head of the
// StringExtractor they are decoded into an unsigned byte and returned
@@ -123,12 +111,17 @@ StringExtractor::DecodeHexU8()
{
SkipSpaces();
if (GetBytesLeft() < 2)
+ {
return -1;
- auto result = translateHexChar(m_packet[m_index], m_packet[m_index + 1]);
- if (!result.hasValue())
+ }
+ 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 *result;
+ return (uint8_t)((hi_nibble << 4) + lo_nibble);
}
//----------------------------------------------------------------------
@@ -236,60 +229,131 @@ StringExtractor::GetS64 (int64_t fail_value, int base)
return fail_value;
}
+
uint32_t
StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
{
- SkipSpaces();
+ uint32_t result = 0;
+ uint32_t nibble_count = 0;
- // Allocate enough space for 2 uint32's. In big endian, if the user writes
- // "AB" then this should be treated as 0xAB, not 0xAB000000. In order to
- // do this, we decode into the second half of the array, and then shift the
- // starting point of the big endian translation left by however many bytes
- // of a uint32 were missing from the input. We're essentially padding left
- // with 0's.
- uint8_t bytes[2 * sizeof(uint32_t) - 1] = {0};
- llvm::MutableArrayRef<uint8_t> byte_array(bytes);
- llvm::MutableArrayRef<uint8_t> decode_loc = byte_array.take_back(sizeof(uint32_t));
- uint32_t bytes_decoded = GetHexBytesAvail(decode_loc);
- if (bytes_decoded == sizeof(uint32_t) && ::isxdigit(PeekChar()))
- return fail();
-
- using namespace llvm::support;
+ SkipSpaces();
if (little_endian)
- return endian::read<uint32_t, endianness::little>(decode_loc.data());
+ {
+ 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
{
- decode_loc = byte_array.drop_front(bytes_decoded - 1).take_front(sizeof(uint32_t));
- return endian::read<uint32_t, endianness::big>(decode_loc.data());
+ 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
StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
{
- SkipSpaces();
-
- // Allocate enough space for 2 uint64's. In big endian, if the user writes
- // "AB" then this should be treated as 0x000000AB, not 0xAB000000. In order
- // to do this, we decode into the second half of the array, and then shift
- // the starting point of the big endian translation left by however many bytes
- // of a uint32 were missing from the input. We're essentially padding left
- // with 0's.
- uint8_t bytes[2 * sizeof(uint64_t) - 1] = {0};
- llvm::MutableArrayRef<uint8_t> byte_array(bytes);
- llvm::MutableArrayRef<uint8_t> decode_loc = byte_array.take_back(sizeof(uint64_t));
- uint32_t bytes_decoded = GetHexBytesAvail(decode_loc);
- if (bytes_decoded == sizeof(uint64_t) && ::isxdigit(PeekChar()))
- return fail();
+ uint64_t result = 0;
+ uint32_t nibble_count = 0;
- using namespace llvm::support;
+ SkipSpaces();
if (little_endian)
- return endian::read<uint64_t, endianness::little>(decode_loc.data());
+ {
+ 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
{
- decode_loc = byte_array.drop_front(bytes_decoded - 1).take_front(sizeof(uint64_t));
- return endian::read<uint64_t, endianness::big>(decode_loc.data());
+ 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
@@ -333,6 +397,41 @@ StringExtractor::GetHexBytesAvail (llvm::MutableArrayRef<uint8_t> dest)
return bytes_extracted;
}
+// Consume ASCII hex nibble character pairs until we have decoded byte_size
+// bytes of data.
+
+uint64_t
+StringExtractor::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
StringExtractor::GetHexByteString (std::string &str)
{
@@ -348,16 +447,11 @@ size_t
StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
{
str.clear();
- llvm::StringRef nibs = Peek().take_front(nibble_length);
- while (nibs.size() >= 2)
- {
- auto ch = translateHexChar(nibs[0], nibs[1]);
- if (!ch.hasValue())
- break;
- str.push_back(*ch);
- nibs = nibs.drop_front(2);
- }
- m_index += str.size() * 2;
+
+ 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();
}
@@ -369,7 +463,7 @@ StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
char ch;
while ((ch = GetHexU8(0,false)) != '\0')
str.append(1, ch);
- if (GetBytesLeft() > 0 && PeekChar() == terminator)
+ if (Peek() && *Peek() == terminator)
return str.size();
str.clear();
OpenPOWER on IntegriCloud