]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / lldb / 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 "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 const uint8_t
20 g_hex_ascii_to_hex_integer[256] = {
21     
22     255, 255, 255, 255, 255, 255, 255, 255,
23     255, 255, 255, 255, 255, 255, 255, 255,
24     255, 255, 255, 255, 255, 255, 255, 255,
25     255, 255, 255, 255, 255, 255, 255, 255,
26     255, 255, 255, 255, 255, 255, 255, 255,
27     255, 255, 255, 255, 255, 255, 255, 255,
28     0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
29     0x8, 0x9, 255, 255, 255, 255, 255, 255,
30     255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255,
31     255, 255, 255, 255, 255, 255, 255, 255,
32     255, 255, 255, 255, 255, 255, 255, 255,
33     255, 255, 255, 255, 255, 255, 255, 255,
34     255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255,
35     255, 255, 255, 255, 255, 255, 255, 255,
36     255, 255, 255, 255, 255, 255, 255, 255,
37     255, 255, 255, 255, 255, 255, 255, 255,
38     255, 255, 255, 255, 255, 255, 255, 255,
39     255, 255, 255, 255, 255, 255, 255, 255,
40     255, 255, 255, 255, 255, 255, 255, 255,
41     255, 255, 255, 255, 255, 255, 255, 255,
42     255, 255, 255, 255, 255, 255, 255, 255,
43     255, 255, 255, 255, 255, 255, 255, 255,
44     255, 255, 255, 255, 255, 255, 255, 255,
45     255, 255, 255, 255, 255, 255, 255, 255,
46     255, 255, 255, 255, 255, 255, 255, 255,
47     255, 255, 255, 255, 255, 255, 255, 255,
48     255, 255, 255, 255, 255, 255, 255, 255,
49     255, 255, 255, 255, 255, 255, 255, 255,
50     255, 255, 255, 255, 255, 255, 255, 255,
51     255, 255, 255, 255, 255, 255, 255, 255,
52     255, 255, 255, 255, 255, 255, 255, 255,
53     255, 255, 255, 255, 255, 255, 255, 255,
54 };
55
56 static inline int
57 xdigit_to_sint (char ch)
58 {
59     if (ch >= 'a' && ch <= 'f')
60         return 10 + ch - 'a';
61     if (ch >= 'A' && ch <= 'F')
62         return 10 + ch - 'A';
63     return ch - '0';
64 }
65
66 static inline unsigned int
67 xdigit_to_uint (uint8_t ch)
68 {
69     if (ch >= 'a' && ch <= 'f')
70         return 10u + ch - 'a';
71     if (ch >= 'A' && ch <= 'F')
72         return 10u + ch - 'A';
73     return ch - '0';
74 }
75
76 //----------------------------------------------------------------------
77 // StringExtractor constructor
78 //----------------------------------------------------------------------
79 StringExtractor::StringExtractor() :
80     m_packet(),
81     m_index (0)
82 {
83 }
84
85
86 StringExtractor::StringExtractor(const char *packet_cstr) :
87     m_packet(),
88     m_index (0)
89 {
90     if (packet_cstr)
91         m_packet.assign (packet_cstr);
92 }
93
94
95 //----------------------------------------------------------------------
96 // StringExtractor copy constructor
97 //----------------------------------------------------------------------
98 StringExtractor::StringExtractor(const StringExtractor& rhs) :
99     m_packet (rhs.m_packet),
100     m_index (rhs.m_index)
101 {
102
103 }
104
105 //----------------------------------------------------------------------
106 // StringExtractor assignment operator
107 //----------------------------------------------------------------------
108 const StringExtractor&
109 StringExtractor::operator=(const StringExtractor& rhs)
110 {
111     if (this != &rhs)
112     {
113         m_packet = rhs.m_packet;
114         m_index = rhs.m_index;
115
116     }
117     return *this;
118 }
119
120 //----------------------------------------------------------------------
121 // Destructor
122 //----------------------------------------------------------------------
123 StringExtractor::~StringExtractor()
124 {
125 }
126
127
128 char
129 StringExtractor::GetChar (char fail_value)
130 {
131     if (m_index < m_packet.size())
132     {
133         char ch = m_packet[m_index];
134         ++m_index;
135         return ch;
136     }
137     m_index = UINT64_MAX;
138     return fail_value;
139 }
140
141 //----------------------------------------------------------------------
142 // Extract an unsigned character from two hex ASCII chars in the packet
143 // string
144 //----------------------------------------------------------------------
145 uint8_t
146 StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
147 {
148     if (GetBytesLeft() >= 2)
149     {
150         const uint8_t hi_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[m_index])];
151         const uint8_t lo_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[m_index+1])];
152         if (hi_nibble < 16 && lo_nibble < 16)
153         {
154             m_index += 2;
155             return (hi_nibble << 4) + lo_nibble;
156         }
157     }
158     if (set_eof_on_fail || m_index >= m_packet.size())
159         m_index = UINT64_MAX;
160     return fail_value;
161 }
162
163 uint32_t
164 StringExtractor::GetU32 (uint32_t fail_value, int base)
165 {
166     if (m_index < m_packet.size())
167     {
168         char *end = NULL;
169         const char *start = m_packet.c_str();
170         const char *cstr = start + m_index;
171         uint32_t result = ::strtoul (cstr, &end, base);
172
173         if (end && end != cstr)
174         {
175             m_index = end - start;
176             return result;
177         }
178     }
179     return fail_value;
180 }
181
182 int32_t
183 StringExtractor::GetS32 (int32_t fail_value, int base)
184 {
185     if (m_index < m_packet.size())
186     {
187         char *end = NULL;
188         const char *start = m_packet.c_str();
189         const char *cstr = start + m_index;
190         int32_t result = ::strtol (cstr, &end, base);
191         
192         if (end && end != cstr)
193         {
194             m_index = end - start;
195             return result;
196         }
197     }
198     return fail_value;
199 }
200
201
202 uint64_t
203 StringExtractor::GetU64 (uint64_t fail_value, int base)
204 {
205     if (m_index < m_packet.size())
206     {
207         char *end = NULL;
208         const char *start = m_packet.c_str();
209         const char *cstr = start + m_index;
210         uint64_t result = ::strtoull (cstr, &end, base);
211         
212         if (end && end != cstr)
213         {
214             m_index = end - start;
215             return result;
216         }
217     }
218     return fail_value;
219 }
220
221 int64_t
222 StringExtractor::GetS64 (int64_t fail_value, int base)
223 {
224     if (m_index < m_packet.size())
225     {
226         char *end = NULL;
227         const char *start = m_packet.c_str();
228         const char *cstr = start + m_index;
229         int64_t result = ::strtoll (cstr, &end, base);
230         
231         if (end && end != cstr)
232         {
233             m_index = end - start;
234             return result;
235         }
236     }
237     return fail_value;
238 }
239
240
241 uint32_t
242 StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
243 {
244     uint32_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 uint32_t...
253             if (nibble_count >= (sizeof(uint32_t) * 2))
254             {
255                 m_index = UINT64_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 |= ((uint32_t)nibble_hi << (shift_amount + 4));
267                 result |= ((uint32_t)nibble_lo << shift_amount);
268                 nibble_count += 2;
269                 shift_amount += 8;
270             }
271             else
272             {
273                 result |= ((uint32_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 uint32_t...
285             if (nibble_count >= (sizeof(uint32_t) * 2))
286             {
287                 m_index = UINT64_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
303 uint64_t
304 StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
305 {
306     uint64_t result = 0;
307     uint32_t nibble_count = 0;
308
309     if (little_endian)
310     {
311         uint32_t shift_amount = 0;
312         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
313         {
314             // Make sure we don't exceed the size of a uint64_t...
315             if (nibble_count >= (sizeof(uint64_t) * 2))
316             {
317                 m_index = UINT64_MAX;
318                 return fail_value;
319             }
320
321             uint8_t nibble_lo;
322             uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
323             ++m_index;
324             if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
325             {
326                 nibble_lo = xdigit_to_sint (m_packet[m_index]);
327                 ++m_index;
328                 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
329                 result |= ((uint64_t)nibble_lo << shift_amount);
330                 nibble_count += 2;
331                 shift_amount += 8;
332             }
333             else
334             {
335                 result |= ((uint64_t)nibble_hi << shift_amount);
336                 nibble_count += 1;
337                 shift_amount += 4;
338             }
339
340         }
341     }
342     else
343     {
344         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
345         {
346             // Make sure we don't exceed the size of a uint64_t...
347             if (nibble_count >= (sizeof(uint64_t) * 2))
348             {
349                 m_index = UINT64_MAX;
350                 return fail_value;
351             }
352
353             uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
354             // Big Endian
355             result <<= 4;
356             result |= nibble;
357
358             ++m_index;
359             ++nibble_count;
360         }
361     }
362     return result;
363 }
364
365 size_t
366 StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
367 {
368     uint8_t *dst = (uint8_t*)dst_void;
369     size_t bytes_extracted = 0;
370     while (bytes_extracted < dst_len && GetBytesLeft ())
371     {
372         dst[bytes_extracted] = GetHexU8 (fail_fill_value);
373         if (IsGood())
374             ++bytes_extracted;
375         else
376             break;
377     }
378
379     for (size_t i = bytes_extracted; i < dst_len; ++i)
380         dst[i] = fail_fill_value;
381
382     return bytes_extracted;
383 }
384
385
386 // Consume ASCII hex nibble character pairs until we have decoded byte_size
387 // bytes of data.
388
389 uint64_t
390 StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
391 {
392     if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
393     {
394         uint64_t result = 0;
395         uint32_t i;
396         if (little_endian)
397         {
398             // Little Endian
399             uint32_t shift_amount;
400             for (i = 0, shift_amount = 0;
401                  i < byte_size && IsGood();
402                  ++i, shift_amount += 8)
403             {
404                 result |= ((uint64_t)GetHexU8() << shift_amount);
405             }
406         }
407         else
408         {
409             // Big Endian
410             for (i = 0; i < byte_size && IsGood(); ++i)
411             {
412                 result <<= 8;
413                 result |= GetHexU8();
414             }
415         }
416     }
417     m_index = UINT64_MAX;
418     return fail_value;
419 }
420
421 size_t
422 StringExtractor::GetHexByteString (std::string &str)
423 {
424     str.clear();
425     char ch;
426     while ((ch = GetHexU8()) != '\0')
427         str.append(1, ch);
428     return str.size();
429 }
430
431 size_t
432 StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
433                                                char terminator)
434 {
435     str.clear();
436     char ch;
437     while ((ch = GetHexU8(0,false)) != '\0')
438         str.append(1, ch);
439     if (Peek() && *Peek() == terminator)
440         return str.size();
441     str.clear();
442     return str.size();
443 }
444
445 bool
446 StringExtractor::GetNameColonValue (std::string &name, std::string &value)
447 {
448     // Read something in the form of NNNN:VVVV; where NNNN is any character
449     // that is not a colon, followed by a ':' character, then a value (one or
450     // more ';' chars), followed by a ';'
451     if (m_index < m_packet.size())
452     {
453         const size_t colon_idx = m_packet.find (':', m_index);
454         if (colon_idx != std::string::npos)
455         {
456             const size_t semicolon_idx = m_packet.find (';', colon_idx);
457             if (semicolon_idx != std::string::npos)
458             {
459                 name.assign (m_packet, m_index, colon_idx - m_index);
460                 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
461                 m_index = semicolon_idx + 1;
462                 return true;
463             }
464         }
465     }
466     m_index = UINT64_MAX;
467     return false;
468 }