blob: 5152f3e21276d61091d84f1032f643aded1c3911 [file] [log] [blame]
Zachary Turner44c35e82016-08-29 19:45:59 +00001//===-- StdStringExtractor.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 "lldb/Utility/StdStringExtractor.h"
11
12// C Includes
13#include <stdlib.h>
14
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18
19static inline int
20xdigit_to_sint (char ch)
21{
22 if (ch >= 'a' && ch <= 'f')
23 return 10 + ch - 'a';
24 if (ch >= 'A' && ch <= 'F')
25 return 10 + ch - 'A';
26 if (ch >= '0' && ch <= '9')
27 return ch - '0';
28 return -1;
29}
30
31//----------------------------------------------------------------------
32// StdStringExtractor constructor
33//----------------------------------------------------------------------
34StdStringExtractor::StdStringExtractor() :
35 m_packet(),
36 m_index (0)
37{
38}
39
40
41StdStringExtractor::StdStringExtractor(const char *packet_cstr) :
42 m_packet(),
43 m_index (0)
44{
45 if (packet_cstr)
46 m_packet.assign (packet_cstr);
47}
48
49
50//----------------------------------------------------------------------
51// StdStringExtractor copy constructor
52//----------------------------------------------------------------------
53StdStringExtractor::StdStringExtractor(const StdStringExtractor& rhs) :
54 m_packet (rhs.m_packet),
55 m_index (rhs.m_index)
56{
57
58}
59
60//----------------------------------------------------------------------
61// StdStringExtractor assignment operator
62//----------------------------------------------------------------------
63const StdStringExtractor&
64StdStringExtractor::operator=(const StdStringExtractor& rhs)
65{
66 if (this != &rhs)
67 {
68 m_packet = rhs.m_packet;
69 m_index = rhs.m_index;
70
71 }
72 return *this;
73}
74
75//----------------------------------------------------------------------
76// Destructor
77//----------------------------------------------------------------------
78StdStringExtractor::~StdStringExtractor()
79{
80}
81
82
83char
84StdStringExtractor::GetChar (char fail_value)
85{
86 if (m_index < m_packet.size())
87 {
88 char ch = m_packet[m_index];
89 ++m_index;
90 return ch;
91 }
92 m_index = UINT64_MAX;
93 return fail_value;
94}
95
96//----------------------------------------------------------------------
97// If a pair of valid hex digits exist at the head of the
98// StdStringExtractor they are decoded into an unsigned byte and returned
99// by this function
100//
101// If there is not a pair of valid hex digits at the head of the
102// StdStringExtractor, it is left unchanged and -1 is returned
103//----------------------------------------------------------------------
104int
105StdStringExtractor::DecodeHexU8()
106{
107 SkipSpaces();
108 if (GetBytesLeft() < 2)
109 {
110 return -1;
111 }
112 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
113 const int lo_nibble = xdigit_to_sint(m_packet[m_index+1]);
114 if (hi_nibble == -1 || lo_nibble == -1)
115 {
116 return -1;
117 }
118 m_index += 2;
119 return (uint8_t)((hi_nibble << 4) + lo_nibble);
120}
121
122//----------------------------------------------------------------------
123// Extract an unsigned character from two hex ASCII chars in the packet
124// string, or return fail_value on failure
125//----------------------------------------------------------------------
126uint8_t
127StdStringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
128{
129 // On success, fail_value will be overwritten with the next
130 // character in the stream
131 GetHexU8Ex(fail_value, set_eof_on_fail);
132 return fail_value;
133}
134
135bool
136StdStringExtractor::GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail)
137{
138 int byte = DecodeHexU8();
139 if (byte == -1)
140 {
141 if (set_eof_on_fail || m_index >= m_packet.size())
142 m_index = UINT64_MAX;
143 // ch should not be changed in case of failure
144 return false;
145 }
146 ch = (uint8_t)byte;
147 return true;
148}
149
150uint32_t
151StdStringExtractor::GetU32 (uint32_t fail_value, int base)
152{
153 if (m_index < m_packet.size())
154 {
155 char *end = nullptr;
156 const char *start = m_packet.c_str();
157 const char *cstr = start + m_index;
158 uint32_t result = static_cast<uint32_t>(::strtoul (cstr, &end, base));
159
160 if (end && end != cstr)
161 {
162 m_index = end - start;
163 return result;
164 }
165 }
166 return fail_value;
167}
168
169int32_t
170StdStringExtractor::GetS32 (int32_t fail_value, int base)
171{
172 if (m_index < m_packet.size())
173 {
174 char *end = nullptr;
175 const char *start = m_packet.c_str();
176 const char *cstr = start + m_index;
177 int32_t result = static_cast<int32_t>(::strtol (cstr, &end, base));
178
179 if (end && end != cstr)
180 {
181 m_index = end - start;
182 return result;
183 }
184 }
185 return fail_value;
186}
187
188
189uint64_t
190StdStringExtractor::GetU64 (uint64_t fail_value, int base)
191{
192 if (m_index < m_packet.size())
193 {
194 char *end = nullptr;
195 const char *start = m_packet.c_str();
196 const char *cstr = start + m_index;
197 uint64_t result = ::strtoull (cstr, &end, base);
198
199 if (end && end != cstr)
200 {
201 m_index = end - start;
202 return result;
203 }
204 }
205 return fail_value;
206}
207
208int64_t
209StdStringExtractor::GetS64 (int64_t fail_value, int base)
210{
211 if (m_index < m_packet.size())
212 {
213 char *end = nullptr;
214 const char *start = m_packet.c_str();
215 const char *cstr = start + m_index;
216 int64_t result = ::strtoll (cstr, &end, base);
217
218 if (end && end != cstr)
219 {
220 m_index = end - start;
221 return result;
222 }
223 }
224 return fail_value;
225}
226
227
228uint32_t
229StdStringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
230{
231 uint32_t result = 0;
232 uint32_t nibble_count = 0;
233
234 SkipSpaces();
235 if (little_endian)
236 {
237 uint32_t shift_amount = 0;
238 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
239 {
240 // Make sure we don't exceed the size of a uint32_t...
241 if (nibble_count >= (sizeof(uint32_t) * 2))
242 {
243 m_index = UINT64_MAX;
244 return fail_value;
245 }
246
247 uint8_t nibble_lo;
248 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
249 ++m_index;
250 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
251 {
252 nibble_lo = xdigit_to_sint (m_packet[m_index]);
253 ++m_index;
254 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
255 result |= ((uint32_t)nibble_lo << shift_amount);
256 nibble_count += 2;
257 shift_amount += 8;
258 }
259 else
260 {
261 result |= ((uint32_t)nibble_hi << shift_amount);
262 nibble_count += 1;
263 shift_amount += 4;
264 }
265
266 }
267 }
268 else
269 {
270 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
271 {
272 // Make sure we don't exceed the size of a uint32_t...
273 if (nibble_count >= (sizeof(uint32_t) * 2))
274 {
275 m_index = UINT64_MAX;
276 return fail_value;
277 }
278
279 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
280 // Big Endian
281 result <<= 4;
282 result |= nibble;
283
284 ++m_index;
285 ++nibble_count;
286 }
287 }
288 return result;
289}
290
291uint64_t
292StdStringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
293{
294 uint64_t result = 0;
295 uint32_t nibble_count = 0;
296
297 SkipSpaces();
298 if (little_endian)
299 {
300 uint32_t shift_amount = 0;
301 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
302 {
303 // Make sure we don't exceed the size of a uint64_t...
304 if (nibble_count >= (sizeof(uint64_t) * 2))
305 {
306 m_index = UINT64_MAX;
307 return fail_value;
308 }
309
310 uint8_t nibble_lo;
311 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
312 ++m_index;
313 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
314 {
315 nibble_lo = xdigit_to_sint (m_packet[m_index]);
316 ++m_index;
317 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
318 result |= ((uint64_t)nibble_lo << shift_amount);
319 nibble_count += 2;
320 shift_amount += 8;
321 }
322 else
323 {
324 result |= ((uint64_t)nibble_hi << shift_amount);
325 nibble_count += 1;
326 shift_amount += 4;
327 }
328
329 }
330 }
331 else
332 {
333 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
334 {
335 // Make sure we don't exceed the size of a uint64_t...
336 if (nibble_count >= (sizeof(uint64_t) * 2))
337 {
338 m_index = UINT64_MAX;
339 return fail_value;
340 }
341
342 uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
343 // Big Endian
344 result <<= 4;
345 result |= nibble;
346
347 ++m_index;
348 ++nibble_count;
349 }
350 }
351 return result;
352}
353
354size_t
355StdStringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
356{
357 uint8_t *dst = (uint8_t*)dst_void;
358 size_t bytes_extracted = 0;
359 while (bytes_extracted < dst_len && GetBytesLeft ())
360 {
361 dst[bytes_extracted] = GetHexU8 (fail_fill_value);
362 if (IsGood())
363 ++bytes_extracted;
364 else
365 break;
366 }
367
368 for (size_t i = bytes_extracted; i < dst_len; ++i)
369 dst[i] = fail_fill_value;
370
371 return bytes_extracted;
372}
373
374//----------------------------------------------------------------------
375// Decodes all valid hex encoded bytes at the head of the
376// StdStringExtractor, limited by dst_len.
377//
378// Returns the number of bytes successfully decoded
379//----------------------------------------------------------------------
380size_t
381StdStringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len)
382{
383 uint8_t *dst = (uint8_t*)dst_void;
384 size_t bytes_extracted = 0;
385 while (bytes_extracted < dst_len)
386 {
387 int decode = DecodeHexU8();
388 if (decode == -1)
389 {
390 break;
391 }
392 dst[bytes_extracted++] = (uint8_t)decode;
393 }
394 return bytes_extracted;
395}
396
397// Consume ASCII hex nibble character pairs until we have decoded byte_size
398// bytes of data.
399
400uint64_t
401StdStringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
402{
403 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
404 {
405 uint64_t result = 0;
406 uint32_t i;
407 if (little_endian)
408 {
409 // Little Endian
410 uint32_t shift_amount;
411 for (i = 0, shift_amount = 0;
412 i < byte_size && IsGood();
413 ++i, shift_amount += 8)
414 {
415 result |= ((uint64_t)GetHexU8() << shift_amount);
416 }
417 }
418 else
419 {
420 // Big Endian
421 for (i = 0; i < byte_size && IsGood(); ++i)
422 {
423 result <<= 8;
424 result |= GetHexU8();
425 }
426 }
427 }
428 m_index = UINT64_MAX;
429 return fail_value;
430}
431
432size_t
433StdStringExtractor::GetHexByteString (std::string &str)
434{
435 str.clear();
436 str.reserve(GetBytesLeft() / 2);
437 char ch;
438 while ((ch = GetHexU8()) != '\0')
439 str.append(1, ch);
440 return str.size();
441}
442
443size_t
444StdStringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
445{
446 str.clear();
447
448 uint32_t nibble_count = 0;
449 for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
450 {}
451
452 return str.size();
453}
454
455size_t
456StdStringExtractor::GetHexByteStringTerminatedBy (std::string &str,
457 char terminator)
458{
459 str.clear();
460 char ch;
461 while ((ch = GetHexU8(0,false)) != '\0')
462 str.append(1, ch);
463 if (Peek() && *Peek() == terminator)
464 return str.size();
465
466 str.clear();
467 return str.size();
468}
469
470bool
471StdStringExtractor::GetNameColonValue (std::string &name, std::string &value)
472{
473 // Read something in the form of NNNN:VVVV; where NNNN is any character
474 // that is not a colon, followed by a ':' character, then a value (one or
475 // more ';' chars), followed by a ';'
476 if (m_index < m_packet.size())
477 {
478 const size_t colon_idx = m_packet.find (':', m_index);
479 if (colon_idx != std::string::npos)
480 {
481 const size_t semicolon_idx = m_packet.find (';', colon_idx);
482 if (semicolon_idx != std::string::npos)
483 {
484 name.assign (m_packet, m_index, colon_idx - m_index);
485 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
486 m_index = semicolon_idx + 1;
487 return true;
488 }
489 }
490 }
491 m_index = UINT64_MAX;
492 return false;
493}
494
495void
496StdStringExtractor::SkipSpaces ()
497{
498 const size_t n = m_packet.size();
499 while (m_index < n && isspace(m_packet[m_index]))
500 ++m_index;
501}
502