blob: f62c83637003c44b4372fe52a51b3efe79908135 [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
Zachary Turner54695a32016-08-29 19:58:1416#include <tuple>
Chris Lattner30fdc8d2010-06-08 16:52:2417// Other libraries and framework includes
18// Project includes
19
Chris Lattner30fdc8d2010-06-08 16:52:2420static inline int
21xdigit_to_sint (char ch)
22{
Chris Lattner30fdc8d2010-06-08 16:52:2423 if (ch >= 'a' && ch <= 'f')
24 return 10 + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:0525 if (ch >= 'A' && ch <= 'F')
26 return 10 + ch - 'A';
Vince Harron6eddf8d2014-12-01 22:19:3327 if (ch >= '0' && ch <= '9')
28 return ch - '0';
29 return -1;
Chris Lattner30fdc8d2010-06-08 16:52:2430}
31
Chris Lattner30fdc8d2010-06-08 16:52:2432//----------------------------------------------------------------------
33// StringExtractor constructor
34//----------------------------------------------------------------------
35StringExtractor::StringExtractor() :
36 m_packet(),
37 m_index (0)
38{
39}
40
Zachary Turner54695a32016-08-29 19:58:1441StringExtractor::StringExtractor(llvm::StringRef packet_str) : m_packet(), m_index(0)
42{
43 m_packet.assign(packet_str.begin(), packet_str.end());
44}
Chris Lattner30fdc8d2010-06-08 16:52:2445
46StringExtractor::StringExtractor(const char *packet_cstr) :
47 m_packet(),
48 m_index (0)
49{
50 if (packet_cstr)
51 m_packet.assign (packet_cstr);
52}
53
54
55//----------------------------------------------------------------------
56// StringExtractor copy constructor
57//----------------------------------------------------------------------
58StringExtractor::StringExtractor(const StringExtractor& rhs) :
59 m_packet (rhs.m_packet),
60 m_index (rhs.m_index)
61{
62
63}
64
65//----------------------------------------------------------------------
66// StringExtractor assignment operator
67//----------------------------------------------------------------------
68const StringExtractor&
69StringExtractor::operator=(const StringExtractor& rhs)
70{
71 if (this != &rhs)
72 {
73 m_packet = rhs.m_packet;
74 m_index = rhs.m_index;
75
76 }
77 return *this;
78}
79
80//----------------------------------------------------------------------
81// Destructor
82//----------------------------------------------------------------------
83StringExtractor::~StringExtractor()
84{
85}
86
87
88char
89StringExtractor::GetChar (char fail_value)
90{
91 if (m_index < m_packet.size())
92 {
93 char ch = m_packet[m_index];
94 ++m_index;
95 return ch;
96 }
Greg Claytonc7bece562013-01-25 18:06:2197 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:2498 return fail_value;
99}
100
Chris Lattner30fdc8d2010-06-08 16:52:24101//----------------------------------------------------------------------
Vince Harron6eddf8d2014-12-01 22:19:33102// If a pair of valid hex digits exist at the head of the
103// StringExtractor they are decoded into an unsigned byte and returned
104// by this function
105//
106// If there is not a pair of valid hex digits at the head of the
107// StringExtractor, it is left unchanged and -1 is returned
108//----------------------------------------------------------------------
109int
110StringExtractor::DecodeHexU8()
111{
Francis Ricci15a21652016-05-24 18:19:45112 SkipSpaces();
Vince Harron6eddf8d2014-12-01 22:19:33113 if (GetBytesLeft() < 2)
Pavel Labathb9739d42016-08-31 08:43:37114 {
Vince Harron6eddf8d2014-12-01 22:19:33115 return -1;
Pavel Labathb9739d42016-08-31 08:43:37116 }
117 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
118 const int lo_nibble = xdigit_to_sint(m_packet[m_index+1]);
119 if (hi_nibble == -1 || lo_nibble == -1)
120 {
Vince Harron6eddf8d2014-12-01 22:19:33121 return -1;
Pavel Labathb9739d42016-08-31 08:43:37122 }
Vince Harron6eddf8d2014-12-01 22:19:33123 m_index += 2;
Pavel Labathb9739d42016-08-31 08:43:37124 return (uint8_t)((hi_nibble << 4) + lo_nibble);
Vince Harron6eddf8d2014-12-01 22:19:33125}
126
127//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24128// Extract an unsigned character from two hex ASCII chars in the packet
Dawn Perchik5e8115b2015-09-25 18:23:50129// string, or return fail_value on failure
Chris Lattner30fdc8d2010-06-08 16:52:24130//----------------------------------------------------------------------
131uint8_t
Greg Clayton7b70be32012-04-07 00:42:53132StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
Chris Lattner30fdc8d2010-06-08 16:52:24133{
Dawn Perchik5e8115b2015-09-25 18:23:50134 // On success, fail_value will be overwritten with the next
135 // character in the stream
Dawn Perchik554a8572015-09-17 17:55:32136 GetHexU8Ex(fail_value, set_eof_on_fail);
137 return fail_value;
138}
139
140bool
141StringExtractor::GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail)
142{
Vince Harron6eddf8d2014-12-01 22:19:33143 int byte = DecodeHexU8();
144 if (byte == -1)
Chris Lattner30fdc8d2010-06-08 16:52:24145 {
Vince Harron6eddf8d2014-12-01 22:19:33146 if (set_eof_on_fail || m_index >= m_packet.size())
147 m_index = UINT64_MAX;
Dawn Perchik554a8572015-09-17 17:55:32148 // ch should not be changed in case of failure
149 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24150 }
Dawn Perchik554a8572015-09-17 17:55:32151 ch = (uint8_t)byte;
152 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24153}
154
155uint32_t
Greg Clayton32e0a752011-03-30 18:16:51156StringExtractor::GetU32 (uint32_t fail_value, int base)
157{
158 if (m_index < m_packet.size())
159 {
Ed Masted4612ad2014-04-20 13:17:36160 char *end = nullptr;
Greg Clayton32e0a752011-03-30 18:16:51161 const char *start = m_packet.c_str();
Daniel Maleae0f8f572013-08-26 23:57:52162 const char *cstr = start + m_index;
Enrico Granataf2d44ca82015-03-13 00:31:45163 uint32_t result = static_cast<uint32_t>(::strtoul (cstr, &end, base));
Greg Clayton32e0a752011-03-30 18:16:51164
Daniel Maleae0f8f572013-08-26 23:57:52165 if (end && end != cstr)
166 {
167 m_index = end - start;
168 return result;
169 }
170 }
171 return fail_value;
172}
173
174int32_t
175StringExtractor::GetS32 (int32_t fail_value, int base)
176{
177 if (m_index < m_packet.size())
178 {
Ed Masted4612ad2014-04-20 13:17:36179 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52180 const char *start = m_packet.c_str();
181 const char *cstr = start + m_index;
Enrico Granataf2d44ca82015-03-13 00:31:45182 int32_t result = static_cast<int32_t>(::strtol (cstr, &end, base));
Daniel Maleae0f8f572013-08-26 23:57:52183
184 if (end && end != cstr)
185 {
186 m_index = end - start;
187 return result;
188 }
189 }
190 return fail_value;
191}
192
193
194uint64_t
195StringExtractor::GetU64 (uint64_t fail_value, int base)
196{
197 if (m_index < m_packet.size())
198 {
Ed Masted4612ad2014-04-20 13:17:36199 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52200 const char *start = m_packet.c_str();
201 const char *cstr = start + m_index;
202 uint64_t result = ::strtoull (cstr, &end, base);
203
204 if (end && end != cstr)
205 {
206 m_index = end - start;
207 return result;
208 }
209 }
210 return fail_value;
211}
212
213int64_t
214StringExtractor::GetS64 (int64_t fail_value, int base)
215{
216 if (m_index < m_packet.size())
217 {
Ed Masted4612ad2014-04-20 13:17:36218 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52219 const char *start = m_packet.c_str();
220 const char *cstr = start + m_index;
221 int64_t result = ::strtoll (cstr, &end, base);
222
223 if (end && end != cstr)
Greg Clayton32e0a752011-03-30 18:16:51224 {
225 m_index = end - start;
226 return result;
227 }
228 }
229 return fail_value;
230}
231
Pavel Labathb9739d42016-08-31 08:43:37232
Greg Clayton32e0a752011-03-30 18:16:51233uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24234StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
235{
Pavel Labathb9739d42016-08-31 08:43:37236 uint32_t result = 0;
237 uint32_t nibble_count = 0;
238
Francis Ricci15a21652016-05-24 18:19:45239 SkipSpaces();
Chris Lattner30fdc8d2010-06-08 16:52:24240 if (little_endian)
Pavel Labathb9739d42016-08-31 08:43:37241 {
242 uint32_t shift_amount = 0;
243 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
244 {
245 // Make sure we don't exceed the size of a uint32_t...
246 if (nibble_count >= (sizeof(uint32_t) * 2))
247 {
248 m_index = UINT64_MAX;
249 return fail_value;
250 }
251
252 uint8_t nibble_lo;
253 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
254 ++m_index;
255 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
256 {
257 nibble_lo = xdigit_to_sint (m_packet[m_index]);
258 ++m_index;
259 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
260 result |= ((uint32_t)nibble_lo << shift_amount);
261 nibble_count += 2;
262 shift_amount += 8;
263 }
264 else
265 {
266 result |= ((uint32_t)nibble_hi << shift_amount);
267 nibble_count += 1;
268 shift_amount += 4;
269 }
270
271 }
272 }
Chris Lattner30fdc8d2010-06-08 16:52:24273 else
274 {
Pavel Labathb9739d42016-08-31 08:43:37275 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
276 {
277 // Make sure we don't exceed the size of a uint32_t...
278 if (nibble_count >= (sizeof(uint32_t) * 2))
279 {
280 m_index = UINT64_MAX;
281 return fail_value;
282 }
283
284 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
285 // Big Endian
286 result <<= 4;
287 result |= nibble;
288
289 ++m_index;
290 ++nibble_count;
291 }
Chris Lattner30fdc8d2010-06-08 16:52:24292 }
Pavel Labathb9739d42016-08-31 08:43:37293 return result;
Chris Lattner30fdc8d2010-06-08 16:52:24294}
295
296uint64_t
297StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
298{
Pavel Labathb9739d42016-08-31 08:43:37299 uint64_t result = 0;
300 uint32_t nibble_count = 0;
301
Francis Ricci15a21652016-05-24 18:19:45302 SkipSpaces();
Chris Lattner30fdc8d2010-06-08 16:52:24303 if (little_endian)
Pavel Labathb9739d42016-08-31 08:43:37304 {
305 uint32_t shift_amount = 0;
306 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
307 {
308 // Make sure we don't exceed the size of a uint64_t...
309 if (nibble_count >= (sizeof(uint64_t) * 2))
310 {
311 m_index = UINT64_MAX;
312 return fail_value;
313 }
314
315 uint8_t nibble_lo;
316 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
317 ++m_index;
318 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
319 {
320 nibble_lo = xdigit_to_sint (m_packet[m_index]);
321 ++m_index;
322 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
323 result |= ((uint64_t)nibble_lo << shift_amount);
324 nibble_count += 2;
325 shift_amount += 8;
326 }
327 else
328 {
329 result |= ((uint64_t)nibble_hi << shift_amount);
330 nibble_count += 1;
331 shift_amount += 4;
332 }
333
334 }
335 }
Chris Lattner30fdc8d2010-06-08 16:52:24336 else
337 {
Pavel Labathb9739d42016-08-31 08:43:37338 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
339 {
340 // Make sure we don't exceed the size of a uint64_t...
341 if (nibble_count >= (sizeof(uint64_t) * 2))
342 {
343 m_index = UINT64_MAX;
344 return fail_value;
345 }
346
347 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
348 // Big Endian
349 result <<= 4;
350 result |= nibble;
351
352 ++m_index;
353 ++nibble_count;
354 }
Chris Lattner30fdc8d2010-06-08 16:52:24355 }
Pavel Labathb9739d42016-08-31 08:43:37356 return result;
Chris Lattner30fdc8d2010-06-08 16:52:24357}
358
359size_t
Zachary Turnerd08f09c2016-08-30 18:12:11360StringExtractor::GetHexBytes (llvm::MutableArrayRef<uint8_t> dest, uint8_t fail_fill_value)
Chris Lattner30fdc8d2010-06-08 16:52:24361{
Chris Lattner30fdc8d2010-06-08 16:52:24362 size_t bytes_extracted = 0;
Zachary Turnerd08f09c2016-08-30 18:12:11363 while (!dest.empty() && GetBytesLeft() > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24364 {
Zachary Turnerd08f09c2016-08-30 18:12:11365 dest[0] = GetHexU8 (fail_fill_value);
366 if (!IsGood())
Chris Lattner30fdc8d2010-06-08 16:52:24367 break;
Zachary Turnerd08f09c2016-08-30 18:12:11368 ++bytes_extracted;
369 dest = dest.drop_front();
Chris Lattner30fdc8d2010-06-08 16:52:24370 }
371
Zachary Turnerd08f09c2016-08-30 18:12:11372 if (!dest.empty())
373 ::memset(dest.data(), fail_fill_value, dest.size());
Chris Lattner30fdc8d2010-06-08 16:52:24374
375 return bytes_extracted;
376}
377
Vince Harron6eddf8d2014-12-01 22:19:33378//----------------------------------------------------------------------
379// Decodes all valid hex encoded bytes at the head of the
380// StringExtractor, limited by dst_len.
381//
382// Returns the number of bytes successfully decoded
383//----------------------------------------------------------------------
384size_t
Zachary Turnerd08f09c2016-08-30 18:12:11385StringExtractor::GetHexBytesAvail (llvm::MutableArrayRef<uint8_t> dest)
Vince Harron6eddf8d2014-12-01 22:19:33386{
Vince Harron6eddf8d2014-12-01 22:19:33387 size_t bytes_extracted = 0;
Zachary Turnerd08f09c2016-08-30 18:12:11388 while (!dest.empty())
Vince Harron6eddf8d2014-12-01 22:19:33389 {
390 int decode = DecodeHexU8();
391 if (decode == -1)
Vince Harron6eddf8d2014-12-01 22:19:33392 break;
Zachary Turnerd08f09c2016-08-30 18:12:11393 dest[0] = (uint8_t)decode;
394 dest = dest.drop_front();
395 ++bytes_extracted;
Vince Harron6eddf8d2014-12-01 22:19:33396 }
397 return bytes_extracted;
398}
Chris Lattner30fdc8d2010-06-08 16:52:24399
Pavel Labathb9739d42016-08-31 08:43:37400// Consume ASCII hex nibble character pairs until we have decoded byte_size
401// bytes of data.
402
403uint64_t
404StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
405{
406 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
407 {
408 uint64_t result = 0;
409 uint32_t i;
410 if (little_endian)
411 {
412 // Little Endian
413 uint32_t shift_amount;
414 for (i = 0, shift_amount = 0;
415 i < byte_size && IsGood();
416 ++i, shift_amount += 8)
417 {
418 result |= ((uint64_t)GetHexU8() << shift_amount);
419 }
420 }
421 else
422 {
423 // Big Endian
424 for (i = 0; i < byte_size && IsGood(); ++i)
425 {
426 result <<= 8;
427 result |= GetHexU8();
428 }
429 }
430 }
431 m_index = UINT64_MAX;
432 return fail_value;
433}
434
Greg Claytonde9d0492011-01-08 03:17:57435size_t
436StringExtractor::GetHexByteString (std::string &str)
437{
438 str.clear();
Pavel Labath8c1b6bd2016-08-09 12:04:46439 str.reserve(GetBytesLeft() / 2);
Greg Claytonde9d0492011-01-08 03:17:57440 char ch;
441 while ((ch = GetHexU8()) != '\0')
442 str.append(1, ch);
443 return str.size();
444}
445
Daniel Maleae0f8f572013-08-26 23:57:52446size_t
Todd Fialaaf245d12014-06-30 21:05:18447StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
448{
449 str.clear();
Pavel Labathb9739d42016-08-31 08:43:37450
451 uint32_t nibble_count = 0;
452 for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
453 {}
454
Todd Fialaaf245d12014-06-30 21:05:18455 return str.size();
456}
457
458size_t
Daniel Maleae0f8f572013-08-26 23:57:52459StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
460 char terminator)
461{
462 str.clear();
463 char ch;
464 while ((ch = GetHexU8(0,false)) != '\0')
465 str.append(1, ch);
Pavel Labathb9739d42016-08-31 08:43:37466 if (Peek() && *Peek() == terminator)
Daniel Maleae0f8f572013-08-26 23:57:52467 return str.size();
Todd Fialaaf245d12014-06-30 21:05:18468
Daniel Maleae0f8f572013-08-26 23:57:52469 str.clear();
470 return str.size();
471}
472
Chris Lattner30fdc8d2010-06-08 16:52:24473bool
Zachary Turner54695a32016-08-29 19:58:14474StringExtractor::GetNameColonValue(llvm::StringRef &name, llvm::StringRef &value)
Chris Lattner30fdc8d2010-06-08 16:52:24475{
476 // Read something in the form of NNNN:VVVV; where NNNN is any character
477 // that is not a colon, followed by a ':' character, then a value (one or
478 // more ';' chars), followed by a ';'
Zachary Turner54695a32016-08-29 19:58:14479 if (m_index >= m_packet.size())
480 return fail();
481
482 llvm::StringRef view(m_packet);
483 if (view.empty())
484 return fail();
485
486 llvm::StringRef a, b, c, d;
487 view = view.substr(m_index);
488 std::tie(a, b) = view.split(':');
489 if (a.empty() || b.empty())
490 return fail();
491 std::tie(c, d) = b.split(';');
492 if (b == c && d.empty())
493 return fail();
494
495 name = a;
496 value = c;
497 if (d.empty())
498 m_index = m_packet.size();
499 else
Chris Lattner30fdc8d2010-06-08 16:52:24500 {
Zachary Turner54695a32016-08-29 19:58:14501 size_t bytes_consumed = d.data() - view.data();
502 m_index += bytes_consumed;
Chris Lattner30fdc8d2010-06-08 16:52:24503 }
Zachary Turner54695a32016-08-29 19:58:14504 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24505}
Greg Clayton98424c42015-07-06 23:40:40506
507void
508StringExtractor::SkipSpaces ()
509{
510 const size_t n = m_packet.size();
511 while (m_index < n && isspace(m_packet[m_index]))
512 ++m_index;
513}
514