blob: 744e7d482cb588e6c8c33e9fdae0e9f081e54960 [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)
114 {
115 return -1;
116 }
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 {
121 return -1;
122 }
123 m_index += 2;
124 return (uint8_t)((hi_nibble << 4) + lo_nibble);
125}
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
232
233uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24234StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
235{
236 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)
241 {
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 {
Greg Claytonc7bece562013-01-25 18:06:21248 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24249 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 }
273 else
274 {
275 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 {
Greg Claytonc7bece562013-01-25 18:06:21280 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24281 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 }
292 }
293 return result;
294}
295
296uint64_t
297StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
298{
299 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)
304 {
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 {
Greg Claytonc7bece562013-01-25 18:06:21311 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24312 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 }
336 else
337 {
338 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 {
Greg Claytonc7bece562013-01-25 18:06:21343 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24344 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 }
355 }
356 return result;
357}
358
359size_t
360StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
361{
362 uint8_t *dst = (uint8_t*)dst_void;
363 size_t bytes_extracted = 0;
364 while (bytes_extracted < dst_len && GetBytesLeft ())
365 {
366 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
367 if (IsGood())
368 ++bytes_extracted;
369 else
370 break;
371 }
372
373 for (size_t i = bytes_extracted; i < dst_len; ++i)
374 dst[i] = fail_fill_value;
375
376 return bytes_extracted;
377}
378
Vince Harron6eddf8d2014-12-01 22:19:33379//----------------------------------------------------------------------
380// Decodes all valid hex encoded bytes at the head of the
381// StringExtractor, limited by dst_len.
382//
383// Returns the number of bytes successfully decoded
384//----------------------------------------------------------------------
385size_t
386StringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len)
387{
388 uint8_t *dst = (uint8_t*)dst_void;
389 size_t bytes_extracted = 0;
390 while (bytes_extracted < dst_len)
391 {
392 int decode = DecodeHexU8();
393 if (decode == -1)
394 {
395 break;
396 }
397 dst[bytes_extracted++] = (uint8_t)decode;
398 }
399 return bytes_extracted;
400}
Chris Lattner30fdc8d2010-06-08 16:52:24401
402// Consume ASCII hex nibble character pairs until we have decoded byte_size
403// bytes of data.
404
405uint64_t
406StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
407{
408 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
409 {
410 uint64_t result = 0;
411 uint32_t i;
412 if (little_endian)
413 {
414 // Little Endian
415 uint32_t shift_amount;
416 for (i = 0, shift_amount = 0;
Greg Claytonc7bece562013-01-25 18:06:21417 i < byte_size && IsGood();
Chris Lattner30fdc8d2010-06-08 16:52:24418 ++i, shift_amount += 8)
419 {
420 result |= ((uint64_t)GetHexU8() << shift_amount);
421 }
422 }
423 else
424 {
425 // Big Endian
Greg Claytonc7bece562013-01-25 18:06:21426 for (i = 0; i < byte_size && IsGood(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24427 {
428 result <<= 8;
429 result |= GetHexU8();
430 }
431 }
432 }
Greg Claytonc7bece562013-01-25 18:06:21433 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24434 return fail_value;
435}
436
Greg Claytonde9d0492011-01-08 03:17:57437size_t
438StringExtractor::GetHexByteString (std::string &str)
439{
440 str.clear();
Pavel Labath8c1b6bd2016-08-09 12:04:46441 str.reserve(GetBytesLeft() / 2);
Greg Claytonde9d0492011-01-08 03:17:57442 char ch;
443 while ((ch = GetHexU8()) != '\0')
444 str.append(1, ch);
445 return str.size();
446}
447
Daniel Maleae0f8f572013-08-26 23:57:52448size_t
Todd Fialaaf245d12014-06-30 21:05:18449StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
450{
451 str.clear();
452
453 uint32_t nibble_count = 0;
454 for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
455 {}
456
457 return str.size();
458}
459
460size_t
Daniel Maleae0f8f572013-08-26 23:57:52461StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
462 char terminator)
463{
464 str.clear();
465 char ch;
466 while ((ch = GetHexU8(0,false)) != '\0')
467 str.append(1, ch);
468 if (Peek() && *Peek() == terminator)
469 return str.size();
Todd Fialaaf245d12014-06-30 21:05:18470
Daniel Maleae0f8f572013-08-26 23:57:52471 str.clear();
472 return str.size();
473}
474
Chris Lattner30fdc8d2010-06-08 16:52:24475bool
Zachary Turner54695a32016-08-29 19:58:14476StringExtractor::GetNameColonValue(llvm::StringRef &name, llvm::StringRef &value)
Chris Lattner30fdc8d2010-06-08 16:52:24477{
478 // Read something in the form of NNNN:VVVV; where NNNN is any character
479 // that is not a colon, followed by a ':' character, then a value (one or
480 // more ';' chars), followed by a ';'
Zachary Turner54695a32016-08-29 19:58:14481 if (m_index >= m_packet.size())
482 return fail();
483
484 llvm::StringRef view(m_packet);
485 if (view.empty())
486 return fail();
487
488 llvm::StringRef a, b, c, d;
489 view = view.substr(m_index);
490 std::tie(a, b) = view.split(':');
491 if (a.empty() || b.empty())
492 return fail();
493 std::tie(c, d) = b.split(';');
494 if (b == c && d.empty())
495 return fail();
496
497 name = a;
498 value = c;
499 if (d.empty())
500 m_index = m_packet.size();
501 else
Chris Lattner30fdc8d2010-06-08 16:52:24502 {
Zachary Turner54695a32016-08-29 19:58:14503 size_t bytes_consumed = d.data() - view.data();
504 m_index += bytes_consumed;
Chris Lattner30fdc8d2010-06-08 16:52:24505 }
Zachary Turner54695a32016-08-29 19:58:14506 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24507}
Greg Clayton98424c42015-07-06 23:40:40508
509void
510StringExtractor::SkipSpaces ()
511{
512 const size_t n = m_packet.size();
513 while (m_index < n && isspace(m_packet[m_index]))
514 ++m_index;
515}
516