blob: d4ce470d56f36dec8815f441227932f91e2d24b9 [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 Clayton3852b3e2012-09-28 21:51:54 +0000148 uint32_t i = m_index;
149 if ((i + 2) <= m_packet.size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150 {
Daniel Maleaa85e6b62012-12-07 22:21:08 +0000151 const uint8_t hi_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[i])];
152 const uint8_t lo_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[i+1])];
Greg Clayton3852b3e2012-09-28 21:51:54 +0000153 if (hi_nibble < 16 && lo_nibble < 16)
154 {
155 m_index += 2;
156 return (hi_nibble << 4) + lo_nibble;
157 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158 }
Greg Clayton7b70be32012-04-07 00:42:53 +0000159 if (set_eof_on_fail || m_index >= m_packet.size())
Greg Claytonc7bece562013-01-25 18:06:21 +0000160 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161 return fail_value;
162}
163
164uint32_t
Greg Clayton32e0a752011-03-30 18:16:51 +0000165StringExtractor::GetU32 (uint32_t fail_value, int base)
166{
167 if (m_index < m_packet.size())
168 {
169 char *end = NULL;
170 const char *start = m_packet.c_str();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000171 const char *cstr = start + m_index;
172 uint32_t result = ::strtoul (cstr, &end, base);
Greg Clayton32e0a752011-03-30 18:16:51 +0000173
Daniel Maleae0f8f572013-08-26 23:57:52 +0000174 if (end && end != cstr)
175 {
176 m_index = end - start;
177 return result;
178 }
179 }
180 return fail_value;
181}
182
183int32_t
184StringExtractor::GetS32 (int32_t fail_value, int base)
185{
186 if (m_index < m_packet.size())
187 {
188 char *end = NULL;
189 const char *start = m_packet.c_str();
190 const char *cstr = start + m_index;
191 int32_t result = ::strtol (cstr, &end, base);
192
193 if (end && end != cstr)
194 {
195 m_index = end - start;
196 return result;
197 }
198 }
199 return fail_value;
200}
201
202
203uint64_t
204StringExtractor::GetU64 (uint64_t fail_value, int base)
205{
206 if (m_index < m_packet.size())
207 {
208 char *end = NULL;
209 const char *start = m_packet.c_str();
210 const char *cstr = start + m_index;
211 uint64_t result = ::strtoull (cstr, &end, base);
212
213 if (end && end != cstr)
214 {
215 m_index = end - start;
216 return result;
217 }
218 }
219 return fail_value;
220}
221
222int64_t
223StringExtractor::GetS64 (int64_t fail_value, int base)
224{
225 if (m_index < m_packet.size())
226 {
227 char *end = NULL;
228 const char *start = m_packet.c_str();
229 const char *cstr = start + m_index;
230 int64_t result = ::strtoll (cstr, &end, base);
231
232 if (end && end != cstr)
Greg Clayton32e0a752011-03-30 18:16:51 +0000233 {
234 m_index = end - start;
235 return result;
236 }
237 }
238 return fail_value;
239}
240
241
242uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
244{
245 uint32_t result = 0;
246 uint32_t nibble_count = 0;
247
248 if (little_endian)
249 {
250 uint32_t shift_amount = 0;
251 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
252 {
253 // Make sure we don't exceed the size of a uint32_t...
254 if (nibble_count >= (sizeof(uint32_t) * 2))
255 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000256 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257 return fail_value;
258 }
259
260 uint8_t nibble_lo;
261 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
262 ++m_index;
263 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
264 {
265 nibble_lo = xdigit_to_sint (m_packet[m_index]);
266 ++m_index;
267 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
268 result |= ((uint32_t)nibble_lo << shift_amount);
269 nibble_count += 2;
270 shift_amount += 8;
271 }
272 else
273 {
274 result |= ((uint32_t)nibble_hi << shift_amount);
275 nibble_count += 1;
276 shift_amount += 4;
277 }
278
279 }
280 }
281 else
282 {
283 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
284 {
285 // Make sure we don't exceed the size of a uint32_t...
286 if (nibble_count >= (sizeof(uint32_t) * 2))
287 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000288 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000289 return fail_value;
290 }
291
292 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
293 // Big Endian
294 result <<= 4;
295 result |= nibble;
296
297 ++m_index;
298 ++nibble_count;
299 }
300 }
301 return result;
302}
303
304uint64_t
305StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
306{
307 uint64_t result = 0;
308 uint32_t nibble_count = 0;
309
310 if (little_endian)
311 {
312 uint32_t shift_amount = 0;
313 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
314 {
315 // Make sure we don't exceed the size of a uint64_t...
316 if (nibble_count >= (sizeof(uint64_t) * 2))
317 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000318 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000319 return fail_value;
320 }
321
322 uint8_t nibble_lo;
323 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
324 ++m_index;
325 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
326 {
327 nibble_lo = xdigit_to_sint (m_packet[m_index]);
328 ++m_index;
329 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
330 result |= ((uint64_t)nibble_lo << shift_amount);
331 nibble_count += 2;
332 shift_amount += 8;
333 }
334 else
335 {
336 result |= ((uint64_t)nibble_hi << shift_amount);
337 nibble_count += 1;
338 shift_amount += 4;
339 }
340
341 }
342 }
343 else
344 {
345 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
346 {
347 // Make sure we don't exceed the size of a uint64_t...
348 if (nibble_count >= (sizeof(uint64_t) * 2))
349 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000350 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000351 return fail_value;
352 }
353
354 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
355 // Big Endian
356 result <<= 4;
357 result |= nibble;
358
359 ++m_index;
360 ++nibble_count;
361 }
362 }
363 return result;
364}
365
366size_t
367StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
368{
369 uint8_t *dst = (uint8_t*)dst_void;
370 size_t bytes_extracted = 0;
371 while (bytes_extracted < dst_len && GetBytesLeft ())
372 {
373 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
374 if (IsGood())
375 ++bytes_extracted;
376 else
377 break;
378 }
379
380 for (size_t i = bytes_extracted; i < dst_len; ++i)
381 dst[i] = fail_fill_value;
382
383 return bytes_extracted;
384}
385
386
387// Consume ASCII hex nibble character pairs until we have decoded byte_size
388// bytes of data.
389
390uint64_t
391StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
392{
393 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
394 {
395 uint64_t result = 0;
396 uint32_t i;
397 if (little_endian)
398 {
399 // Little Endian
400 uint32_t shift_amount;
401 for (i = 0, shift_amount = 0;
Greg Claytonc7bece562013-01-25 18:06:21 +0000402 i < byte_size && IsGood();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000403 ++i, shift_amount += 8)
404 {
405 result |= ((uint64_t)GetHexU8() << shift_amount);
406 }
407 }
408 else
409 {
410 // Big Endian
Greg Claytonc7bece562013-01-25 18:06:21 +0000411 for (i = 0; i < byte_size && IsGood(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000412 {
413 result <<= 8;
414 result |= GetHexU8();
415 }
416 }
417 }
Greg Claytonc7bece562013-01-25 18:06:21 +0000418 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000419 return fail_value;
420}
421
Greg Claytonde9d0492011-01-08 03:17:57 +0000422size_t
423StringExtractor::GetHexByteString (std::string &str)
424{
425 str.clear();
426 char ch;
427 while ((ch = GetHexU8()) != '\0')
428 str.append(1, ch);
429 return str.size();
430}
431
Daniel Maleae0f8f572013-08-26 23:57:52 +0000432size_t
433StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
434 char terminator)
435{
436 str.clear();
437 char ch;
438 while ((ch = GetHexU8(0,false)) != '\0')
439 str.append(1, ch);
440 if (Peek() && *Peek() == terminator)
441 return str.size();
442 str.clear();
443 return str.size();
444}
445
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000446bool
447StringExtractor::GetNameColonValue (std::string &name, std::string &value)
448{
449 // Read something in the form of NNNN:VVVV; where NNNN is any character
450 // that is not a colon, followed by a ':' character, then a value (one or
451 // more ';' chars), followed by a ';'
452 if (m_index < m_packet.size())
453 {
454 const size_t colon_idx = m_packet.find (':', m_index);
455 if (colon_idx != std::string::npos)
456 {
457 const size_t semicolon_idx = m_packet.find (';', colon_idx);
458 if (semicolon_idx != std::string::npos)
459 {
460 name.assign (m_packet, m_index, colon_idx - m_index);
461 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
462 m_index = semicolon_idx + 1;
463 return true;
464 }
465 }
466 }
Greg Claytonc7bece562013-01-25 18:06:21 +0000467 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000468 return false;
469}