blob: 9d2315708821e319e5e4746962870e71f0a6e1f9 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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
Greg Claytonc982c762010-07-09 20:39:50 +000010#include "Utility/StringExtractor.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011
12// C Includes
Stephen Wilson78709172011-04-07 10:20:23 +000013#include <stdlib.h>
14
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015// C++ Includes
16// Other libraries and framework includes
17// Project includes
18
Greg Clayton3852b3e2012-09-28 21:51:54 +000019static const uint8_t
20g_hex_ascii_to_hex_integer[256] = {
21
22 255, 255, 255, 255, 255, 255, 255, 255,
23 255, 255, 255, 255, 255, 255, 255, 255,
24 255, 255, 255, 255, 255, 255, 255, 255,
25 255, 255, 255, 255, 255, 255, 255, 255,
26 255, 255, 255, 255, 255, 255, 255, 255,
27 255, 255, 255, 255, 255, 255, 255, 255,
28 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
29 0x8, 0x9, 255, 255, 255, 255, 255, 255,
30 255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255,
31 255, 255, 255, 255, 255, 255, 255, 255,
32 255, 255, 255, 255, 255, 255, 255, 255,
33 255, 255, 255, 255, 255, 255, 255, 255,
34 255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255,
35 255, 255, 255, 255, 255, 255, 255, 255,
36 255, 255, 255, 255, 255, 255, 255, 255,
37 255, 255, 255, 255, 255, 255, 255, 255,
38 255, 255, 255, 255, 255, 255, 255, 255,
39 255, 255, 255, 255, 255, 255, 255, 255,
40 255, 255, 255, 255, 255, 255, 255, 255,
41 255, 255, 255, 255, 255, 255, 255, 255,
42 255, 255, 255, 255, 255, 255, 255, 255,
43 255, 255, 255, 255, 255, 255, 255, 255,
44 255, 255, 255, 255, 255, 255, 255, 255,
45 255, 255, 255, 255, 255, 255, 255, 255,
46 255, 255, 255, 255, 255, 255, 255, 255,
47 255, 255, 255, 255, 255, 255, 255, 255,
48 255, 255, 255, 255, 255, 255, 255, 255,
49 255, 255, 255, 255, 255, 255, 255, 255,
50 255, 255, 255, 255, 255, 255, 255, 255,
51 255, 255, 255, 255, 255, 255, 255, 255,
52 255, 255, 255, 255, 255, 255, 255, 255,
53 255, 255, 255, 255, 255, 255, 255, 255,
54};
55
Chris Lattner30fdc8d2010-06-08 16:52:24 +000056static inline int
57xdigit_to_sint (char ch)
58{
Chris Lattner30fdc8d2010-06-08 16:52:24 +000059 if (ch >= 'a' && ch <= 'f')
60 return 10 + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:05 +000061 if (ch >= 'A' && ch <= 'F')
62 return 10 + ch - 'A';
Chris Lattner30fdc8d2010-06-08 16:52:24 +000063 return ch - '0';
64}
65
66static inline unsigned int
67xdigit_to_uint (uint8_t ch)
68{
Chris Lattner30fdc8d2010-06-08 16:52:24 +000069 if (ch >= 'a' && ch <= 'f')
70 return 10u + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:05 +000071 if (ch >= 'A' && ch <= 'F')
72 return 10u + ch - 'A';
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073 return ch - '0';
74}
75
76//----------------------------------------------------------------------
77// StringExtractor constructor
78//----------------------------------------------------------------------
79StringExtractor::StringExtractor() :
80 m_packet(),
81 m_index (0)
82{
83}
84
85
86StringExtractor::StringExtractor(const char *packet_cstr) :
87 m_packet(),
88 m_index (0)
89{
90 if (packet_cstr)
91 m_packet.assign (packet_cstr);
92}
93
94
95//----------------------------------------------------------------------
96// StringExtractor copy constructor
97//----------------------------------------------------------------------
98StringExtractor::StringExtractor(const StringExtractor& rhs) :
99 m_packet (rhs.m_packet),
100 m_index (rhs.m_index)
101{
102
103}
104
105//----------------------------------------------------------------------
106// StringExtractor assignment operator
107//----------------------------------------------------------------------
108const StringExtractor&
109StringExtractor::operator=(const StringExtractor& rhs)
110{
111 if (this != &rhs)
112 {
113 m_packet = rhs.m_packet;
114 m_index = rhs.m_index;
115
116 }
117 return *this;
118}
119
120//----------------------------------------------------------------------
121// Destructor
122//----------------------------------------------------------------------
123StringExtractor::~StringExtractor()
124{
125}
126
127
128char
129StringExtractor::GetChar (char fail_value)
130{
131 if (m_index < m_packet.size())
132 {
133 char ch = m_packet[m_index];
134 ++m_index;
135 return ch;
136 }
Greg Claytonc7bece562013-01-25 18:06:21 +0000137 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138 return fail_value;
139}
140
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141//----------------------------------------------------------------------
142// Extract an unsigned character from two hex ASCII chars in the packet
143// string
144//----------------------------------------------------------------------
145uint8_t
Greg Clayton7b70be32012-04-07 00:42:53 +0000146StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147{
Greg Claytonfbb76342013-11-20 21:07:01 +0000148 if (GetBytesLeft() >= 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000149 {
Greg Claytonfbb76342013-11-20 21:07:01 +0000150 const uint8_t hi_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[m_index])];
151 const uint8_t lo_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[m_index+1])];
Greg Clayton3852b3e2012-09-28 21:51:54 +0000152 if (hi_nibble < 16 && lo_nibble < 16)
153 {
154 m_index += 2;
155 return (hi_nibble << 4) + lo_nibble;
156 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000157 }
Greg Clayton7b70be32012-04-07 00:42:53 +0000158 if (set_eof_on_fail || m_index >= m_packet.size())
Greg Claytonc7bece562013-01-25 18:06:21 +0000159 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160 return fail_value;
161}
162
163uint32_t
Greg Clayton32e0a752011-03-30 18:16:51 +0000164StringExtractor::GetU32 (uint32_t fail_value, int base)
165{
166 if (m_index < m_packet.size())
167 {
168 char *end = NULL;
169 const char *start = m_packet.c_str();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000170 const char *cstr = start + m_index;
171 uint32_t result = ::strtoul (cstr, &end, base);
Greg Clayton32e0a752011-03-30 18:16:51 +0000172
Daniel Maleae0f8f572013-08-26 23:57:52 +0000173 if (end && end != cstr)
174 {
175 m_index = end - start;
176 return result;
177 }
178 }
179 return fail_value;
180}
181
182int32_t
183StringExtractor::GetS32 (int32_t fail_value, int base)
184{
185 if (m_index < m_packet.size())
186 {
187 char *end = NULL;
188 const char *start = m_packet.c_str();
189 const char *cstr = start + m_index;
190 int32_t result = ::strtol (cstr, &end, base);
191
192 if (end && end != cstr)
193 {
194 m_index = end - start;
195 return result;
196 }
197 }
198 return fail_value;
199}
200
201
202uint64_t
203StringExtractor::GetU64 (uint64_t fail_value, int base)
204{
205 if (m_index < m_packet.size())
206 {
207 char *end = NULL;
208 const char *start = m_packet.c_str();
209 const char *cstr = start + m_index;
210 uint64_t result = ::strtoull (cstr, &end, base);
211
212 if (end && end != cstr)
213 {
214 m_index = end - start;
215 return result;
216 }
217 }
218 return fail_value;
219}
220
221int64_t
222StringExtractor::GetS64 (int64_t fail_value, int base)
223{
224 if (m_index < m_packet.size())
225 {
226 char *end = NULL;
227 const char *start = m_packet.c_str();
228 const char *cstr = start + m_index;
229 int64_t result = ::strtoll (cstr, &end, base);
230
231 if (end && end != cstr)
Greg Clayton32e0a752011-03-30 18:16:51 +0000232 {
233 m_index = end - start;
234 return result;
235 }
236 }
237 return fail_value;
238}
239
240
241uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000242StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
243{
244 uint32_t result = 0;
245 uint32_t nibble_count = 0;
246
247 if (little_endian)
248 {
249 uint32_t shift_amount = 0;
250 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
251 {
252 // Make sure we don't exceed the size of a uint32_t...
253 if (nibble_count >= (sizeof(uint32_t) * 2))
254 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000255 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256 return fail_value;
257 }
258
259 uint8_t nibble_lo;
260 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
261 ++m_index;
262 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
263 {
264 nibble_lo = xdigit_to_sint (m_packet[m_index]);
265 ++m_index;
266 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
267 result |= ((uint32_t)nibble_lo << shift_amount);
268 nibble_count += 2;
269 shift_amount += 8;
270 }
271 else
272 {
273 result |= ((uint32_t)nibble_hi << shift_amount);
274 nibble_count += 1;
275 shift_amount += 4;
276 }
277
278 }
279 }
280 else
281 {
282 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
283 {
284 // Make sure we don't exceed the size of a uint32_t...
285 if (nibble_count >= (sizeof(uint32_t) * 2))
286 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000287 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288 return fail_value;
289 }
290
291 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
292 // Big Endian
293 result <<= 4;
294 result |= nibble;
295
296 ++m_index;
297 ++nibble_count;
298 }
299 }
300 return result;
301}
302
303uint64_t
304StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
305{
306 uint64_t result = 0;
307 uint32_t nibble_count = 0;
308
309 if (little_endian)
310 {
311 uint32_t shift_amount = 0;
312 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
313 {
314 // Make sure we don't exceed the size of a uint64_t...
315 if (nibble_count >= (sizeof(uint64_t) * 2))
316 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000317 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000318 return fail_value;
319 }
320
321 uint8_t nibble_lo;
322 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
323 ++m_index;
324 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
325 {
326 nibble_lo = xdigit_to_sint (m_packet[m_index]);
327 ++m_index;
328 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
329 result |= ((uint64_t)nibble_lo << shift_amount);
330 nibble_count += 2;
331 shift_amount += 8;
332 }
333 else
334 {
335 result |= ((uint64_t)nibble_hi << shift_amount);
336 nibble_count += 1;
337 shift_amount += 4;
338 }
339
340 }
341 }
342 else
343 {
344 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
345 {
346 // Make sure we don't exceed the size of a uint64_t...
347 if (nibble_count >= (sizeof(uint64_t) * 2))
348 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000349 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000350 return fail_value;
351 }
352
353 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
354 // Big Endian
355 result <<= 4;
356 result |= nibble;
357
358 ++m_index;
359 ++nibble_count;
360 }
361 }
362 return result;
363}
364
365size_t
366StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
367{
368 uint8_t *dst = (uint8_t*)dst_void;
369 size_t bytes_extracted = 0;
370 while (bytes_extracted < dst_len && GetBytesLeft ())
371 {
372 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
373 if (IsGood())
374 ++bytes_extracted;
375 else
376 break;
377 }
378
379 for (size_t i = bytes_extracted; i < dst_len; ++i)
380 dst[i] = fail_fill_value;
381
382 return bytes_extracted;
383}
384
385
386// Consume ASCII hex nibble character pairs until we have decoded byte_size
387// bytes of data.
388
389uint64_t
390StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
391{
392 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
393 {
394 uint64_t result = 0;
395 uint32_t i;
396 if (little_endian)
397 {
398 // Little Endian
399 uint32_t shift_amount;
400 for (i = 0, shift_amount = 0;
Greg Claytonc7bece562013-01-25 18:06:21 +0000401 i < byte_size && IsGood();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000402 ++i, shift_amount += 8)
403 {
404 result |= ((uint64_t)GetHexU8() << shift_amount);
405 }
406 }
407 else
408 {
409 // Big Endian
Greg Claytonc7bece562013-01-25 18:06:21 +0000410 for (i = 0; i < byte_size && IsGood(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000411 {
412 result <<= 8;
413 result |= GetHexU8();
414 }
415 }
416 }
Greg Claytonc7bece562013-01-25 18:06:21 +0000417 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000418 return fail_value;
419}
420
Greg Claytonde9d0492011-01-08 03:17:57 +0000421size_t
422StringExtractor::GetHexByteString (std::string &str)
423{
424 str.clear();
425 char ch;
426 while ((ch = GetHexU8()) != '\0')
427 str.append(1, ch);
428 return str.size();
429}
430
Daniel Maleae0f8f572013-08-26 23:57:52 +0000431size_t
432StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
433 char terminator)
434{
435 str.clear();
436 char ch;
437 while ((ch = GetHexU8(0,false)) != '\0')
438 str.append(1, ch);
439 if (Peek() && *Peek() == terminator)
440 return str.size();
441 str.clear();
442 return str.size();
443}
444
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000445bool
446StringExtractor::GetNameColonValue (std::string &name, std::string &value)
447{
448 // Read something in the form of NNNN:VVVV; where NNNN is any character
449 // that is not a colon, followed by a ':' character, then a value (one or
450 // more ';' chars), followed by a ';'
451 if (m_index < m_packet.size())
452 {
453 const size_t colon_idx = m_packet.find (':', m_index);
454 if (colon_idx != std::string::npos)
455 {
456 const size_t semicolon_idx = m_packet.find (';', colon_idx);
457 if (semicolon_idx != std::string::npos)
458 {
459 name.assign (m_packet, m_index, colon_idx - m_index);
460 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
461 m_index = semicolon_idx + 1;
462 return true;
463 }
464 }
465 }
Greg Claytonc7bece562013-01-25 18:06:21 +0000466 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000467 return false;
468}