blob: 0209567eafa56a13e4ab614927d8ae7cc526a114 [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
Greg Claytonc982c762010-07-09 20:39:5010#include "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
Greg Clayton3852b3e2012-09-28 21:51:5419static 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:2456static inline int
57xdigit_to_sint (char ch)
58{
Chris Lattner30fdc8d2010-06-08 16:52:2459 if (ch >= 'a' && ch <= 'f')
60 return 10 + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:0561 if (ch >= 'A' && ch <= 'F')
62 return 10 + ch - 'A';
Chris Lattner30fdc8d2010-06-08 16:52:2463 return ch - '0';
64}
65
Chris Lattner30fdc8d2010-06-08 16:52:2466//----------------------------------------------------------------------
67// StringExtractor constructor
68//----------------------------------------------------------------------
69StringExtractor::StringExtractor() :
70 m_packet(),
71 m_index (0)
72{
73}
74
75
76StringExtractor::StringExtractor(const char *packet_cstr) :
77 m_packet(),
78 m_index (0)
79{
80 if (packet_cstr)
81 m_packet.assign (packet_cstr);
82}
83
84
85//----------------------------------------------------------------------
86// StringExtractor copy constructor
87//----------------------------------------------------------------------
88StringExtractor::StringExtractor(const StringExtractor& rhs) :
89 m_packet (rhs.m_packet),
90 m_index (rhs.m_index)
91{
92
93}
94
95//----------------------------------------------------------------------
96// StringExtractor assignment operator
97//----------------------------------------------------------------------
98const StringExtractor&
99StringExtractor::operator=(const StringExtractor& rhs)
100{
101 if (this != &rhs)
102 {
103 m_packet = rhs.m_packet;
104 m_index = rhs.m_index;
105
106 }
107 return *this;
108}
109
110//----------------------------------------------------------------------
111// Destructor
112//----------------------------------------------------------------------
113StringExtractor::~StringExtractor()
114{
115}
116
117
118char
119StringExtractor::GetChar (char fail_value)
120{
121 if (m_index < m_packet.size())
122 {
123 char ch = m_packet[m_index];
124 ++m_index;
125 return ch;
126 }
Greg Claytonc7bece562013-01-25 18:06:21127 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24128 return fail_value;
129}
130
Chris Lattner30fdc8d2010-06-08 16:52:24131//----------------------------------------------------------------------
132// Extract an unsigned character from two hex ASCII chars in the packet
133// string
134//----------------------------------------------------------------------
135uint8_t
Greg Clayton7b70be32012-04-07 00:42:53136StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
Chris Lattner30fdc8d2010-06-08 16:52:24137{
Greg Claytonfbb76342013-11-20 21:07:01138 if (GetBytesLeft() >= 2)
Chris Lattner30fdc8d2010-06-08 16:52:24139 {
Greg Claytonfbb76342013-11-20 21:07:01140 const uint8_t hi_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[m_index])];
141 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:54142 if (hi_nibble < 16 && lo_nibble < 16)
143 {
144 m_index += 2;
145 return (hi_nibble << 4) + lo_nibble;
146 }
Chris Lattner30fdc8d2010-06-08 16:52:24147 }
Greg Clayton7b70be32012-04-07 00:42:53148 if (set_eof_on_fail || m_index >= m_packet.size())
Greg Claytonc7bece562013-01-25 18:06:21149 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24150 return fail_value;
151}
152
153uint32_t
Greg Clayton32e0a752011-03-30 18:16:51154StringExtractor::GetU32 (uint32_t fail_value, int base)
155{
156 if (m_index < m_packet.size())
157 {
Ed Masted4612ad2014-04-20 13:17:36158 char *end = nullptr;
Greg Clayton32e0a752011-03-30 18:16:51159 const char *start = m_packet.c_str();
Daniel Maleae0f8f572013-08-26 23:57:52160 const char *cstr = start + m_index;
161 uint32_t result = ::strtoul (cstr, &end, base);
Greg Clayton32e0a752011-03-30 18:16:51162
Daniel Maleae0f8f572013-08-26 23:57:52163 if (end && end != cstr)
164 {
165 m_index = end - start;
166 return result;
167 }
168 }
169 return fail_value;
170}
171
172int32_t
173StringExtractor::GetS32 (int32_t fail_value, int base)
174{
175 if (m_index < m_packet.size())
176 {
Ed Masted4612ad2014-04-20 13:17:36177 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52178 const char *start = m_packet.c_str();
179 const char *cstr = start + m_index;
180 int32_t result = ::strtol (cstr, &end, base);
181
182 if (end && end != cstr)
183 {
184 m_index = end - start;
185 return result;
186 }
187 }
188 return fail_value;
189}
190
191
192uint64_t
193StringExtractor::GetU64 (uint64_t fail_value, int base)
194{
195 if (m_index < m_packet.size())
196 {
Ed Masted4612ad2014-04-20 13:17:36197 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52198 const char *start = m_packet.c_str();
199 const char *cstr = start + m_index;
200 uint64_t result = ::strtoull (cstr, &end, base);
201
202 if (end && end != cstr)
203 {
204 m_index = end - start;
205 return result;
206 }
207 }
208 return fail_value;
209}
210
211int64_t
212StringExtractor::GetS64 (int64_t fail_value, int base)
213{
214 if (m_index < m_packet.size())
215 {
Ed Masted4612ad2014-04-20 13:17:36216 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52217 const char *start = m_packet.c_str();
218 const char *cstr = start + m_index;
219 int64_t result = ::strtoll (cstr, &end, base);
220
221 if (end && end != cstr)
Greg Clayton32e0a752011-03-30 18:16:51222 {
223 m_index = end - start;
224 return result;
225 }
226 }
227 return fail_value;
228}
229
230
231uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24232StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
233{
234 uint32_t result = 0;
235 uint32_t nibble_count = 0;
236
237 if (little_endian)
238 {
239 uint32_t shift_amount = 0;
240 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
241 {
242 // Make sure we don't exceed the size of a uint32_t...
243 if (nibble_count >= (sizeof(uint32_t) * 2))
244 {
Greg Claytonc7bece562013-01-25 18:06:21245 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24246 return fail_value;
247 }
248
249 uint8_t nibble_lo;
250 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
251 ++m_index;
252 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
253 {
254 nibble_lo = xdigit_to_sint (m_packet[m_index]);
255 ++m_index;
256 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
257 result |= ((uint32_t)nibble_lo << shift_amount);
258 nibble_count += 2;
259 shift_amount += 8;
260 }
261 else
262 {
263 result |= ((uint32_t)nibble_hi << shift_amount);
264 nibble_count += 1;
265 shift_amount += 4;
266 }
267
268 }
269 }
270 else
271 {
272 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
273 {
274 // Make sure we don't exceed the size of a uint32_t...
275 if (nibble_count >= (sizeof(uint32_t) * 2))
276 {
Greg Claytonc7bece562013-01-25 18:06:21277 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24278 return fail_value;
279 }
280
281 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
282 // Big Endian
283 result <<= 4;
284 result |= nibble;
285
286 ++m_index;
287 ++nibble_count;
288 }
289 }
290 return result;
291}
292
293uint64_t
294StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
295{
296 uint64_t result = 0;
297 uint32_t nibble_count = 0;
298
299 if (little_endian)
300 {
301 uint32_t shift_amount = 0;
302 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
303 {
304 // Make sure we don't exceed the size of a uint64_t...
305 if (nibble_count >= (sizeof(uint64_t) * 2))
306 {
Greg Claytonc7bece562013-01-25 18:06:21307 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24308 return fail_value;
309 }
310
311 uint8_t nibble_lo;
312 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
313 ++m_index;
314 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
315 {
316 nibble_lo = xdigit_to_sint (m_packet[m_index]);
317 ++m_index;
318 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
319 result |= ((uint64_t)nibble_lo << shift_amount);
320 nibble_count += 2;
321 shift_amount += 8;
322 }
323 else
324 {
325 result |= ((uint64_t)nibble_hi << shift_amount);
326 nibble_count += 1;
327 shift_amount += 4;
328 }
329
330 }
331 }
332 else
333 {
334 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
335 {
336 // Make sure we don't exceed the size of a uint64_t...
337 if (nibble_count >= (sizeof(uint64_t) * 2))
338 {
Greg Claytonc7bece562013-01-25 18:06:21339 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24340 return fail_value;
341 }
342
343 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
344 // Big Endian
345 result <<= 4;
346 result |= nibble;
347
348 ++m_index;
349 ++nibble_count;
350 }
351 }
352 return result;
353}
354
355size_t
356StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
357{
358 uint8_t *dst = (uint8_t*)dst_void;
359 size_t bytes_extracted = 0;
360 while (bytes_extracted < dst_len && GetBytesLeft ())
361 {
362 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
363 if (IsGood())
364 ++bytes_extracted;
365 else
366 break;
367 }
368
369 for (size_t i = bytes_extracted; i < dst_len; ++i)
370 dst[i] = fail_fill_value;
371
372 return bytes_extracted;
373}
374
375
376// Consume ASCII hex nibble character pairs until we have decoded byte_size
377// bytes of data.
378
379uint64_t
380StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
381{
382 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
383 {
384 uint64_t result = 0;
385 uint32_t i;
386 if (little_endian)
387 {
388 // Little Endian
389 uint32_t shift_amount;
390 for (i = 0, shift_amount = 0;
Greg Claytonc7bece562013-01-25 18:06:21391 i < byte_size && IsGood();
Chris Lattner30fdc8d2010-06-08 16:52:24392 ++i, shift_amount += 8)
393 {
394 result |= ((uint64_t)GetHexU8() << shift_amount);
395 }
396 }
397 else
398 {
399 // Big Endian
Greg Claytonc7bece562013-01-25 18:06:21400 for (i = 0; i < byte_size && IsGood(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24401 {
402 result <<= 8;
403 result |= GetHexU8();
404 }
405 }
406 }
Greg Claytonc7bece562013-01-25 18:06:21407 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24408 return fail_value;
409}
410
Greg Claytonde9d0492011-01-08 03:17:57411size_t
412StringExtractor::GetHexByteString (std::string &str)
413{
414 str.clear();
415 char ch;
416 while ((ch = GetHexU8()) != '\0')
417 str.append(1, ch);
418 return str.size();
419}
420
Daniel Maleae0f8f572013-08-26 23:57:52421size_t
422StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
423 char terminator)
424{
425 str.clear();
426 char ch;
427 while ((ch = GetHexU8(0,false)) != '\0')
428 str.append(1, ch);
429 if (Peek() && *Peek() == terminator)
430 return str.size();
431 str.clear();
432 return str.size();
433}
434
Chris Lattner30fdc8d2010-06-08 16:52:24435bool
436StringExtractor::GetNameColonValue (std::string &name, std::string &value)
437{
438 // Read something in the form of NNNN:VVVV; where NNNN is any character
439 // that is not a colon, followed by a ':' character, then a value (one or
440 // more ';' chars), followed by a ';'
441 if (m_index < m_packet.size())
442 {
443 const size_t colon_idx = m_packet.find (':', m_index);
444 if (colon_idx != std::string::npos)
445 {
446 const size_t semicolon_idx = m_packet.find (';', colon_idx);
447 if (semicolon_idx != std::string::npos)
448 {
449 name.assign (m_packet, m_index, colon_idx - m_index);
450 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
451 m_index = semicolon_idx + 1;
452 return true;
453 }
454 }
455 }
Greg Claytonc7bece562013-01-25 18:06:21456 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24457 return false;
458}