blob: dc1483d01cdae703d085c511698bd2c93fc311e3 [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
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16
17static inline int
18xdigit_to_sint (char ch)
19{
Chris Lattner30fdc8d2010-06-08 16:52:2420 if (ch >= 'a' && ch <= 'f')
21 return 10 + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:0522 if (ch >= 'A' && ch <= 'F')
23 return 10 + ch - 'A';
Chris Lattner30fdc8d2010-06-08 16:52:2424 return ch - '0';
25}
26
27static inline unsigned int
28xdigit_to_uint (uint8_t ch)
29{
Chris Lattner30fdc8d2010-06-08 16:52:2430 if (ch >= 'a' && ch <= 'f')
31 return 10u + ch - 'a';
Benjamin Kramer1e89cd82010-06-22 21:28:0532 if (ch >= 'A' && ch <= 'F')
33 return 10u + ch - 'A';
Chris Lattner30fdc8d2010-06-08 16:52:2434 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 {
149 uint8_t hi_nibble = xdigit_to_sint (hi_nibble_char);
150 uint8_t lo_nibble = xdigit_to_sint (lo_nibble_char);
151 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
160StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
161{
162 uint32_t result = 0;
163 uint32_t nibble_count = 0;
164
165 if (little_endian)
166 {
167 uint32_t shift_amount = 0;
168 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
169 {
170 // Make sure we don't exceed the size of a uint32_t...
171 if (nibble_count >= (sizeof(uint32_t) * 2))
172 {
173 m_index = UINT32_MAX;
174 return fail_value;
175 }
176
177 uint8_t nibble_lo;
178 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
179 ++m_index;
180 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
181 {
182 nibble_lo = xdigit_to_sint (m_packet[m_index]);
183 ++m_index;
184 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
185 result |= ((uint32_t)nibble_lo << shift_amount);
186 nibble_count += 2;
187 shift_amount += 8;
188 }
189 else
190 {
191 result |= ((uint32_t)nibble_hi << shift_amount);
192 nibble_count += 1;
193 shift_amount += 4;
194 }
195
196 }
197 }
198 else
199 {
200 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
201 {
202 // Make sure we don't exceed the size of a uint32_t...
203 if (nibble_count >= (sizeof(uint32_t) * 2))
204 {
205 m_index = UINT32_MAX;
206 return fail_value;
207 }
208
209 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
210 // Big Endian
211 result <<= 4;
212 result |= nibble;
213
214 ++m_index;
215 ++nibble_count;
216 }
217 }
218 return result;
219}
220
221uint64_t
222StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
223{
224 uint64_t result = 0;
225 uint32_t nibble_count = 0;
226
227 if (little_endian)
228 {
229 uint32_t shift_amount = 0;
230 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
231 {
232 // Make sure we don't exceed the size of a uint64_t...
233 if (nibble_count >= (sizeof(uint64_t) * 2))
234 {
235 m_index = UINT32_MAX;
236 return fail_value;
237 }
238
239 uint8_t nibble_lo;
240 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
241 ++m_index;
242 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
243 {
244 nibble_lo = xdigit_to_sint (m_packet[m_index]);
245 ++m_index;
246 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
247 result |= ((uint64_t)nibble_lo << shift_amount);
248 nibble_count += 2;
249 shift_amount += 8;
250 }
251 else
252 {
253 result |= ((uint64_t)nibble_hi << shift_amount);
254 nibble_count += 1;
255 shift_amount += 4;
256 }
257
258 }
259 }
260 else
261 {
262 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
263 {
264 // Make sure we don't exceed the size of a uint64_t...
265 if (nibble_count >= (sizeof(uint64_t) * 2))
266 {
267 m_index = UINT32_MAX;
268 return fail_value;
269 }
270
271 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
272 // Big Endian
273 result <<= 4;
274 result |= nibble;
275
276 ++m_index;
277 ++nibble_count;
278 }
279 }
280 return result;
281}
282
283size_t
284StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
285{
286 uint8_t *dst = (uint8_t*)dst_void;
287 size_t bytes_extracted = 0;
288 while (bytes_extracted < dst_len && GetBytesLeft ())
289 {
290 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
291 if (IsGood())
292 ++bytes_extracted;
293 else
294 break;
295 }
296
297 for (size_t i = bytes_extracted; i < dst_len; ++i)
298 dst[i] = fail_fill_value;
299
300 return bytes_extracted;
301}
302
303
304// Consume ASCII hex nibble character pairs until we have decoded byte_size
305// bytes of data.
306
307uint64_t
308StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
309{
310 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
311 {
312 uint64_t result = 0;
313 uint32_t i;
314 if (little_endian)
315 {
316 // Little Endian
317 uint32_t shift_amount;
318 for (i = 0, shift_amount = 0;
319 i < byte_size && m_index != UINT32_MAX;
320 ++i, shift_amount += 8)
321 {
322 result |= ((uint64_t)GetHexU8() << shift_amount);
323 }
324 }
325 else
326 {
327 // Big Endian
328 for (i = 0; i < byte_size && m_index != UINT32_MAX; ++i)
329 {
330 result <<= 8;
331 result |= GetHexU8();
332 }
333 }
334 }
335 m_index = UINT32_MAX;
336 return fail_value;
337}
338
339bool
340StringExtractor::GetNameColonValue (std::string &name, std::string &value)
341{
342 // Read something in the form of NNNN:VVVV; where NNNN is any character
343 // that is not a colon, followed by a ':' character, then a value (one or
344 // more ';' chars), followed by a ';'
345 if (m_index < m_packet.size())
346 {
347 const size_t colon_idx = m_packet.find (':', m_index);
348 if (colon_idx != std::string::npos)
349 {
350 const size_t semicolon_idx = m_packet.find (';', colon_idx);
351 if (semicolon_idx != std::string::npos)
352 {
353 name.assign (m_packet, m_index, colon_idx - m_index);
354 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
355 m_index = semicolon_idx + 1;
356 return true;
357 }
358 }
359 }
360 m_index = UINT32_MAX;
361 return false;
362}