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