blob: e135531d6a4a3310d860cf1125b6e67519733411 [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
123// string
124//----------------------------------------------------------------------
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 Perchik554a8572015-09-17 17:55:32128 GetHexU8Ex(fail_value, set_eof_on_fail);
129 return fail_value;
130}
131
132bool
133StringExtractor::GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail)
134{
Vince Harron6eddf8d2014-12-01 22:19:33135 int byte = DecodeHexU8();
136 if (byte == -1)
Chris Lattner30fdc8d2010-06-08 16:52:24137 {
Vince Harron6eddf8d2014-12-01 22:19:33138 if (set_eof_on_fail || m_index >= m_packet.size())
139 m_index = UINT64_MAX;
Dawn Perchik554a8572015-09-17 17:55:32140 // ch should not be changed in case of failure
141 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24142 }
Dawn Perchik554a8572015-09-17 17:55:32143 ch = (uint8_t)byte;
144 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24145}
146
147uint32_t
Greg Clayton32e0a752011-03-30 18:16:51148StringExtractor::GetU32 (uint32_t fail_value, int base)
149{
150 if (m_index < m_packet.size())
151 {
Ed Masted4612ad2014-04-20 13:17:36152 char *end = nullptr;
Greg Clayton32e0a752011-03-30 18:16:51153 const char *start = m_packet.c_str();
Daniel Maleae0f8f572013-08-26 23:57:52154 const char *cstr = start + m_index;
Enrico Granataf2d44ca82015-03-13 00:31:45155 uint32_t result = static_cast<uint32_t>(::strtoul (cstr, &end, base));
Greg Clayton32e0a752011-03-30 18:16:51156
Daniel Maleae0f8f572013-08-26 23:57:52157 if (end && end != cstr)
158 {
159 m_index = end - start;
160 return result;
161 }
162 }
163 return fail_value;
164}
165
166int32_t
167StringExtractor::GetS32 (int32_t fail_value, int base)
168{
169 if (m_index < m_packet.size())
170 {
Ed Masted4612ad2014-04-20 13:17:36171 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52172 const char *start = m_packet.c_str();
173 const char *cstr = start + m_index;
Enrico Granataf2d44ca82015-03-13 00:31:45174 int32_t result = static_cast<int32_t>(::strtol (cstr, &end, base));
Daniel Maleae0f8f572013-08-26 23:57:52175
176 if (end && end != cstr)
177 {
178 m_index = end - start;
179 return result;
180 }
181 }
182 return fail_value;
183}
184
185
186uint64_t
187StringExtractor::GetU64 (uint64_t fail_value, int base)
188{
189 if (m_index < m_packet.size())
190 {
Ed Masted4612ad2014-04-20 13:17:36191 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52192 const char *start = m_packet.c_str();
193 const char *cstr = start + m_index;
194 uint64_t result = ::strtoull (cstr, &end, base);
195
196 if (end && end != cstr)
197 {
198 m_index = end - start;
199 return result;
200 }
201 }
202 return fail_value;
203}
204
205int64_t
206StringExtractor::GetS64 (int64_t fail_value, int base)
207{
208 if (m_index < m_packet.size())
209 {
Ed Masted4612ad2014-04-20 13:17:36210 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52211 const char *start = m_packet.c_str();
212 const char *cstr = start + m_index;
213 int64_t result = ::strtoll (cstr, &end, base);
214
215 if (end && end != cstr)
Greg Clayton32e0a752011-03-30 18:16:51216 {
217 m_index = end - start;
218 return result;
219 }
220 }
221 return fail_value;
222}
223
224
225uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24226StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
227{
228 uint32_t result = 0;
229 uint32_t nibble_count = 0;
230
231 if (little_endian)
232 {
233 uint32_t shift_amount = 0;
234 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
235 {
236 // Make sure we don't exceed the size of a uint32_t...
237 if (nibble_count >= (sizeof(uint32_t) * 2))
238 {
Greg Claytonc7bece562013-01-25 18:06:21239 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24240 return fail_value;
241 }
242
243 uint8_t nibble_lo;
244 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
245 ++m_index;
246 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
247 {
248 nibble_lo = xdigit_to_sint (m_packet[m_index]);
249 ++m_index;
250 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
251 result |= ((uint32_t)nibble_lo << shift_amount);
252 nibble_count += 2;
253 shift_amount += 8;
254 }
255 else
256 {
257 result |= ((uint32_t)nibble_hi << shift_amount);
258 nibble_count += 1;
259 shift_amount += 4;
260 }
261
262 }
263 }
264 else
265 {
266 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
267 {
268 // Make sure we don't exceed the size of a uint32_t...
269 if (nibble_count >= (sizeof(uint32_t) * 2))
270 {
Greg Claytonc7bece562013-01-25 18:06:21271 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24272 return fail_value;
273 }
274
275 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
276 // Big Endian
277 result <<= 4;
278 result |= nibble;
279
280 ++m_index;
281 ++nibble_count;
282 }
283 }
284 return result;
285}
286
287uint64_t
288StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
289{
290 uint64_t result = 0;
291 uint32_t nibble_count = 0;
292
293 if (little_endian)
294 {
295 uint32_t shift_amount = 0;
296 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
297 {
298 // Make sure we don't exceed the size of a uint64_t...
299 if (nibble_count >= (sizeof(uint64_t) * 2))
300 {
Greg Claytonc7bece562013-01-25 18:06:21301 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24302 return fail_value;
303 }
304
305 uint8_t nibble_lo;
306 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
307 ++m_index;
308 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
309 {
310 nibble_lo = xdigit_to_sint (m_packet[m_index]);
311 ++m_index;
312 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
313 result |= ((uint64_t)nibble_lo << shift_amount);
314 nibble_count += 2;
315 shift_amount += 8;
316 }
317 else
318 {
319 result |= ((uint64_t)nibble_hi << shift_amount);
320 nibble_count += 1;
321 shift_amount += 4;
322 }
323
324 }
325 }
326 else
327 {
328 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
329 {
330 // Make sure we don't exceed the size of a uint64_t...
331 if (nibble_count >= (sizeof(uint64_t) * 2))
332 {
Greg Claytonc7bece562013-01-25 18:06:21333 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24334 return fail_value;
335 }
336
337 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
338 // Big Endian
339 result <<= 4;
340 result |= nibble;
341
342 ++m_index;
343 ++nibble_count;
344 }
345 }
346 return result;
347}
348
349size_t
350StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
351{
352 uint8_t *dst = (uint8_t*)dst_void;
353 size_t bytes_extracted = 0;
354 while (bytes_extracted < dst_len && GetBytesLeft ())
355 {
356 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
357 if (IsGood())
358 ++bytes_extracted;
359 else
360 break;
361 }
362
363 for (size_t i = bytes_extracted; i < dst_len; ++i)
364 dst[i] = fail_fill_value;
365
366 return bytes_extracted;
367}
368
Vince Harron6eddf8d2014-12-01 22:19:33369//----------------------------------------------------------------------
370// Decodes all valid hex encoded bytes at the head of the
371// StringExtractor, limited by dst_len.
372//
373// Returns the number of bytes successfully decoded
374//----------------------------------------------------------------------
375size_t
376StringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len)
377{
378 uint8_t *dst = (uint8_t*)dst_void;
379 size_t bytes_extracted = 0;
380 while (bytes_extracted < dst_len)
381 {
382 int decode = DecodeHexU8();
383 if (decode == -1)
384 {
385 break;
386 }
387 dst[bytes_extracted++] = (uint8_t)decode;
388 }
389 return bytes_extracted;
390}
Chris Lattner30fdc8d2010-06-08 16:52:24391
392// Consume ASCII hex nibble character pairs until we have decoded byte_size
393// bytes of data.
394
395uint64_t
396StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
397{
398 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
399 {
400 uint64_t result = 0;
401 uint32_t i;
402 if (little_endian)
403 {
404 // Little Endian
405 uint32_t shift_amount;
406 for (i = 0, shift_amount = 0;
Greg Claytonc7bece562013-01-25 18:06:21407 i < byte_size && IsGood();
Chris Lattner30fdc8d2010-06-08 16:52:24408 ++i, shift_amount += 8)
409 {
410 result |= ((uint64_t)GetHexU8() << shift_amount);
411 }
412 }
413 else
414 {
415 // Big Endian
Greg Claytonc7bece562013-01-25 18:06:21416 for (i = 0; i < byte_size && IsGood(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24417 {
418 result <<= 8;
419 result |= GetHexU8();
420 }
421 }
422 }
Greg Claytonc7bece562013-01-25 18:06:21423 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24424 return fail_value;
425}
426
Greg Claytonde9d0492011-01-08 03:17:57427size_t
428StringExtractor::GetHexByteString (std::string &str)
429{
430 str.clear();
431 char ch;
432 while ((ch = GetHexU8()) != '\0')
433 str.append(1, ch);
434 return str.size();
435}
436
Daniel Maleae0f8f572013-08-26 23:57:52437size_t
Todd Fialaaf245d12014-06-30 21:05:18438StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
439{
440 str.clear();
441
442 uint32_t nibble_count = 0;
443 for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
444 {}
445
446 return str.size();
447}
448
449size_t
Daniel Maleae0f8f572013-08-26 23:57:52450StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
451 char terminator)
452{
453 str.clear();
454 char ch;
455 while ((ch = GetHexU8(0,false)) != '\0')
456 str.append(1, ch);
457 if (Peek() && *Peek() == terminator)
458 return str.size();
Todd Fialaaf245d12014-06-30 21:05:18459
Daniel Maleae0f8f572013-08-26 23:57:52460 str.clear();
461 return str.size();
462}
463
Chris Lattner30fdc8d2010-06-08 16:52:24464bool
465StringExtractor::GetNameColonValue (std::string &name, std::string &value)
466{
467 // Read something in the form of NNNN:VVVV; where NNNN is any character
468 // that is not a colon, followed by a ':' character, then a value (one or
469 // more ';' chars), followed by a ';'
470 if (m_index < m_packet.size())
471 {
472 const size_t colon_idx = m_packet.find (':', m_index);
473 if (colon_idx != std::string::npos)
474 {
475 const size_t semicolon_idx = m_packet.find (';', colon_idx);
476 if (semicolon_idx != std::string::npos)
477 {
478 name.assign (m_packet, m_index, colon_idx - m_index);
479 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
480 m_index = semicolon_idx + 1;
481 return true;
482 }
483 }
484 }
Greg Claytonc7bece562013-01-25 18:06:21485 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24486 return false;
487}
Greg Clayton98424c42015-07-06 23:40:40488
489void
490StringExtractor::SkipSpaces ()
491{
492 const size_t n = m_packet.size();
493 while (m_index < n && isspace(m_packet[m_index]))
494 ++m_index;
495}
496