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