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