blob: d2f4a68f7c4d61d8b45dea35425e3f1077da3d00 [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
19static inline int
20xdigit_to_sint (char ch)
21{
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022 if (ch >= 'a' && ch <= 'f')
23 return 10 + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:05 +000024 if (ch >= 'A' && ch <= 'F')
25 return 10 + ch - 'A';
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026 return ch - '0';
27}
28
29static inline unsigned int
30xdigit_to_uint (uint8_t ch)
31{
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032 if (ch >= 'a' && ch <= 'f')
33 return 10u + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:05 +000034 if (ch >= 'A' && ch <= 'F')
35 return 10u + ch - 'A';
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036 return ch - '0';
37}
38
39//----------------------------------------------------------------------
40// StringExtractor constructor
41//----------------------------------------------------------------------
42StringExtractor::StringExtractor() :
43 m_packet(),
44 m_index (0)
45{
46}
47
48
49StringExtractor::StringExtractor(const char *packet_cstr) :
50 m_packet(),
51 m_index (0)
52{
53 if (packet_cstr)
54 m_packet.assign (packet_cstr);
55}
56
57
58//----------------------------------------------------------------------
59// StringExtractor copy constructor
60//----------------------------------------------------------------------
61StringExtractor::StringExtractor(const StringExtractor& rhs) :
62 m_packet (rhs.m_packet),
63 m_index (rhs.m_index)
64{
65
66}
67
68//----------------------------------------------------------------------
69// StringExtractor assignment operator
70//----------------------------------------------------------------------
71const StringExtractor&
72StringExtractor::operator=(const StringExtractor& rhs)
73{
74 if (this != &rhs)
75 {
76 m_packet = rhs.m_packet;
77 m_index = rhs.m_index;
78
79 }
80 return *this;
81}
82
83//----------------------------------------------------------------------
84// Destructor
85//----------------------------------------------------------------------
86StringExtractor::~StringExtractor()
87{
88}
89
90
91char
92StringExtractor::GetChar (char fail_value)
93{
94 if (m_index < m_packet.size())
95 {
96 char ch = m_packet[m_index];
97 ++m_index;
98 return ch;
99 }
100 m_index = UINT32_MAX;
101 return fail_value;
102}
103
104uint32_t
105StringExtractor::GetNumHexASCIICharsAtFilePos (uint32_t max) const
106{
107 uint32_t idx = m_index;
108 const size_t size = m_packet.size();
109 while (idx < size && idx - m_index < max && isxdigit(m_packet[idx]))
110 ++idx;
111 return idx - m_index;
112}
113//----------------------------------------------------------------------
114// Extract a signed character from two hex ASCII chars in the packet
115// string
116//----------------------------------------------------------------------
117int8_t
118StringExtractor::GetHexS8 (int8_t fail_value)
119{
120 if (GetNumHexASCIICharsAtFilePos(2))
121 {
122 char hi_nibble_char = m_packet[m_index];
123 char lo_nibble_char = m_packet[m_index+1];
Greg Clayton7b70be32012-04-07 00:42:53 +0000124 char hi_nibble = xdigit_to_sint (hi_nibble_char);
125 char lo_nibble = xdigit_to_sint (lo_nibble_char);
126 m_index += 2;
127 return (hi_nibble << 4) + lo_nibble;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128 }
129 m_index = UINT32_MAX;
130 return fail_value;
131}
132
133//----------------------------------------------------------------------
134// Extract an unsigned character from two hex ASCII chars in the packet
135// string
136//----------------------------------------------------------------------
137uint8_t
Greg Clayton7b70be32012-04-07 00:42:53 +0000138StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000139{
140 if (GetNumHexASCIICharsAtFilePos(2))
141 {
142 uint8_t hi_nibble_char = m_packet[m_index];
143 uint8_t lo_nibble_char = m_packet[m_index+1];
Greg Clayton7b70be32012-04-07 00:42:53 +0000144 uint8_t hi_nibble = xdigit_to_uint (hi_nibble_char);
145 uint8_t lo_nibble = xdigit_to_uint (lo_nibble_char);
146 m_index += 2;
147 return (hi_nibble << 4) + lo_nibble;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000148 }
Greg Clayton7b70be32012-04-07 00:42:53 +0000149 if (set_eof_on_fail || m_index >= m_packet.size())
150 m_index = UINT32_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151 return fail_value;
152}
153
154uint32_t
Greg Clayton32e0a752011-03-30 18:16:51 +0000155StringExtractor::GetU32 (uint32_t fail_value, int base)
156{
157 if (m_index < m_packet.size())
158 {
159 char *end = NULL;
160 const char *start = m_packet.c_str();
161 const char *uint_cstr = start + m_index;
162 uint32_t result = ::strtoul (uint_cstr, &end, base);
163
164 if (end && end != uint_cstr)
165 {
166 m_index = end - start;
167 return result;
168 }
169 }
170 return fail_value;
171}
172
173
174uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000175StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
176{
177 uint32_t result = 0;
178 uint32_t nibble_count = 0;
179
180 if (little_endian)
181 {
182 uint32_t shift_amount = 0;
183 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
184 {
185 // Make sure we don't exceed the size of a uint32_t...
186 if (nibble_count >= (sizeof(uint32_t) * 2))
187 {
188 m_index = UINT32_MAX;
189 return fail_value;
190 }
191
192 uint8_t nibble_lo;
193 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
194 ++m_index;
195 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
196 {
197 nibble_lo = xdigit_to_sint (m_packet[m_index]);
198 ++m_index;
199 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
200 result |= ((uint32_t)nibble_lo << shift_amount);
201 nibble_count += 2;
202 shift_amount += 8;
203 }
204 else
205 {
206 result |= ((uint32_t)nibble_hi << shift_amount);
207 nibble_count += 1;
208 shift_amount += 4;
209 }
210
211 }
212 }
213 else
214 {
215 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
216 {
217 // Make sure we don't exceed the size of a uint32_t...
218 if (nibble_count >= (sizeof(uint32_t) * 2))
219 {
220 m_index = UINT32_MAX;
221 return fail_value;
222 }
223
224 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
225 // Big Endian
226 result <<= 4;
227 result |= nibble;
228
229 ++m_index;
230 ++nibble_count;
231 }
232 }
233 return result;
234}
235
236uint64_t
237StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
238{
239 uint64_t result = 0;
240 uint32_t nibble_count = 0;
241
242 if (little_endian)
243 {
244 uint32_t shift_amount = 0;
245 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
246 {
247 // Make sure we don't exceed the size of a uint64_t...
248 if (nibble_count >= (sizeof(uint64_t) * 2))
249 {
250 m_index = UINT32_MAX;
251 return fail_value;
252 }
253
254 uint8_t nibble_lo;
255 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
256 ++m_index;
257 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
258 {
259 nibble_lo = xdigit_to_sint (m_packet[m_index]);
260 ++m_index;
261 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
262 result |= ((uint64_t)nibble_lo << shift_amount);
263 nibble_count += 2;
264 shift_amount += 8;
265 }
266 else
267 {
268 result |= ((uint64_t)nibble_hi << shift_amount);
269 nibble_count += 1;
270 shift_amount += 4;
271 }
272
273 }
274 }
275 else
276 {
277 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
278 {
279 // Make sure we don't exceed the size of a uint64_t...
280 if (nibble_count >= (sizeof(uint64_t) * 2))
281 {
282 m_index = UINT32_MAX;
283 return fail_value;
284 }
285
286 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
287 // Big Endian
288 result <<= 4;
289 result |= nibble;
290
291 ++m_index;
292 ++nibble_count;
293 }
294 }
295 return result;
296}
297
298size_t
299StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
300{
301 uint8_t *dst = (uint8_t*)dst_void;
302 size_t bytes_extracted = 0;
303 while (bytes_extracted < dst_len && GetBytesLeft ())
304 {
305 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
306 if (IsGood())
307 ++bytes_extracted;
308 else
309 break;
310 }
311
312 for (size_t i = bytes_extracted; i < dst_len; ++i)
313 dst[i] = fail_fill_value;
314
315 return bytes_extracted;
316}
317
318
319// Consume ASCII hex nibble character pairs until we have decoded byte_size
320// bytes of data.
321
322uint64_t
323StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
324{
325 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
326 {
327 uint64_t result = 0;
328 uint32_t i;
329 if (little_endian)
330 {
331 // Little Endian
332 uint32_t shift_amount;
333 for (i = 0, shift_amount = 0;
334 i < byte_size && m_index != UINT32_MAX;
335 ++i, shift_amount += 8)
336 {
337 result |= ((uint64_t)GetHexU8() << shift_amount);
338 }
339 }
340 else
341 {
342 // Big Endian
343 for (i = 0; i < byte_size && m_index != UINT32_MAX; ++i)
344 {
345 result <<= 8;
346 result |= GetHexU8();
347 }
348 }
349 }
350 m_index = UINT32_MAX;
351 return fail_value;
352}
353
Greg Claytonde9d0492011-01-08 03:17:57 +0000354size_t
355StringExtractor::GetHexByteString (std::string &str)
356{
357 str.clear();
358 char ch;
359 while ((ch = GetHexU8()) != '\0')
360 str.append(1, ch);
361 return str.size();
362}
363
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364bool
365StringExtractor::GetNameColonValue (std::string &name, std::string &value)
366{
367 // Read something in the form of NNNN:VVVV; where NNNN is any character
368 // that is not a colon, followed by a ':' character, then a value (one or
369 // more ';' chars), followed by a ';'
370 if (m_index < m_packet.size())
371 {
372 const size_t colon_idx = m_packet.find (':', m_index);
373 if (colon_idx != std::string::npos)
374 {
375 const size_t semicolon_idx = m_packet.find (';', colon_idx);
376 if (semicolon_idx != std::string::npos)
377 {
378 name.assign (m_packet, m_index, colon_idx - m_index);
379 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
380 m_index = semicolon_idx + 1;
381 return true;
382 }
383 }
384 }
385 m_index = UINT32_MAX;
386 return false;
387}