blob: ae92704668fc7992e17ab949fd5ff5b6f07ad992 [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{
107 if (GetBytesLeft() < 2)
108 {
109 return -1;
110 }
111 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
112 const int lo_nibble = xdigit_to_sint(m_packet[m_index+1]);
113 if (hi_nibble == -1 || lo_nibble == -1)
114 {
115 return -1;
116 }
117 m_index += 2;
118 return (uint8_t)((hi_nibble << 4) + lo_nibble);
119}
120
121//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24122// Extract an unsigned character from two hex ASCII chars in the packet
Dawn Perchik5e8115b2015-09-25 18:23:50123// string, or return fail_value on failure
Chris Lattner30fdc8d2010-06-08 16:52:24124//----------------------------------------------------------------------
125uint8_t
Greg Clayton7b70be32012-04-07 00:42:53126StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
Chris Lattner30fdc8d2010-06-08 16:52:24127{
Dawn Perchik5e8115b2015-09-25 18:23:50128 // On success, fail_value will be overwritten with the next
129 // character in the stream
Dawn Perchik554a8572015-09-17 17:55:32130 GetHexU8Ex(fail_value, set_eof_on_fail);
131 return fail_value;
132}
133
134bool
135StringExtractor::GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail)
136{
Vince Harron6eddf8d2014-12-01 22:19:33137 int byte = DecodeHexU8();
138 if (byte == -1)
Chris Lattner30fdc8d2010-06-08 16:52:24139 {
Vince Harron6eddf8d2014-12-01 22:19:33140 if (set_eof_on_fail || m_index >= m_packet.size())
141 m_index = UINT64_MAX;
Dawn Perchik554a8572015-09-17 17:55:32142 // ch should not be changed in case of failure
143 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24144 }
Dawn Perchik554a8572015-09-17 17:55:32145 ch = (uint8_t)byte;
146 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24147}
148
149uint32_t
Greg Clayton32e0a752011-03-30 18:16:51150StringExtractor::GetU32 (uint32_t fail_value, int base)
151{
152 if (m_index < m_packet.size())
153 {
Ed Masted4612ad2014-04-20 13:17:36154 char *end = nullptr;
Greg Clayton32e0a752011-03-30 18:16:51155 const char *start = m_packet.c_str();
Daniel Maleae0f8f572013-08-26 23:57:52156 const char *cstr = start + m_index;
Enrico Granataf2d44ca82015-03-13 00:31:45157 uint32_t result = static_cast<uint32_t>(::strtoul (cstr, &end, base));
Greg Clayton32e0a752011-03-30 18:16:51158
Daniel Maleae0f8f572013-08-26 23:57:52159 if (end && end != cstr)
160 {
161 m_index = end - start;
162 return result;
163 }
164 }
165 return fail_value;
166}
167
168int32_t
169StringExtractor::GetS32 (int32_t fail_value, int base)
170{
171 if (m_index < m_packet.size())
172 {
Ed Masted4612ad2014-04-20 13:17:36173 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52174 const char *start = m_packet.c_str();
175 const char *cstr = start + m_index;
Enrico Granataf2d44ca82015-03-13 00:31:45176 int32_t result = static_cast<int32_t>(::strtol (cstr, &end, base));
Daniel Maleae0f8f572013-08-26 23:57:52177
178 if (end && end != cstr)
179 {
180 m_index = end - start;
181 return result;
182 }
183 }
184 return fail_value;
185}
186
187
188uint64_t
189StringExtractor::GetU64 (uint64_t fail_value, int base)
190{
191 if (m_index < m_packet.size())
192 {
Ed Masted4612ad2014-04-20 13:17:36193 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52194 const char *start = m_packet.c_str();
195 const char *cstr = start + m_index;
196 uint64_t result = ::strtoull (cstr, &end, base);
197
198 if (end && end != cstr)
199 {
200 m_index = end - start;
201 return result;
202 }
203 }
204 return fail_value;
205}
206
207int64_t
208StringExtractor::GetS64 (int64_t fail_value, int base)
209{
210 if (m_index < m_packet.size())
211 {
Ed Masted4612ad2014-04-20 13:17:36212 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52213 const char *start = m_packet.c_str();
214 const char *cstr = start + m_index;
215 int64_t result = ::strtoll (cstr, &end, base);
216
217 if (end && end != cstr)
Greg Clayton32e0a752011-03-30 18:16:51218 {
219 m_index = end - start;
220 return result;
221 }
222 }
223 return fail_value;
224}
225
226
227uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24228StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
229{
230 uint32_t result = 0;
231 uint32_t nibble_count = 0;
232
233 if (little_endian)
234 {
235 uint32_t shift_amount = 0;
236 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
237 {
238 // Make sure we don't exceed the size of a uint32_t...
239 if (nibble_count >= (sizeof(uint32_t) * 2))
240 {
Greg Claytonc7bece562013-01-25 18:06:21241 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24242 return fail_value;
243 }
244
245 uint8_t nibble_lo;
246 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
247 ++m_index;
248 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
249 {
250 nibble_lo = xdigit_to_sint (m_packet[m_index]);
251 ++m_index;
252 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
253 result |= ((uint32_t)nibble_lo << shift_amount);
254 nibble_count += 2;
255 shift_amount += 8;
256 }
257 else
258 {
259 result |= ((uint32_t)nibble_hi << shift_amount);
260 nibble_count += 1;
261 shift_amount += 4;
262 }
263
264 }
265 }
266 else
267 {
268 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
269 {
270 // Make sure we don't exceed the size of a uint32_t...
271 if (nibble_count >= (sizeof(uint32_t) * 2))
272 {
Greg Claytonc7bece562013-01-25 18:06:21273 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24274 return fail_value;
275 }
276
277 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
278 // Big Endian
279 result <<= 4;
280 result |= nibble;
281
282 ++m_index;
283 ++nibble_count;
284 }
285 }
286 return result;
287}
288
289uint64_t
290StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
291{
292 uint64_t result = 0;
293 uint32_t nibble_count = 0;
294
295 if (little_endian)
296 {
297 uint32_t shift_amount = 0;
298 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
299 {
300 // Make sure we don't exceed the size of a uint64_t...
301 if (nibble_count >= (sizeof(uint64_t) * 2))
302 {
Greg Claytonc7bece562013-01-25 18:06:21303 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24304 return fail_value;
305 }
306
307 uint8_t nibble_lo;
308 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
309 ++m_index;
310 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
311 {
312 nibble_lo = xdigit_to_sint (m_packet[m_index]);
313 ++m_index;
314 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
315 result |= ((uint64_t)nibble_lo << shift_amount);
316 nibble_count += 2;
317 shift_amount += 8;
318 }
319 else
320 {
321 result |= ((uint64_t)nibble_hi << shift_amount);
322 nibble_count += 1;
323 shift_amount += 4;
324 }
325
326 }
327 }
328 else
329 {
330 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
331 {
332 // Make sure we don't exceed the size of a uint64_t...
333 if (nibble_count >= (sizeof(uint64_t) * 2))
334 {
Greg Claytonc7bece562013-01-25 18:06:21335 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24336 return fail_value;
337 }
338
339 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
340 // Big Endian
341 result <<= 4;
342 result |= nibble;
343
344 ++m_index;
345 ++nibble_count;
346 }
347 }
348 return result;
349}
350
351size_t
352StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
353{
354 uint8_t *dst = (uint8_t*)dst_void;
355 size_t bytes_extracted = 0;
356 while (bytes_extracted < dst_len && GetBytesLeft ())
357 {
358 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
359 if (IsGood())
360 ++bytes_extracted;
361 else
362 break;
363 }
364
365 for (size_t i = bytes_extracted; i < dst_len; ++i)
366 dst[i] = fail_fill_value;
367
368 return bytes_extracted;
369}
370
Vince Harron6eddf8d2014-12-01 22:19:33371//----------------------------------------------------------------------
372// Decodes all valid hex encoded bytes at the head of the
373// StringExtractor, limited by dst_len.
374//
375// Returns the number of bytes successfully decoded
376//----------------------------------------------------------------------
377size_t
378StringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len)
379{
380 uint8_t *dst = (uint8_t*)dst_void;
381 size_t bytes_extracted = 0;
382 while (bytes_extracted < dst_len)
383 {
384 int decode = DecodeHexU8();
385 if (decode == -1)
386 {
387 break;
388 }
389 dst[bytes_extracted++] = (uint8_t)decode;
390 }
391 return bytes_extracted;
392}
Chris Lattner30fdc8d2010-06-08 16:52:24393
394// Consume ASCII hex nibble character pairs until we have decoded byte_size
395// bytes of data.
396
397uint64_t
398StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
399{
400 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
401 {
402 uint64_t result = 0;
403 uint32_t i;
404 if (little_endian)
405 {
406 // Little Endian
407 uint32_t shift_amount;
408 for (i = 0, shift_amount = 0;
Greg Claytonc7bece562013-01-25 18:06:21409 i < byte_size && IsGood();
Chris Lattner30fdc8d2010-06-08 16:52:24410 ++i, shift_amount += 8)
411 {
412 result |= ((uint64_t)GetHexU8() << shift_amount);
413 }
414 }
415 else
416 {
417 // Big Endian
Greg Claytonc7bece562013-01-25 18:06:21418 for (i = 0; i < byte_size && IsGood(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24419 {
420 result <<= 8;
421 result |= GetHexU8();
422 }
423 }
424 }
Greg Claytonc7bece562013-01-25 18:06:21425 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24426 return fail_value;
427}
428
Greg Claytonde9d0492011-01-08 03:17:57429size_t
430StringExtractor::GetHexByteString (std::string &str)
431{
432 str.clear();
433 char ch;
434 while ((ch = GetHexU8()) != '\0')
435 str.append(1, ch);
436 return str.size();
437}
438
Daniel Maleae0f8f572013-08-26 23:57:52439size_t
Todd Fialaaf245d12014-06-30 21:05:18440StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
441{
442 str.clear();
443
444 uint32_t nibble_count = 0;
445 for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
446 {}
447
448 return str.size();
449}
450
451size_t
Daniel Maleae0f8f572013-08-26 23:57:52452StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
453 char terminator)
454{
455 str.clear();
456 char ch;
457 while ((ch = GetHexU8(0,false)) != '\0')
458 str.append(1, ch);
459 if (Peek() && *Peek() == terminator)
460 return str.size();
Todd Fialaaf245d12014-06-30 21:05:18461
Daniel Maleae0f8f572013-08-26 23:57:52462 str.clear();
463 return str.size();
464}
465
Chris Lattner30fdc8d2010-06-08 16:52:24466bool
467StringExtractor::GetNameColonValue (std::string &name, std::string &value)
468{
469 // Read something in the form of NNNN:VVVV; where NNNN is any character
470 // that is not a colon, followed by a ':' character, then a value (one or
471 // more ';' chars), followed by a ';'
472 if (m_index < m_packet.size())
473 {
474 const size_t colon_idx = m_packet.find (':', m_index);
475 if (colon_idx != std::string::npos)
476 {
477 const size_t semicolon_idx = m_packet.find (';', colon_idx);
478 if (semicolon_idx != std::string::npos)
479 {
480 name.assign (m_packet, m_index, colon_idx - m_index);
481 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
482 m_index = semicolon_idx + 1;
483 return true;
484 }
485 }
486 }
Greg Claytonc7bece562013-01-25 18:06:21487 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24488 return false;
489}
Greg Clayton98424c42015-07-06 23:40:40490
491void
492StringExtractor::SkipSpaces ()
493{
494 const size_t n = m_packet.size();
495 while (m_index < n && isspace(m_packet[m_index]))
496 ++m_index;
497}
498