]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Utility/StringExtractor.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / source / Utility / StringExtractor.cpp
1 //===-- 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 "lldb/Utility/StringExtractor.h"
11
12 // C Includes
13 #include <stdlib.h>
14
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18
19 static inline int
20 xdigit_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 // StringExtractor constructor
33 //----------------------------------------------------------------------
34 StringExtractor::StringExtractor() :
35     m_packet(),
36     m_index (0)
37 {
38 }
39
40
41 StringExtractor::StringExtractor(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 // StringExtractor copy constructor
52 //----------------------------------------------------------------------
53 StringExtractor::StringExtractor(const StringExtractor& rhs) :
54     m_packet (rhs.m_packet),
55     m_index (rhs.m_index)
56 {
57
58 }
59
60 //----------------------------------------------------------------------
61 // StringExtractor assignment operator
62 //----------------------------------------------------------------------
63 const StringExtractor&
64 StringExtractor::operator=(const StringExtractor& 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 //----------------------------------------------------------------------
78 StringExtractor::~StringExtractor()
79 {
80 }
81
82
83 char
84 StringExtractor::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 // StringExtractor 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 // StringExtractor, it is left unchanged and -1 is returned
103 //----------------------------------------------------------------------
104 int
105 StringExtractor::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 //----------------------------------------------------------------------
126 uint8_t
127 StringExtractor::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
135 bool
136 StringExtractor::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
150 uint32_t
151 StringExtractor::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
169 int32_t
170 StringExtractor::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
189 uint64_t
190 StringExtractor::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
208 int64_t
209 StringExtractor::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
228 uint32_t
229 StringExtractor::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
291 uint64_t
292 StringExtractor::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
354 size_t
355 StringExtractor::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 // StringExtractor, limited by dst_len.
377 //
378 // Returns the number of bytes successfully decoded
379 //----------------------------------------------------------------------
380 size_t
381 StringExtractor::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
400 uint64_t
401 StringExtractor::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
432 size_t
433 StringExtractor::GetHexByteString (std::string &str)
434 {
435     str.clear();
436     char ch;
437     while ((ch = GetHexU8()) != '\0')
438         str.append(1, ch);
439     return str.size();
440 }
441
442 size_t
443 StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
444 {
445     str.clear();
446
447     uint32_t nibble_count = 0;
448     for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
449     {}
450
451     return str.size();
452 }
453
454 size_t
455 StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
456                                                char terminator)
457 {
458     str.clear();
459     char ch;
460     while ((ch = GetHexU8(0,false)) != '\0')
461         str.append(1, ch);
462     if (Peek() && *Peek() == terminator)
463         return str.size();
464
465     str.clear();
466     return str.size();
467 }
468
469 bool
470 StringExtractor::GetNameColonValue (std::string &name, std::string &value)
471 {
472     // Read something in the form of NNNN:VVVV; where NNNN is any character
473     // that is not a colon, followed by a ':' character, then a value (one or
474     // more ';' chars), followed by a ';'
475     if (m_index < m_packet.size())
476     {
477         const size_t colon_idx = m_packet.find (':', m_index);
478         if (colon_idx != std::string::npos)
479         {
480             const size_t semicolon_idx = m_packet.find (';', colon_idx);
481             if (semicolon_idx != std::string::npos)
482             {
483                 name.assign (m_packet, m_index, colon_idx - m_index);
484                 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
485                 m_index = semicolon_idx + 1;
486                 return true;
487             }
488         }
489     }
490     m_index = UINT64_MAX;
491     return false;
492 }
493
494 void
495 StringExtractor::SkipSpaces ()
496 {
497     const size_t n = m_packet.size();
498     while (m_index < n && isspace(m_packet[m_index]))
499         ++m_index;
500 }
501