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"
16 // Other libraries and framework includes
20 xdigit_to_sint (char ch)
22 if (ch >= 'a' && ch <= 'f')
24 if (ch >= 'A' && ch <= 'F')
26 if (ch >= '0' && ch <= '9')
31 //----------------------------------------------------------------------
32 // StringExtractor constructor
33 //----------------------------------------------------------------------
34 StringExtractor::StringExtractor() :
41 StringExtractor::StringExtractor(const char *packet_cstr) :
46 m_packet.assign (packet_cstr);
50 //----------------------------------------------------------------------
51 // StringExtractor copy constructor
52 //----------------------------------------------------------------------
53 StringExtractor::StringExtractor(const StringExtractor& rhs) :
54 m_packet (rhs.m_packet),
60 //----------------------------------------------------------------------
61 // StringExtractor assignment operator
62 //----------------------------------------------------------------------
63 const StringExtractor&
64 StringExtractor::operator=(const StringExtractor& rhs)
68 m_packet = rhs.m_packet;
69 m_index = rhs.m_index;
75 //----------------------------------------------------------------------
77 //----------------------------------------------------------------------
78 StringExtractor::~StringExtractor()
84 StringExtractor::GetChar (char fail_value)
86 if (m_index < m_packet.size())
88 char ch = m_packet[m_index];
96 //----------------------------------------------------------------------
97 // If a pair of valid hex digits exist at the head of the
98 // StringExtractor they are decoded into an unsigned byte and returned
101 // If there is not a pair of valid hex digits at the head of the
102 // StringExtractor, it is left unchanged and -1 is returned
103 //----------------------------------------------------------------------
105 StringExtractor::DecodeHexU8()
108 if (GetBytesLeft() < 2)
112 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
113 const int lo_nibble = xdigit_to_sint(m_packet[m_index+1]);
114 if (hi_nibble == -1 || lo_nibble == -1)
119 return (uint8_t)((hi_nibble << 4) + lo_nibble);
122 //----------------------------------------------------------------------
123 // Extract an unsigned character from two hex ASCII chars in the packet
124 // string, or return fail_value on failure
125 //----------------------------------------------------------------------
127 StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
129 // On success, fail_value will be overwritten with the next
130 // character in the stream
131 GetHexU8Ex(fail_value, set_eof_on_fail);
136 StringExtractor::GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail)
138 int byte = DecodeHexU8();
141 if (set_eof_on_fail || m_index >= m_packet.size())
142 m_index = UINT64_MAX;
143 // ch should not be changed in case of failure
151 StringExtractor::GetU32 (uint32_t fail_value, int base)
153 if (m_index < m_packet.size())
156 const char *start = m_packet.c_str();
157 const char *cstr = start + m_index;
158 uint32_t result = static_cast<uint32_t>(::strtoul (cstr, &end, base));
160 if (end && end != cstr)
162 m_index = end - start;
170 StringExtractor::GetS32 (int32_t fail_value, int base)
172 if (m_index < m_packet.size())
175 const char *start = m_packet.c_str();
176 const char *cstr = start + m_index;
177 int32_t result = static_cast<int32_t>(::strtol (cstr, &end, base));
179 if (end && end != cstr)
181 m_index = end - start;
190 StringExtractor::GetU64 (uint64_t fail_value, int base)
192 if (m_index < m_packet.size())
195 const char *start = m_packet.c_str();
196 const char *cstr = start + m_index;
197 uint64_t result = ::strtoull (cstr, &end, base);
199 if (end && end != cstr)
201 m_index = end - start;
209 StringExtractor::GetS64 (int64_t fail_value, int base)
211 if (m_index < m_packet.size())
214 const char *start = m_packet.c_str();
215 const char *cstr = start + m_index;
216 int64_t result = ::strtoll (cstr, &end, base);
218 if (end && end != cstr)
220 m_index = end - start;
229 StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
232 uint32_t nibble_count = 0;
237 uint32_t shift_amount = 0;
238 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
240 // Make sure we don't exceed the size of a uint32_t...
241 if (nibble_count >= (sizeof(uint32_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]))
252 nibble_lo = xdigit_to_sint (m_packet[m_index]);
254 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
255 result |= ((uint32_t)nibble_lo << shift_amount);
261 result |= ((uint32_t)nibble_hi << shift_amount);
270 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
272 // Make sure we don't exceed the size of a uint32_t...
273 if (nibble_count >= (sizeof(uint32_t) * 2))
275 m_index = UINT64_MAX;
279 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
292 StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
295 uint32_t nibble_count = 0;
300 uint32_t shift_amount = 0;
301 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
303 // Make sure we don't exceed the size of a uint64_t...
304 if (nibble_count >= (sizeof(uint64_t) * 2))
306 m_index = UINT64_MAX;
311 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
313 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
315 nibble_lo = xdigit_to_sint (m_packet[m_index]);
317 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
318 result |= ((uint64_t)nibble_lo << shift_amount);
324 result |= ((uint64_t)nibble_hi << shift_amount);
333 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
335 // Make sure we don't exceed the size of a uint64_t...
336 if (nibble_count >= (sizeof(uint64_t) * 2))
338 m_index = UINT64_MAX;
342 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
355 StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
357 uint8_t *dst = (uint8_t*)dst_void;
358 size_t bytes_extracted = 0;
359 while (bytes_extracted < dst_len && GetBytesLeft ())
361 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
368 for (size_t i = bytes_extracted; i < dst_len; ++i)
369 dst[i] = fail_fill_value;
371 return bytes_extracted;
374 //----------------------------------------------------------------------
375 // Decodes all valid hex encoded bytes at the head of the
376 // StringExtractor, limited by dst_len.
378 // Returns the number of bytes successfully decoded
379 //----------------------------------------------------------------------
381 StringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len)
383 uint8_t *dst = (uint8_t*)dst_void;
384 size_t bytes_extracted = 0;
385 while (bytes_extracted < dst_len)
387 int decode = DecodeHexU8();
392 dst[bytes_extracted++] = (uint8_t)decode;
394 return bytes_extracted;
397 // Consume ASCII hex nibble character pairs until we have decoded byte_size
401 StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
403 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
410 uint32_t shift_amount;
411 for (i = 0, shift_amount = 0;
412 i < byte_size && IsGood();
413 ++i, shift_amount += 8)
415 result |= ((uint64_t)GetHexU8() << shift_amount);
421 for (i = 0; i < byte_size && IsGood(); ++i)
424 result |= GetHexU8();
428 m_index = UINT64_MAX;
433 StringExtractor::GetHexByteString (std::string &str)
437 while ((ch = GetHexU8()) != '\0')
443 StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
447 uint32_t nibble_count = 0;
448 for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
455 StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
460 while ((ch = GetHexU8(0,false)) != '\0')
462 if (Peek() && *Peek() == terminator)
470 StringExtractor::GetNameColonValue (std::string &name, std::string &value)
472 // Read something in the form of NNNN:VVVV; where NNNN is any character
473 // that is not a colon, followed by a ':' character, then a value (one or
474 // more ';' chars), followed by a ';'
475 if (m_index < m_packet.size())
477 const size_t colon_idx = m_packet.find (':', m_index);
478 if (colon_idx != std::string::npos)
480 const size_t semicolon_idx = m_packet.find (';', colon_idx);
481 if (semicolon_idx != std::string::npos)
483 name.assign (m_packet, m_index, colon_idx - m_index);
484 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
485 m_index = semicolon_idx + 1;
490 m_index = UINT64_MAX;
495 StringExtractor::SkipSpaces ()
497 const size_t n = m_packet.size();
498 while (m_index < n && isspace(m_packet[m_index]))