blob: 2f4bcecda8f320468205241d5da8a9a9f0f702f2 [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
66static inline unsigned int
67xdigit_to_uint (uint8_t ch)
68{
Chris Lattner30fdc8d2010-06-08 16:52:2469 if (ch >= 'a' && ch <= 'f')
70 return 10u + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:0571 if (ch >= 'A' && ch <= 'F')
72 return 10u + ch - 'A';
Chris Lattner30fdc8d2010-06-08 16:52:2473 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:21137 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24138 return fail_value;
139}
140
Chris Lattner30fdc8d2010-06-08 16:52:24141//----------------------------------------------------------------------
142// Extract an unsigned character from two hex ASCII chars in the packet
143// string
144//----------------------------------------------------------------------
145uint8_t
Greg Clayton7b70be32012-04-07 00:42:53146StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
Chris Lattner30fdc8d2010-06-08 16:52:24147{
Greg Clayton3852b3e2012-09-28 21:51:54148 uint32_t i = m_index;
149 if ((i + 2) <= m_packet.size())
Chris Lattner30fdc8d2010-06-08 16:52:24150 {
Daniel Maleaa85e6b62012-12-07 22:21:08151 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:54153 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:24158 }
Greg Clayton7b70be32012-04-07 00:42:53159 if (set_eof_on_fail || m_index >= m_packet.size())
Greg Claytonc7bece562013-01-25 18:06:21160 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24161 return fail_value;
162}
163
164uint32_t
Greg Clayton32e0a752011-03-30 18:16:51165StringExtractor::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();
171 const char *uint_cstr = start + m_index;
172 uint32_t result = ::strtoul (uint_cstr, &end, base);
173
174 if (end && end != uint_cstr)
175 {
176 m_index = end - start;
177 return result;
178 }
179 }
180 return fail_value;
181}
182
183
184uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24185StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
186{
187 uint32_t result = 0;
188 uint32_t nibble_count = 0;
189
190 if (little_endian)
191 {
192 uint32_t shift_amount = 0;
193 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
194 {
195 // Make sure we don't exceed the size of a uint32_t...
196 if (nibble_count >= (sizeof(uint32_t) * 2))
197 {
Greg Claytonc7bece562013-01-25 18:06:21198 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24199 return fail_value;
200 }
201
202 uint8_t nibble_lo;
203 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
204 ++m_index;
205 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
206 {
207 nibble_lo = xdigit_to_sint (m_packet[m_index]);
208 ++m_index;
209 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
210 result |= ((uint32_t)nibble_lo << shift_amount);
211 nibble_count += 2;
212 shift_amount += 8;
213 }
214 else
215 {
216 result |= ((uint32_t)nibble_hi << shift_amount);
217 nibble_count += 1;
218 shift_amount += 4;
219 }
220
221 }
222 }
223 else
224 {
225 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
226 {
227 // Make sure we don't exceed the size of a uint32_t...
228 if (nibble_count >= (sizeof(uint32_t) * 2))
229 {
Greg Claytonc7bece562013-01-25 18:06:21230 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24231 return fail_value;
232 }
233
234 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
235 // Big Endian
236 result <<= 4;
237 result |= nibble;
238
239 ++m_index;
240 ++nibble_count;
241 }
242 }
243 return result;
244}
245
246uint64_t
247StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
248{
249 uint64_t result = 0;
250 uint32_t nibble_count = 0;
251
252 if (little_endian)
253 {
254 uint32_t shift_amount = 0;
255 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
256 {
257 // Make sure we don't exceed the size of a uint64_t...
258 if (nibble_count >= (sizeof(uint64_t) * 2))
259 {
Greg Claytonc7bece562013-01-25 18:06:21260 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24261 return fail_value;
262 }
263
264 uint8_t nibble_lo;
265 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
266 ++m_index;
267 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
268 {
269 nibble_lo = xdigit_to_sint (m_packet[m_index]);
270 ++m_index;
271 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
272 result |= ((uint64_t)nibble_lo << shift_amount);
273 nibble_count += 2;
274 shift_amount += 8;
275 }
276 else
277 {
278 result |= ((uint64_t)nibble_hi << shift_amount);
279 nibble_count += 1;
280 shift_amount += 4;
281 }
282
283 }
284 }
285 else
286 {
287 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
288 {
289 // Make sure we don't exceed the size of a uint64_t...
290 if (nibble_count >= (sizeof(uint64_t) * 2))
291 {
Greg Claytonc7bece562013-01-25 18:06:21292 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24293 return fail_value;
294 }
295
296 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
297 // Big Endian
298 result <<= 4;
299 result |= nibble;
300
301 ++m_index;
302 ++nibble_count;
303 }
304 }
305 return result;
306}
307
308size_t
309StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
310{
311 uint8_t *dst = (uint8_t*)dst_void;
312 size_t bytes_extracted = 0;
313 while (bytes_extracted < dst_len && GetBytesLeft ())
314 {
315 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
316 if (IsGood())
317 ++bytes_extracted;
318 else
319 break;
320 }
321
322 for (size_t i = bytes_extracted; i < dst_len; ++i)
323 dst[i] = fail_fill_value;
324
325 return bytes_extracted;
326}
327
328
329// Consume ASCII hex nibble character pairs until we have decoded byte_size
330// bytes of data.
331
332uint64_t
333StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
334{
335 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
336 {
337 uint64_t result = 0;
338 uint32_t i;
339 if (little_endian)
340 {
341 // Little Endian
342 uint32_t shift_amount;
343 for (i = 0, shift_amount = 0;
Greg Claytonc7bece562013-01-25 18:06:21344 i < byte_size && IsGood();
Chris Lattner30fdc8d2010-06-08 16:52:24345 ++i, shift_amount += 8)
346 {
347 result |= ((uint64_t)GetHexU8() << shift_amount);
348 }
349 }
350 else
351 {
352 // Big Endian
Greg Claytonc7bece562013-01-25 18:06:21353 for (i = 0; i < byte_size && IsGood(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24354 {
355 result <<= 8;
356 result |= GetHexU8();
357 }
358 }
359 }
Greg Claytonc7bece562013-01-25 18:06:21360 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24361 return fail_value;
362}
363
Greg Claytonde9d0492011-01-08 03:17:57364size_t
365StringExtractor::GetHexByteString (std::string &str)
366{
367 str.clear();
368 char ch;
369 while ((ch = GetHexU8()) != '\0')
370 str.append(1, ch);
371 return str.size();
372}
373
Chris Lattner30fdc8d2010-06-08 16:52:24374bool
375StringExtractor::GetNameColonValue (std::string &name, std::string &value)
376{
377 // Read something in the form of NNNN:VVVV; where NNNN is any character
378 // that is not a colon, followed by a ':' character, then a value (one or
379 // more ';' chars), followed by a ';'
380 if (m_index < m_packet.size())
381 {
382 const size_t colon_idx = m_packet.find (':', m_index);
383 if (colon_idx != std::string::npos)
384 {
385 const size_t semicolon_idx = m_packet.find (';', colon_idx);
386 if (semicolon_idx != std::string::npos)
387 {
388 name.assign (m_packet, m_index, colon_idx - m_index);
389 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
390 m_index = semicolon_idx + 1;
391 return true;
392 }
393 }
394 }
Greg Claytonc7bece562013-01-25 18:06:21395 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24396 return false;
397}