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