blob: e25acabfaf8cf6cb7ce54919b45a5629a61f7571 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:241//===-- StringExtractor.cpp -------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Pavel Labathf805e192015-07-07 10:08:4110#include "lldb/Utility/StringExtractor.h"
Chris Lattner30fdc8d2010-06-08 16:52:2411
12// C Includes
Stephen Wilson78709172011-04-07 10:20:2313#include <stdlib.h>
14
Chris Lattner30fdc8d2010-06-08 16:52:2415// C++ Includes
16// Other libraries and framework includes
17// Project includes
18
Chris Lattner30fdc8d2010-06-08 16:52:2419static inline int
20xdigit_to_sint (char ch)
21{
Chris Lattner30fdc8d2010-06-08 16:52:2422 if (ch >= 'a' && ch <= 'f')
23 return 10 + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:0524 if (ch >= 'A' && ch <= 'F')
25 return 10 + ch - 'A';
Vince Harron6eddf8d2014-12-01 22:19:3326 if (ch >= '0' && ch <= '9')
27 return ch - '0';
28 return -1;
Chris Lattner30fdc8d2010-06-08 16:52:2429}
30
Chris Lattner30fdc8d2010-06-08 16:52:2431//----------------------------------------------------------------------
32// StringExtractor constructor
33//----------------------------------------------------------------------
34StringExtractor::StringExtractor() :
35 m_packet(),
36 m_index (0)
37{
38}
39
40
41StringExtractor::StringExtractor(const char *packet_cstr) :
42 m_packet(),
43 m_index (0)
44{
45 if (packet_cstr)
46 m_packet.assign (packet_cstr);
47}
48
49
50//----------------------------------------------------------------------
51// StringExtractor copy constructor
52//----------------------------------------------------------------------
53StringExtractor::StringExtractor(const StringExtractor& rhs) :
54 m_packet (rhs.m_packet),
55 m_index (rhs.m_index)
56{
57
58}
59
60//----------------------------------------------------------------------
61// StringExtractor assignment operator
62//----------------------------------------------------------------------
63const StringExtractor&
64StringExtractor::operator=(const StringExtractor& rhs)
65{
66 if (this != &rhs)
67 {
68 m_packet = rhs.m_packet;
69 m_index = rhs.m_index;
70
71 }
72 return *this;
73}
74
75//----------------------------------------------------------------------
76// Destructor
77//----------------------------------------------------------------------
78StringExtractor::~StringExtractor()
79{
80}
81
82
83char
84StringExtractor::GetChar (char fail_value)
85{
86 if (m_index < m_packet.size())
87 {
88 char ch = m_packet[m_index];
89 ++m_index;
90 return ch;
91 }
Greg Claytonc7bece562013-01-25 18:06:2192 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:2493 return fail_value;
94}
95
Chris Lattner30fdc8d2010-06-08 16:52:2496//----------------------------------------------------------------------
Vince Harron6eddf8d2014-12-01 22:19:3397// If a pair of valid hex digits exist at the head of the
98// StringExtractor they are decoded into an unsigned byte and returned
99// by this function
100//
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//----------------------------------------------------------------------
104int
105StringExtractor::DecodeHexU8()
106{
Francis Ricci15a21652016-05-24 18:19:45107 SkipSpaces();
Vince Harron6eddf8d2014-12-01 22:19:33108 if (GetBytesLeft() < 2)
109 {
110 return -1;
111 }
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)
115 {
116 return -1;
117 }
118 m_index += 2;
119 return (uint8_t)((hi_nibble << 4) + lo_nibble);
120}
121
122//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24123// Extract an unsigned character from two hex ASCII chars in the packet
Dawn Perchik5e8115b2015-09-25 18:23:50124// string, or return fail_value on failure
Chris Lattner30fdc8d2010-06-08 16:52:24125//----------------------------------------------------------------------
126uint8_t
Greg Clayton7b70be32012-04-07 00:42:53127StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
Chris Lattner30fdc8d2010-06-08 16:52:24128{
Dawn Perchik5e8115b2015-09-25 18:23:50129 // On success, fail_value will be overwritten with the next
130 // character in the stream
Dawn Perchik554a8572015-09-17 17:55:32131 GetHexU8Ex(fail_value, set_eof_on_fail);
132 return fail_value;
133}
134
135bool
136StringExtractor::GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail)
137{
Vince Harron6eddf8d2014-12-01 22:19:33138 int byte = DecodeHexU8();
139 if (byte == -1)
Chris Lattner30fdc8d2010-06-08 16:52:24140 {
Vince Harron6eddf8d2014-12-01 22:19:33141 if (set_eof_on_fail || m_index >= m_packet.size())
142 m_index = UINT64_MAX;
Dawn Perchik554a8572015-09-17 17:55:32143 // ch should not be changed in case of failure
144 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24145 }
Dawn Perchik554a8572015-09-17 17:55:32146 ch = (uint8_t)byte;
147 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24148}
149
150uint32_t
Greg Clayton32e0a752011-03-30 18:16:51151StringExtractor::GetU32 (uint32_t fail_value, int base)
152{
153 if (m_index < m_packet.size())
154 {
Ed Masted4612ad2014-04-20 13:17:36155 char *end = nullptr;
Greg Clayton32e0a752011-03-30 18:16:51156 const char *start = m_packet.c_str();
Daniel Maleae0f8f572013-08-26 23:57:52157 const char *cstr = start + m_index;
Enrico Granataf2d44ca82015-03-13 00:31:45158 uint32_t result = static_cast<uint32_t>(::strtoul (cstr, &end, base));
Greg Clayton32e0a752011-03-30 18:16:51159
Daniel Maleae0f8f572013-08-26 23:57:52160 if (end && end != cstr)
161 {
162 m_index = end - start;
163 return result;
164 }
165 }
166 return fail_value;
167}
168
169int32_t
170StringExtractor::GetS32 (int32_t fail_value, int base)
171{
172 if (m_index < m_packet.size())
173 {
Ed Masted4612ad2014-04-20 13:17:36174 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52175 const char *start = m_packet.c_str();
176 const char *cstr = start + m_index;
Enrico Granataf2d44ca82015-03-13 00:31:45177 int32_t result = static_cast<int32_t>(::strtol (cstr, &end, base));
Daniel Maleae0f8f572013-08-26 23:57:52178
179 if (end && end != cstr)
180 {
181 m_index = end - start;
182 return result;
183 }
184 }
185 return fail_value;
186}
187
188
189uint64_t
190StringExtractor::GetU64 (uint64_t fail_value, int base)
191{
192 if (m_index < m_packet.size())
193 {
Ed Masted4612ad2014-04-20 13:17:36194 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52195 const char *start = m_packet.c_str();
196 const char *cstr = start + m_index;
197 uint64_t result = ::strtoull (cstr, &end, base);
198
199 if (end && end != cstr)
200 {
201 m_index = end - start;
202 return result;
203 }
204 }
205 return fail_value;
206}
207
208int64_t
209StringExtractor::GetS64 (int64_t fail_value, int base)
210{
211 if (m_index < m_packet.size())
212 {
Ed Masted4612ad2014-04-20 13:17:36213 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52214 const char *start = m_packet.c_str();
215 const char *cstr = start + m_index;
216 int64_t result = ::strtoll (cstr, &end, base);
217
218 if (end && end != cstr)
Greg Clayton32e0a752011-03-30 18:16:51219 {
220 m_index = end - start;
221 return result;
222 }
223 }
224 return fail_value;
225}
226
227
228uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24229StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
230{
231 uint32_t result = 0;
232 uint32_t nibble_count = 0;
233
Francis Ricci15a21652016-05-24 18:19:45234 SkipSpaces();
Chris Lattner30fdc8d2010-06-08 16:52:24235 if (little_endian)
236 {
237 uint32_t shift_amount = 0;
238 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
239 {
240 // Make sure we don't exceed the size of a uint32_t...
241 if (nibble_count >= (sizeof(uint32_t) * 2))
242 {
Greg Claytonc7bece562013-01-25 18:06:21243 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24244 return fail_value;
245 }
246
247 uint8_t nibble_lo;
248 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
249 ++m_index;
250 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
251 {
252 nibble_lo = xdigit_to_sint (m_packet[m_index]);
253 ++m_index;
254 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
255 result |= ((uint32_t)nibble_lo << shift_amount);
256 nibble_count += 2;
257 shift_amount += 8;
258 }
259 else
260 {
261 result |= ((uint32_t)nibble_hi << shift_amount);
262 nibble_count += 1;
263 shift_amount += 4;
264 }
265
266 }
267 }
268 else
269 {
270 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
271 {
272 // Make sure we don't exceed the size of a uint32_t...
273 if (nibble_count >= (sizeof(uint32_t) * 2))
274 {
Greg Claytonc7bece562013-01-25 18:06:21275 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24276 return fail_value;
277 }
278
279 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
280 // Big Endian
281 result <<= 4;
282 result |= nibble;
283
284 ++m_index;
285 ++nibble_count;
286 }
287 }
288 return result;
289}
290
291uint64_t
292StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
293{
294 uint64_t result = 0;
295 uint32_t nibble_count = 0;
296
Francis Ricci15a21652016-05-24 18:19:45297 SkipSpaces();
Chris Lattner30fdc8d2010-06-08 16:52:24298 if (little_endian)
299 {
300 uint32_t shift_amount = 0;
301 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
302 {
303 // Make sure we don't exceed the size of a uint64_t...
304 if (nibble_count >= (sizeof(uint64_t) * 2))
305 {
Greg Claytonc7bece562013-01-25 18:06:21306 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24307 return fail_value;
308 }
309
310 uint8_t nibble_lo;
311 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
312 ++m_index;
313 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
314 {
315 nibble_lo = xdigit_to_sint (m_packet[m_index]);
316 ++m_index;
317 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
318 result |= ((uint64_t)nibble_lo << shift_amount);
319 nibble_count += 2;
320 shift_amount += 8;
321 }
322 else
323 {
324 result |= ((uint64_t)nibble_hi << shift_amount);
325 nibble_count += 1;
326 shift_amount += 4;
327 }
328
329 }
330 }
331 else
332 {
333 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
334 {
335 // Make sure we don't exceed the size of a uint64_t...
336 if (nibble_count >= (sizeof(uint64_t) * 2))
337 {
Greg Claytonc7bece562013-01-25 18:06:21338 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24339 return fail_value;
340 }
341
342 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
343 // Big Endian
344 result <<= 4;
345 result |= nibble;
346
347 ++m_index;
348 ++nibble_count;
349 }
350 }
351 return result;
352}
353
354size_t
355StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
356{
357 uint8_t *dst = (uint8_t*)dst_void;
358 size_t bytes_extracted = 0;
359 while (bytes_extracted < dst_len && GetBytesLeft ())
360 {
361 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
362 if (IsGood())
363 ++bytes_extracted;
364 else
365 break;
366 }
367
368 for (size_t i = bytes_extracted; i < dst_len; ++i)
369 dst[i] = fail_fill_value;
370
371 return bytes_extracted;
372}
373
Vince Harron6eddf8d2014-12-01 22:19:33374//----------------------------------------------------------------------
375// Decodes all valid hex encoded bytes at the head of the
376// StringExtractor, limited by dst_len.
377//
378// Returns the number of bytes successfully decoded
379//----------------------------------------------------------------------
380size_t
381StringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len)
382{
383 uint8_t *dst = (uint8_t*)dst_void;
384 size_t bytes_extracted = 0;
385 while (bytes_extracted < dst_len)
386 {
387 int decode = DecodeHexU8();
388 if (decode == -1)
389 {
390 break;
391 }
392 dst[bytes_extracted++] = (uint8_t)decode;
393 }
394 return bytes_extracted;
395}
Chris Lattner30fdc8d2010-06-08 16:52:24396
397// Consume ASCII hex nibble character pairs until we have decoded byte_size
398// bytes of data.
399
400uint64_t
401StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
402{
403 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
404 {
405 uint64_t result = 0;
406 uint32_t i;
407 if (little_endian)
408 {
409 // Little Endian
410 uint32_t shift_amount;
411 for (i = 0, shift_amount = 0;
Greg Claytonc7bece562013-01-25 18:06:21412 i < byte_size && IsGood();
Chris Lattner30fdc8d2010-06-08 16:52:24413 ++i, shift_amount += 8)
414 {
415 result |= ((uint64_t)GetHexU8() << shift_amount);
416 }
417 }
418 else
419 {
420 // Big Endian
Greg Claytonc7bece562013-01-25 18:06:21421 for (i = 0; i < byte_size && IsGood(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24422 {
423 result <<= 8;
424 result |= GetHexU8();
425 }
426 }
427 }
Greg Claytonc7bece562013-01-25 18:06:21428 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24429 return fail_value;
430}
431
Greg Claytonde9d0492011-01-08 03:17:57432size_t
433StringExtractor::GetHexByteString (std::string &str)
434{
435 str.clear();
Pavel Labath8c1b6bd2016-08-09 12:04:46436 str.reserve(GetBytesLeft() / 2);
Greg Claytonde9d0492011-01-08 03:17:57437 char ch;
438 while ((ch = GetHexU8()) != '\0')
439 str.append(1, ch);
440 return str.size();
441}
442
Daniel Maleae0f8f572013-08-26 23:57:52443size_t
Todd Fialaaf245d12014-06-30 21:05:18444StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
445{
446 str.clear();
447
448 uint32_t nibble_count = 0;
449 for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
450 {}
451
452 return str.size();
453}
454
455size_t
Daniel Maleae0f8f572013-08-26 23:57:52456StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
457 char terminator)
458{
459 str.clear();
460 char ch;
461 while ((ch = GetHexU8(0,false)) != '\0')
462 str.append(1, ch);
463 if (Peek() && *Peek() == terminator)
464 return str.size();
Todd Fialaaf245d12014-06-30 21:05:18465
Daniel Maleae0f8f572013-08-26 23:57:52466 str.clear();
467 return str.size();
468}
469
Chris Lattner30fdc8d2010-06-08 16:52:24470bool
471StringExtractor::GetNameColonValue (std::string &name, std::string &value)
472{
473 // Read something in the form of NNNN:VVVV; where NNNN is any character
474 // that is not a colon, followed by a ':' character, then a value (one or
475 // more ';' chars), followed by a ';'
476 if (m_index < m_packet.size())
477 {
478 const size_t colon_idx = m_packet.find (':', m_index);
479 if (colon_idx != std::string::npos)
480 {
481 const size_t semicolon_idx = m_packet.find (';', colon_idx);
482 if (semicolon_idx != std::string::npos)
483 {
484 name.assign (m_packet, m_index, colon_idx - m_index);
485 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
486 m_index = semicolon_idx + 1;
487 return true;
488 }
489 }
490 }
Greg Claytonc7bece562013-01-25 18:06:21491 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24492 return false;
493}
Greg Clayton98424c42015-07-06 23:40:40494
495void
496StringExtractor::SkipSpaces ()
497{
498 const size_t n = m_packet.size();
499 while (m_index < n && isspace(m_packet[m_index]))
500 ++m_index;
501}
502