]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp
Update LLDB snapshot to upstream r225923 (git 2b588ecd)
[FreeBSD/FreeBSD.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 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     if (GetBytesLeft() < 2)
108     {
109         return -1;
110     }
111     const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
112     const int lo_nibble = xdigit_to_sint(m_packet[m_index+1]);
113     if (hi_nibble == -1 || lo_nibble == -1)
114     {
115         return -1;
116     }
117     m_index += 2;
118     return (uint8_t)((hi_nibble << 4) + lo_nibble);
119 }
120
121 //----------------------------------------------------------------------
122 // Extract an unsigned character from two hex ASCII chars in the packet
123 // string
124 //----------------------------------------------------------------------
125 uint8_t
126 StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
127 {
128     int byte = DecodeHexU8();
129     if (byte == -1)
130     {
131         if (set_eof_on_fail || m_index >= m_packet.size())
132             m_index = UINT64_MAX;
133         return fail_value;
134     }
135     return (uint8_t)byte;
136 }
137
138 uint32_t
139 StringExtractor::GetU32 (uint32_t fail_value, int base)
140 {
141     if (m_index < m_packet.size())
142     {
143         char *end = nullptr;
144         const char *start = m_packet.c_str();
145         const char *cstr = start + m_index;
146         uint32_t result = ::strtoul (cstr, &end, base);
147
148         if (end && end != cstr)
149         {
150             m_index = end - start;
151             return result;
152         }
153     }
154     return fail_value;
155 }
156
157 int32_t
158 StringExtractor::GetS32 (int32_t fail_value, int base)
159 {
160     if (m_index < m_packet.size())
161     {
162         char *end = nullptr;
163         const char *start = m_packet.c_str();
164         const char *cstr = start + m_index;
165         int32_t result = ::strtol (cstr, &end, base);
166         
167         if (end && end != cstr)
168         {
169             m_index = end - start;
170             return result;
171         }
172     }
173     return fail_value;
174 }
175
176
177 uint64_t
178 StringExtractor::GetU64 (uint64_t fail_value, int base)
179 {
180     if (m_index < m_packet.size())
181     {
182         char *end = nullptr;
183         const char *start = m_packet.c_str();
184         const char *cstr = start + m_index;
185         uint64_t result = ::strtoull (cstr, &end, base);
186         
187         if (end && end != cstr)
188         {
189             m_index = end - start;
190             return result;
191         }
192     }
193     return fail_value;
194 }
195
196 int64_t
197 StringExtractor::GetS64 (int64_t fail_value, int base)
198 {
199     if (m_index < m_packet.size())
200     {
201         char *end = nullptr;
202         const char *start = m_packet.c_str();
203         const char *cstr = start + m_index;
204         int64_t result = ::strtoll (cstr, &end, base);
205         
206         if (end && end != cstr)
207         {
208             m_index = end - start;
209             return result;
210         }
211     }
212     return fail_value;
213 }
214
215
216 uint32_t
217 StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
218 {
219     uint32_t result = 0;
220     uint32_t nibble_count = 0;
221
222     if (little_endian)
223     {
224         uint32_t shift_amount = 0;
225         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
226         {
227             // Make sure we don't exceed the size of a uint32_t...
228             if (nibble_count >= (sizeof(uint32_t) * 2))
229             {
230                 m_index = UINT64_MAX;
231                 return fail_value;
232             }
233
234             uint8_t nibble_lo;
235             uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
236             ++m_index;
237             if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
238             {
239                 nibble_lo = xdigit_to_sint (m_packet[m_index]);
240                 ++m_index;
241                 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
242                 result |= ((uint32_t)nibble_lo << shift_amount);
243                 nibble_count += 2;
244                 shift_amount += 8;
245             }
246             else
247             {
248                 result |= ((uint32_t)nibble_hi << shift_amount);
249                 nibble_count += 1;
250                 shift_amount += 4;
251             }
252
253         }
254     }
255     else
256     {
257         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
258         {
259             // Make sure we don't exceed the size of a uint32_t...
260             if (nibble_count >= (sizeof(uint32_t) * 2))
261             {
262                 m_index = UINT64_MAX;
263                 return fail_value;
264             }
265
266             uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
267             // Big Endian
268             result <<= 4;
269             result |= nibble;
270
271             ++m_index;
272             ++nibble_count;
273         }
274     }
275     return result;
276 }
277
278 uint64_t
279 StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
280 {
281     uint64_t result = 0;
282     uint32_t nibble_count = 0;
283
284     if (little_endian)
285     {
286         uint32_t shift_amount = 0;
287         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
288         {
289             // Make sure we don't exceed the size of a uint64_t...
290             if (nibble_count >= (sizeof(uint64_t) * 2))
291             {
292                 m_index = UINT64_MAX;
293                 return fail_value;
294             }
295
296             uint8_t nibble_lo;
297             uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
298             ++m_index;
299             if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
300             {
301                 nibble_lo = xdigit_to_sint (m_packet[m_index]);
302                 ++m_index;
303                 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
304                 result |= ((uint64_t)nibble_lo << shift_amount);
305                 nibble_count += 2;
306                 shift_amount += 8;
307             }
308             else
309             {
310                 result |= ((uint64_t)nibble_hi << shift_amount);
311                 nibble_count += 1;
312                 shift_amount += 4;
313             }
314
315         }
316     }
317     else
318     {
319         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
320         {
321             // Make sure we don't exceed the size of a uint64_t...
322             if (nibble_count >= (sizeof(uint64_t) * 2))
323             {
324                 m_index = UINT64_MAX;
325                 return fail_value;
326             }
327
328             uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
329             // Big Endian
330             result <<= 4;
331             result |= nibble;
332
333             ++m_index;
334             ++nibble_count;
335         }
336     }
337     return result;
338 }
339
340 size_t
341 StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
342 {
343     uint8_t *dst = (uint8_t*)dst_void;
344     size_t bytes_extracted = 0;
345     while (bytes_extracted < dst_len && GetBytesLeft ())
346     {
347         dst[bytes_extracted] = GetHexU8 (fail_fill_value);
348         if (IsGood())
349             ++bytes_extracted;
350         else
351             break;
352     }
353
354     for (size_t i = bytes_extracted; i < dst_len; ++i)
355         dst[i] = fail_fill_value;
356
357     return bytes_extracted;
358 }
359
360 //----------------------------------------------------------------------
361 // Decodes all valid hex encoded bytes at the head of the
362 // StringExtractor, limited by dst_len.
363 //
364 // Returns the number of bytes successfully decoded
365 //----------------------------------------------------------------------
366 size_t
367 StringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len)
368 {
369     uint8_t *dst = (uint8_t*)dst_void;
370     size_t bytes_extracted = 0;
371     while (bytes_extracted < dst_len)
372     {
373         int decode = DecodeHexU8();
374         if (decode == -1)
375         {
376             break;
377         }
378         dst[bytes_extracted++] = (uint8_t)decode;
379     }
380     return bytes_extracted;
381 }
382
383 // Consume ASCII hex nibble character pairs until we have decoded byte_size
384 // bytes of data.
385
386 uint64_t
387 StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
388 {
389     if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
390     {
391         uint64_t result = 0;
392         uint32_t i;
393         if (little_endian)
394         {
395             // Little Endian
396             uint32_t shift_amount;
397             for (i = 0, shift_amount = 0;
398                  i < byte_size && IsGood();
399                  ++i, shift_amount += 8)
400             {
401                 result |= ((uint64_t)GetHexU8() << shift_amount);
402             }
403         }
404         else
405         {
406             // Big Endian
407             for (i = 0; i < byte_size && IsGood(); ++i)
408             {
409                 result <<= 8;
410                 result |= GetHexU8();
411             }
412         }
413     }
414     m_index = UINT64_MAX;
415     return fail_value;
416 }
417
418 size_t
419 StringExtractor::GetHexByteString (std::string &str)
420 {
421     str.clear();
422     char ch;
423     while ((ch = GetHexU8()) != '\0')
424         str.append(1, ch);
425     return str.size();
426 }
427
428 size_t
429 StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
430 {
431     str.clear();
432
433     uint32_t nibble_count = 0;
434     for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
435     {}
436
437     return str.size();
438 }
439
440 size_t
441 StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
442                                                char terminator)
443 {
444     str.clear();
445     char ch;
446     while ((ch = GetHexU8(0,false)) != '\0')
447         str.append(1, ch);
448     if (Peek() && *Peek() == terminator)
449         return str.size();
450
451     str.clear();
452     return str.size();
453 }
454
455 bool
456 StringExtractor::GetNameColonValue (std::string &name, std::string &value)
457 {
458     // Read something in the form of NNNN:VVVV; where NNNN is any character
459     // that is not a colon, followed by a ':' character, then a value (one or
460     // more ';' chars), followed by a ';'
461     if (m_index < m_packet.size())
462     {
463         const size_t colon_idx = m_packet.find (':', m_index);
464         if (colon_idx != std::string::npos)
465         {
466             const size_t semicolon_idx = m_packet.find (';', colon_idx);
467             if (semicolon_idx != std::string::npos)
468             {
469                 name.assign (m_packet, m_index, colon_idx - m_index);
470                 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
471                 m_index = semicolon_idx + 1;
472                 return true;
473             }
474         }
475     }
476     m_index = UINT64_MAX;
477     return false;
478 }