1 //===-- StringExtractor.cpp -------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Utility/StringExtractor.h"
14 #include <ctype.h> // for isxdigit, isspace
16 #include <string.h> // for memset
18 static inline int xdigit_to_sint(char ch) {
19 if (ch >= 'a' && ch <= 'f')
21 if (ch >= 'A' && ch <= 'F')
23 if (ch >= '0' && ch <= '9')
28 //----------------------------------------------------------------------
29 // StringExtractor constructor
30 //----------------------------------------------------------------------
31 StringExtractor::StringExtractor() : m_packet(), m_index(0) {}
33 StringExtractor::StringExtractor(llvm::StringRef packet_str)
34 : m_packet(), m_index(0) {
35 m_packet.assign(packet_str.begin(), packet_str.end());
38 StringExtractor::StringExtractor(const char *packet_cstr)
39 : m_packet(), m_index(0) {
41 m_packet.assign(packet_cstr);
44 //----------------------------------------------------------------------
45 // StringExtractor copy constructor
46 //----------------------------------------------------------------------
47 StringExtractor::StringExtractor(const StringExtractor &rhs)
48 : m_packet(rhs.m_packet), m_index(rhs.m_index) {}
50 //----------------------------------------------------------------------
51 // StringExtractor assignment operator
52 //----------------------------------------------------------------------
53 const StringExtractor &StringExtractor::operator=(const StringExtractor &rhs) {
55 m_packet = rhs.m_packet;
56 m_index = rhs.m_index;
61 //----------------------------------------------------------------------
63 //----------------------------------------------------------------------
64 StringExtractor::~StringExtractor() {}
66 char StringExtractor::GetChar(char fail_value) {
67 if (m_index < m_packet.size()) {
68 char ch = m_packet[m_index];
76 //----------------------------------------------------------------------
77 // If a pair of valid hex digits exist at the head of the
78 // StringExtractor they are decoded into an unsigned byte and returned
81 // If there is not a pair of valid hex digits at the head of the
82 // StringExtractor, it is left unchanged and -1 is returned
83 //----------------------------------------------------------------------
84 int StringExtractor::DecodeHexU8() {
86 if (GetBytesLeft() < 2) {
89 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
90 const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
91 if (hi_nibble == -1 || lo_nibble == -1) {
95 return (uint8_t)((hi_nibble << 4) + lo_nibble);
98 //----------------------------------------------------------------------
99 // Extract an unsigned character from two hex ASCII chars in the packet
100 // string, or return fail_value on failure
101 //----------------------------------------------------------------------
102 uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
103 // On success, fail_value will be overwritten with the next
104 // character in the stream
105 GetHexU8Ex(fail_value, set_eof_on_fail);
109 bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
110 int byte = DecodeHexU8();
112 if (set_eof_on_fail || m_index >= m_packet.size())
113 m_index = UINT64_MAX;
114 // ch should not be changed in case of failure
121 uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) {
122 if (m_index < m_packet.size()) {
124 const char *start = m_packet.c_str();
125 const char *cstr = start + m_index;
126 uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
128 if (end && end != cstr) {
129 m_index = end - start;
136 int32_t StringExtractor::GetS32(int32_t fail_value, int base) {
137 if (m_index < m_packet.size()) {
139 const char *start = m_packet.c_str();
140 const char *cstr = start + m_index;
141 int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
143 if (end && end != cstr) {
144 m_index = end - start;
151 uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) {
152 if (m_index < m_packet.size()) {
154 const char *start = m_packet.c_str();
155 const char *cstr = start + m_index;
156 uint64_t result = ::strtoull(cstr, &end, base);
158 if (end && end != cstr) {
159 m_index = end - start;
166 int64_t StringExtractor::GetS64(int64_t fail_value, int base) {
167 if (m_index < m_packet.size()) {
169 const char *start = m_packet.c_str();
170 const char *cstr = start + m_index;
171 int64_t result = ::strtoll(cstr, &end, base);
173 if (end && end != cstr) {
174 m_index = end - start;
181 uint32_t StringExtractor::GetHexMaxU32(bool little_endian,
182 uint32_t fail_value) {
184 uint32_t nibble_count = 0;
188 uint32_t shift_amount = 0;
189 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
190 // Make sure we don't exceed the size of a uint32_t...
191 if (nibble_count >= (sizeof(uint32_t) * 2)) {
192 m_index = UINT64_MAX;
197 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
199 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
200 nibble_lo = xdigit_to_sint(m_packet[m_index]);
202 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
203 result |= ((uint32_t)nibble_lo << shift_amount);
207 result |= ((uint32_t)nibble_hi << shift_amount);
213 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
214 // Make sure we don't exceed the size of a uint32_t...
215 if (nibble_count >= (sizeof(uint32_t) * 2)) {
216 m_index = UINT64_MAX;
220 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
232 uint64_t StringExtractor::GetHexMaxU64(bool little_endian,
233 uint64_t fail_value) {
235 uint32_t nibble_count = 0;
239 uint32_t shift_amount = 0;
240 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
241 // Make sure we don't exceed the size of a uint64_t...
242 if (nibble_count >= (sizeof(uint64_t) * 2)) {
243 m_index = UINT64_MAX;
248 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
250 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
251 nibble_lo = xdigit_to_sint(m_packet[m_index]);
253 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
254 result |= ((uint64_t)nibble_lo << shift_amount);
258 result |= ((uint64_t)nibble_hi << shift_amount);
264 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
265 // Make sure we don't exceed the size of a uint64_t...
266 if (nibble_count >= (sizeof(uint64_t) * 2)) {
267 m_index = UINT64_MAX;
271 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
283 bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
284 llvm::StringRef S = GetStringRef();
285 if (!S.startswith(str))
288 m_index += str.size();
292 size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
293 uint8_t fail_fill_value) {
294 size_t bytes_extracted = 0;
295 while (!dest.empty() && GetBytesLeft() > 0) {
296 dest[0] = GetHexU8(fail_fill_value);
300 dest = dest.drop_front();
304 ::memset(dest.data(), fail_fill_value, dest.size());
306 return bytes_extracted;
309 //----------------------------------------------------------------------
310 // Decodes all valid hex encoded bytes at the head of the
311 // StringExtractor, limited by dst_len.
313 // Returns the number of bytes successfully decoded
314 //----------------------------------------------------------------------
315 size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) {
316 size_t bytes_extracted = 0;
317 while (!dest.empty()) {
318 int decode = DecodeHexU8();
321 dest[0] = (uint8_t)decode;
322 dest = dest.drop_front();
325 return bytes_extracted;
328 // Consume ASCII hex nibble character pairs until we have decoded byte_size
331 uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size,
333 uint64_t fail_value) {
334 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) {
339 uint32_t shift_amount;
340 for (i = 0, shift_amount = 0; i < byte_size && IsGood();
341 ++i, shift_amount += 8) {
342 result |= ((uint64_t)GetHexU8() << shift_amount);
346 for (i = 0; i < byte_size && IsGood(); ++i) {
348 result |= GetHexU8();
352 m_index = UINT64_MAX;
356 size_t StringExtractor::GetHexByteString(std::string &str) {
358 str.reserve(GetBytesLeft() / 2);
360 while ((ch = GetHexU8()) != '\0')
365 size_t StringExtractor::GetHexByteStringFixedLength(std::string &str,
366 uint32_t nibble_length) {
369 uint32_t nibble_count = 0;
370 for (const char *pch = Peek();
371 (nibble_count < nibble_length) && (pch != nullptr);
372 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
378 size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
382 while ((ch = GetHexU8(0, false)) != '\0')
384 if (Peek() && *Peek() == terminator)
391 bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
392 llvm::StringRef &value) {
393 // Read something in the form of NNNN:VVVV; where NNNN is any character
394 // that is not a colon, followed by a ':' character, then a value (one or
395 // more ';' chars), followed by a ';'
396 if (m_index >= m_packet.size())
399 llvm::StringRef view(m_packet);
403 llvm::StringRef a, b, c, d;
404 view = view.substr(m_index);
405 std::tie(a, b) = view.split(':');
406 if (a.empty() || b.empty())
408 std::tie(c, d) = b.split(';');
409 if (b == c && d.empty())
415 m_index = m_packet.size();
417 size_t bytes_consumed = d.data() - view.data();
418 m_index += bytes_consumed;
423 void StringExtractor::SkipSpaces() {
424 const size_t n = m_packet.size();
425 while (m_index < n && isspace(m_packet[m_index]))