blob: 96ced320302f14cefd3f93fb98d828344e373353 [file] [log] [blame]
Chris Lattner24943d22010-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 Clayton54e7afa2010-07-09 20:39:50 +000010#include "Utility/StringExtractor.h"
Chris Lattner24943d22010-06-08 16:52:24 +000011
12// C Includes
Stephen Wilson7a198ac2011-04-07 10:20:23 +000013#include <stdlib.h>
14
Chris Lattner24943d22010-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 Lattner24943d22010-06-08 16:52:24 +000022 if (ch >= 'a' && ch <= 'f')
23 return 10 + ch - 'a';
Benjamin Kramer0b145ba2010-06-22 21:28:05 +000024 if (ch >= 'A' && ch <= 'F')
25 return 10 + ch - 'A';
Chris Lattner24943d22010-06-08 16:52:24 +000026 return ch - '0';
27}
28
29static inline unsigned int
30xdigit_to_uint (uint8_t ch)
31{
Chris Lattner24943d22010-06-08 16:52:24 +000032 if (ch >= 'a' && ch <= 'f')
33 return 10u + ch - 'a';
Benjamin Kramer0b145ba2010-06-22 21:28:05 +000034 if (ch >= 'A' && ch <= 'F')
35 return 10u + ch - 'A';
Chris Lattner24943d22010-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];
124
125 if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
126 {
127 char hi_nibble = xdigit_to_sint (hi_nibble_char);
128 char lo_nibble = xdigit_to_sint (lo_nibble_char);
129 m_index += 2;
130 return (hi_nibble << 4) + lo_nibble;
131 }
132 }
133 m_index = UINT32_MAX;
134 return fail_value;
135}
136
137//----------------------------------------------------------------------
138// Extract an unsigned character from two hex ASCII chars in the packet
139// string
140//----------------------------------------------------------------------
141uint8_t
142StringExtractor::GetHexU8 (uint8_t fail_value)
143{
144 if (GetNumHexASCIICharsAtFilePos(2))
145 {
146 uint8_t hi_nibble_char = m_packet[m_index];
147 uint8_t lo_nibble_char = m_packet[m_index+1];
148
149 if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
150 {
Greg Claytona2f74232011-02-24 22:24:29 +0000151 uint8_t hi_nibble = xdigit_to_uint (hi_nibble_char);
152 uint8_t lo_nibble = xdigit_to_uint (lo_nibble_char);
Chris Lattner24943d22010-06-08 16:52:24 +0000153 m_index += 2;
154 return (hi_nibble << 4) + lo_nibble;
155 }
156 }
157 m_index = UINT32_MAX;
158 return fail_value;
159}
160
161uint32_t
Greg Clayton24bc5d92011-03-30 18:16:51 +0000162StringExtractor::GetU32 (uint32_t fail_value, int base)
163{
164 if (m_index < m_packet.size())
165 {
166 char *end = NULL;
167 const char *start = m_packet.c_str();
168 const char *uint_cstr = start + m_index;
169 uint32_t result = ::strtoul (uint_cstr, &end, base);
170
171 if (end && end != uint_cstr)
172 {
173 m_index = end - start;
174 return result;
175 }
176 }
177 return fail_value;
178}
179
180
181uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000182StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
183{
184 uint32_t result = 0;
185 uint32_t nibble_count = 0;
186
187 if (little_endian)
188 {
189 uint32_t shift_amount = 0;
190 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
191 {
192 // Make sure we don't exceed the size of a uint32_t...
193 if (nibble_count >= (sizeof(uint32_t) * 2))
194 {
195 m_index = UINT32_MAX;
196 return fail_value;
197 }
198
199 uint8_t nibble_lo;
200 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
201 ++m_index;
202 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
203 {
204 nibble_lo = xdigit_to_sint (m_packet[m_index]);
205 ++m_index;
206 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
207 result |= ((uint32_t)nibble_lo << shift_amount);
208 nibble_count += 2;
209 shift_amount += 8;
210 }
211 else
212 {
213 result |= ((uint32_t)nibble_hi << shift_amount);
214 nibble_count += 1;
215 shift_amount += 4;
216 }
217
218 }
219 }
220 else
221 {
222 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
223 {
224 // Make sure we don't exceed the size of a uint32_t...
225 if (nibble_count >= (sizeof(uint32_t) * 2))
226 {
227 m_index = UINT32_MAX;
228 return fail_value;
229 }
230
231 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
232 // Big Endian
233 result <<= 4;
234 result |= nibble;
235
236 ++m_index;
237 ++nibble_count;
238 }
239 }
240 return result;
241}
242
243uint64_t
244StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
245{
246 uint64_t result = 0;
247 uint32_t nibble_count = 0;
248
249 if (little_endian)
250 {
251 uint32_t shift_amount = 0;
252 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
253 {
254 // Make sure we don't exceed the size of a uint64_t...
255 if (nibble_count >= (sizeof(uint64_t) * 2))
256 {
257 m_index = UINT32_MAX;
258 return fail_value;
259 }
260
261 uint8_t nibble_lo;
262 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
263 ++m_index;
264 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
265 {
266 nibble_lo = xdigit_to_sint (m_packet[m_index]);
267 ++m_index;
268 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
269 result |= ((uint64_t)nibble_lo << shift_amount);
270 nibble_count += 2;
271 shift_amount += 8;
272 }
273 else
274 {
275 result |= ((uint64_t)nibble_hi << shift_amount);
276 nibble_count += 1;
277 shift_amount += 4;
278 }
279
280 }
281 }
282 else
283 {
284 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
285 {
286 // Make sure we don't exceed the size of a uint64_t...
287 if (nibble_count >= (sizeof(uint64_t) * 2))
288 {
289 m_index = UINT32_MAX;
290 return fail_value;
291 }
292
293 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
294 // Big Endian
295 result <<= 4;
296 result |= nibble;
297
298 ++m_index;
299 ++nibble_count;
300 }
301 }
302 return result;
303}
304
305size_t
306StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
307{
308 uint8_t *dst = (uint8_t*)dst_void;
309 size_t bytes_extracted = 0;
310 while (bytes_extracted < dst_len && GetBytesLeft ())
311 {
312 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
313 if (IsGood())
314 ++bytes_extracted;
315 else
316 break;
317 }
318
319 for (size_t i = bytes_extracted; i < dst_len; ++i)
320 dst[i] = fail_fill_value;
321
322 return bytes_extracted;
323}
324
325
326// Consume ASCII hex nibble character pairs until we have decoded byte_size
327// bytes of data.
328
329uint64_t
330StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
331{
332 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
333 {
334 uint64_t result = 0;
335 uint32_t i;
336 if (little_endian)
337 {
338 // Little Endian
339 uint32_t shift_amount;
340 for (i = 0, shift_amount = 0;
341 i < byte_size && m_index != UINT32_MAX;
342 ++i, shift_amount += 8)
343 {
344 result |= ((uint64_t)GetHexU8() << shift_amount);
345 }
346 }
347 else
348 {
349 // Big Endian
350 for (i = 0; i < byte_size && m_index != UINT32_MAX; ++i)
351 {
352 result <<= 8;
353 result |= GetHexU8();
354 }
355 }
356 }
357 m_index = UINT32_MAX;
358 return fail_value;
359}
360
Greg Clayton4862fa22011-01-08 03:17:57 +0000361size_t
362StringExtractor::GetHexByteString (std::string &str)
363{
364 str.clear();
365 char ch;
366 while ((ch = GetHexU8()) != '\0')
367 str.append(1, ch);
368 return str.size();
369}
370
Chris Lattner24943d22010-06-08 16:52:24 +0000371bool
372StringExtractor::GetNameColonValue (std::string &name, std::string &value)
373{
374 // Read something in the form of NNNN:VVVV; where NNNN is any character
375 // that is not a colon, followed by a ':' character, then a value (one or
376 // more ';' chars), followed by a ';'
377 if (m_index < m_packet.size())
378 {
379 const size_t colon_idx = m_packet.find (':', m_index);
380 if (colon_idx != std::string::npos)
381 {
382 const size_t semicolon_idx = m_packet.find (';', colon_idx);
383 if (semicolon_idx != std::string::npos)
384 {
385 name.assign (m_packet, m_index, colon_idx - m_index);
386 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
387 m_index = semicolon_idx + 1;
388 return true;
389 }
390 }
391 }
392 m_index = UINT32_MAX;
393 return false;
394}