blob: a2cbe6cd48692ec5c9c7a05502a22fa2a28d9463 [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
Chris Lattner30fdc8d2010-06-08 16:52:2419static inline int
20xdigit_to_sint (char ch)
21{
Chris Lattner30fdc8d2010-06-08 16:52:2422 if (ch >= 'a' && ch <= 'f')
23 return 10 + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:0524 if (ch >= 'A' && ch <= 'F')
25 return 10 + ch - 'A';
Vince Harron6eddf8d2014-12-01 22:19:3326 if (ch >= '0' && ch <= '9')
27 return ch - '0';
28 return -1;
Chris Lattner30fdc8d2010-06-08 16:52:2429}
30
Chris Lattner30fdc8d2010-06-08 16:52:2431//----------------------------------------------------------------------
32// StringExtractor constructor
33//----------------------------------------------------------------------
34StringExtractor::StringExtractor() :
35 m_packet(),
36 m_index (0)
37{
38}
39
40
41StringExtractor::StringExtractor(const char *packet_cstr) :
42 m_packet(),
43 m_index (0)
44{
45 if (packet_cstr)
46 m_packet.assign (packet_cstr);
47}
48
49
50//----------------------------------------------------------------------
51// StringExtractor copy constructor
52//----------------------------------------------------------------------
53StringExtractor::StringExtractor(const StringExtractor& rhs) :
54 m_packet (rhs.m_packet),
55 m_index (rhs.m_index)
56{
57
58}
59
60//----------------------------------------------------------------------
61// StringExtractor assignment operator
62//----------------------------------------------------------------------
63const StringExtractor&
64StringExtractor::operator=(const StringExtractor& rhs)
65{
66 if (this != &rhs)
67 {
68 m_packet = rhs.m_packet;
69 m_index = rhs.m_index;
70
71 }
72 return *this;
73}
74
75//----------------------------------------------------------------------
76// Destructor
77//----------------------------------------------------------------------
78StringExtractor::~StringExtractor()
79{
80}
81
82
83char
84StringExtractor::GetChar (char fail_value)
85{
86 if (m_index < m_packet.size())
87 {
88 char ch = m_packet[m_index];
89 ++m_index;
90 return ch;
91 }
Greg Claytonc7bece562013-01-25 18:06:2192 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:2493 return fail_value;
94}
95
Chris Lattner30fdc8d2010-06-08 16:52:2496//----------------------------------------------------------------------
Vince Harron6eddf8d2014-12-01 22:19:3397// If a pair of valid hex digits exist at the head of the
98// StringExtractor they are decoded into an unsigned byte and returned
99// by this function
100//
101// If there is not a pair of valid hex digits at the head of the
102// StringExtractor, it is left unchanged and -1 is returned
103//----------------------------------------------------------------------
104int
105StringExtractor::DecodeHexU8()
106{
107 if (GetBytesLeft() < 2)
108 {
109 return -1;
110 }
111 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
112 const int lo_nibble = xdigit_to_sint(m_packet[m_index+1]);
113 if (hi_nibble == -1 || lo_nibble == -1)
114 {
115 return -1;
116 }
117 m_index += 2;
118 return (uint8_t)((hi_nibble << 4) + lo_nibble);
119}
120
121//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24122// Extract an unsigned character from two hex ASCII chars in the packet
123// string
124//----------------------------------------------------------------------
125uint8_t
Greg Clayton7b70be32012-04-07 00:42:53126StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
Chris Lattner30fdc8d2010-06-08 16:52:24127{
Vince Harron6eddf8d2014-12-01 22:19:33128 int byte = DecodeHexU8();
129 if (byte == -1)
Chris Lattner30fdc8d2010-06-08 16:52:24130 {
Vince Harron6eddf8d2014-12-01 22:19:33131 if (set_eof_on_fail || m_index >= m_packet.size())
132 m_index = UINT64_MAX;
133 return fail_value;
Chris Lattner30fdc8d2010-06-08 16:52:24134 }
Vince Harron6eddf8d2014-12-01 22:19:33135 return (uint8_t)byte;
Chris Lattner30fdc8d2010-06-08 16:52:24136}
137
138uint32_t
Greg Clayton32e0a752011-03-30 18:16:51139StringExtractor::GetU32 (uint32_t fail_value, int base)
140{
141 if (m_index < m_packet.size())
142 {
Ed Masted4612ad2014-04-20 13:17:36143 char *end = nullptr;
Greg Clayton32e0a752011-03-30 18:16:51144 const char *start = m_packet.c_str();
Daniel Maleae0f8f572013-08-26 23:57:52145 const char *cstr = start + m_index;
146 uint32_t result = ::strtoul (cstr, &end, base);
Greg Clayton32e0a752011-03-30 18:16:51147
Daniel Maleae0f8f572013-08-26 23:57:52148 if (end && end != cstr)
149 {
150 m_index = end - start;
151 return result;
152 }
153 }
154 return fail_value;
155}
156
157int32_t
158StringExtractor::GetS32 (int32_t fail_value, int base)
159{
160 if (m_index < m_packet.size())
161 {
Ed Masted4612ad2014-04-20 13:17:36162 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52163 const char *start = m_packet.c_str();
164 const char *cstr = start + m_index;
165 int32_t result = ::strtol (cstr, &end, base);
166
167 if (end && end != cstr)
168 {
169 m_index = end - start;
170 return result;
171 }
172 }
173 return fail_value;
174}
175
176
177uint64_t
178StringExtractor::GetU64 (uint64_t fail_value, int base)
179{
180 if (m_index < m_packet.size())
181 {
Ed Masted4612ad2014-04-20 13:17:36182 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52183 const char *start = m_packet.c_str();
184 const char *cstr = start + m_index;
185 uint64_t result = ::strtoull (cstr, &end, base);
186
187 if (end && end != cstr)
188 {
189 m_index = end - start;
190 return result;
191 }
192 }
193 return fail_value;
194}
195
196int64_t
197StringExtractor::GetS64 (int64_t fail_value, int base)
198{
199 if (m_index < m_packet.size())
200 {
Ed Masted4612ad2014-04-20 13:17:36201 char *end = nullptr;
Daniel Maleae0f8f572013-08-26 23:57:52202 const char *start = m_packet.c_str();
203 const char *cstr = start + m_index;
204 int64_t result = ::strtoll (cstr, &end, base);
205
206 if (end && end != cstr)
Greg Clayton32e0a752011-03-30 18:16:51207 {
208 m_index = end - start;
209 return result;
210 }
211 }
212 return fail_value;
213}
214
215
216uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24217StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
218{
219 uint32_t result = 0;
220 uint32_t nibble_count = 0;
221
222 if (little_endian)
223 {
224 uint32_t shift_amount = 0;
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_lo;
235 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
236 ++m_index;
237 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
238 {
239 nibble_lo = xdigit_to_sint (m_packet[m_index]);
240 ++m_index;
241 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
242 result |= ((uint32_t)nibble_lo << shift_amount);
243 nibble_count += 2;
244 shift_amount += 8;
245 }
246 else
247 {
248 result |= ((uint32_t)nibble_hi << shift_amount);
249 nibble_count += 1;
250 shift_amount += 4;
251 }
252
253 }
254 }
255 else
256 {
257 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
258 {
259 // Make sure we don't exceed the size of a uint32_t...
260 if (nibble_count >= (sizeof(uint32_t) * 2))
261 {
Greg Claytonc7bece562013-01-25 18:06:21262 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24263 return fail_value;
264 }
265
266 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
267 // Big Endian
268 result <<= 4;
269 result |= nibble;
270
271 ++m_index;
272 ++nibble_count;
273 }
274 }
275 return result;
276}
277
278uint64_t
279StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
280{
281 uint64_t result = 0;
282 uint32_t nibble_count = 0;
283
284 if (little_endian)
285 {
286 uint32_t shift_amount = 0;
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_lo;
297 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
298 ++m_index;
299 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
300 {
301 nibble_lo = xdigit_to_sint (m_packet[m_index]);
302 ++m_index;
303 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
304 result |= ((uint64_t)nibble_lo << shift_amount);
305 nibble_count += 2;
306 shift_amount += 8;
307 }
308 else
309 {
310 result |= ((uint64_t)nibble_hi << shift_amount);
311 nibble_count += 1;
312 shift_amount += 4;
313 }
314
315 }
316 }
317 else
318 {
319 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
320 {
321 // Make sure we don't exceed the size of a uint64_t...
322 if (nibble_count >= (sizeof(uint64_t) * 2))
323 {
Greg Claytonc7bece562013-01-25 18:06:21324 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24325 return fail_value;
326 }
327
328 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
329 // Big Endian
330 result <<= 4;
331 result |= nibble;
332
333 ++m_index;
334 ++nibble_count;
335 }
336 }
337 return result;
338}
339
340size_t
341StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
342{
343 uint8_t *dst = (uint8_t*)dst_void;
344 size_t bytes_extracted = 0;
345 while (bytes_extracted < dst_len && GetBytesLeft ())
346 {
347 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
348 if (IsGood())
349 ++bytes_extracted;
350 else
351 break;
352 }
353
354 for (size_t i = bytes_extracted; i < dst_len; ++i)
355 dst[i] = fail_fill_value;
356
357 return bytes_extracted;
358}
359
Vince Harron6eddf8d2014-12-01 22:19:33360//----------------------------------------------------------------------
361// Decodes all valid hex encoded bytes at the head of the
362// StringExtractor, limited by dst_len.
363//
364// Returns the number of bytes successfully decoded
365//----------------------------------------------------------------------
366size_t
367StringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len)
368{
369 uint8_t *dst = (uint8_t*)dst_void;
370 size_t bytes_extracted = 0;
371 while (bytes_extracted < dst_len)
372 {
373 int decode = DecodeHexU8();
374 if (decode == -1)
375 {
376 break;
377 }
378 dst[bytes_extracted++] = (uint8_t)decode;
379 }
380 return bytes_extracted;
381}
Chris Lattner30fdc8d2010-06-08 16:52:24382
383// Consume ASCII hex nibble character pairs until we have decoded byte_size
384// bytes of data.
385
386uint64_t
387StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
388{
389 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
390 {
391 uint64_t result = 0;
392 uint32_t i;
393 if (little_endian)
394 {
395 // Little Endian
396 uint32_t shift_amount;
397 for (i = 0, shift_amount = 0;
Greg Claytonc7bece562013-01-25 18:06:21398 i < byte_size && IsGood();
Chris Lattner30fdc8d2010-06-08 16:52:24399 ++i, shift_amount += 8)
400 {
401 result |= ((uint64_t)GetHexU8() << shift_amount);
402 }
403 }
404 else
405 {
406 // Big Endian
Greg Claytonc7bece562013-01-25 18:06:21407 for (i = 0; i < byte_size && IsGood(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24408 {
409 result <<= 8;
410 result |= GetHexU8();
411 }
412 }
413 }
Greg Claytonc7bece562013-01-25 18:06:21414 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24415 return fail_value;
416}
417
Greg Claytonde9d0492011-01-08 03:17:57418size_t
419StringExtractor::GetHexByteString (std::string &str)
420{
421 str.clear();
422 char ch;
423 while ((ch = GetHexU8()) != '\0')
424 str.append(1, ch);
425 return str.size();
426}
427
Daniel Maleae0f8f572013-08-26 23:57:52428size_t
Todd Fialaaf245d12014-06-30 21:05:18429StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
430{
431 str.clear();
432
433 uint32_t nibble_count = 0;
434 for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
435 {}
436
437 return str.size();
438}
439
440size_t
Daniel Maleae0f8f572013-08-26 23:57:52441StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
442 char terminator)
443{
444 str.clear();
445 char ch;
446 while ((ch = GetHexU8(0,false)) != '\0')
447 str.append(1, ch);
448 if (Peek() && *Peek() == terminator)
449 return str.size();
Todd Fialaaf245d12014-06-30 21:05:18450
Daniel Maleae0f8f572013-08-26 23:57:52451 str.clear();
452 return str.size();
453}
454
Chris Lattner30fdc8d2010-06-08 16:52:24455bool
456StringExtractor::GetNameColonValue (std::string &name, std::string &value)
457{
458 // Read something in the form of NNNN:VVVV; where NNNN is any character
459 // that is not a colon, followed by a ':' character, then a value (one or
460 // more ';' chars), followed by a ';'
461 if (m_index < m_packet.size())
462 {
463 const size_t colon_idx = m_packet.find (':', m_index);
464 if (colon_idx != std::string::npos)
465 {
466 const size_t semicolon_idx = m_packet.find (';', colon_idx);
467 if (semicolon_idx != std::string::npos)
468 {
469 name.assign (m_packet, m_index, colon_idx - m_index);
470 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
471 m_index = semicolon_idx + 1;
472 return true;
473 }
474 }
475 }
Greg Claytonc7bece562013-01-25 18:06:21476 m_index = UINT64_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24477 return false;
478}