blob: cf5c7e2274484c0e7272257b1e24d58cd02e2054 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:241//===-- 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
Pavel Labathf805e192015-07-07 10:08:4110#include "lldb/Utility/StringExtractor.h"
Chris Lattner30fdc8d2010-06-08 16:52:2411
Zachary Turner54695a32016-08-29 19:58:1412#include <tuple>
Zachary Turner4479ac12017-04-06 18:12:2413
14#include <ctype.h> // for isxdigit, isspace
15#include <stdlib.h>
16#include <string.h> // for memset
Chris Lattner30fdc8d2010-06-08 16:52:2417
Kate Stoneb9c1b512016-09-06 20:57:5018static 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;
Chris Lattner30fdc8d2010-06-08 16:52:2426}
27
Chris Lattner30fdc8d2010-06-08 16:52:2428//----------------------------------------------------------------------
29// StringExtractor constructor
30//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5031StringExtractor::StringExtractor() : m_packet(), m_index(0) {}
32
33StringExtractor::StringExtractor(llvm::StringRef packet_str)
34 : m_packet(), m_index(0) {
35 m_packet.assign(packet_str.begin(), packet_str.end());
Chris Lattner30fdc8d2010-06-08 16:52:2436}
37
Kate Stoneb9c1b512016-09-06 20:57:5038StringExtractor::StringExtractor(const char *packet_cstr)
39 : m_packet(), m_index(0) {
40 if (packet_cstr)
41 m_packet.assign(packet_cstr);
Zachary Turner54695a32016-08-29 19:58:1442}
Chris Lattner30fdc8d2010-06-08 16:52:2443
Chris Lattner30fdc8d2010-06-08 16:52:2444//----------------------------------------------------------------------
45// StringExtractor copy constructor
46//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5047StringExtractor::StringExtractor(const StringExtractor &rhs)
48 : m_packet(rhs.m_packet), m_index(rhs.m_index) {}
Chris Lattner30fdc8d2010-06-08 16:52:2449
50//----------------------------------------------------------------------
51// StringExtractor assignment operator
52//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5053const 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;
Chris Lattner30fdc8d2010-06-08 16:52:2459}
60
61//----------------------------------------------------------------------
62// Destructor
63//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5064StringExtractor::~StringExtractor() {}
Chris Lattner30fdc8d2010-06-08 16:52:2465
Kate Stoneb9c1b512016-09-06 20:57:5066char 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;
Chris Lattner30fdc8d2010-06-08 16:52:2474}
75
Chris Lattner30fdc8d2010-06-08 16:52:2476//----------------------------------------------------------------------
Vince Harron6eddf8d2014-12-01 22:19:3377// If a pair of valid hex digits exist at the head of the
78// StringExtractor they are decoded into an unsigned byte and returned
79// by this function
80//
81// If there is not a pair of valid hex digits at the head of the
82// StringExtractor, it is left unchanged and -1 is returned
83//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5084int StringExtractor::DecodeHexU8() {
85 SkipSpaces();
86 if (GetBytesLeft() < 2) {
87 return -1;
88 }
89 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
90 const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
91 if (hi_nibble == -1 || lo_nibble == -1) {
92 return -1;
93 }
94 m_index += 2;
95 return (uint8_t)((hi_nibble << 4) + lo_nibble);
Vince Harron6eddf8d2014-12-01 22:19:3396}
97
98//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:2499// Extract an unsigned character from two hex ASCII chars in the packet
Dawn Perchik5e8115b2015-09-25 18:23:50100// string, or return fail_value on failure
Chris Lattner30fdc8d2010-06-08 16:52:24101//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50102uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
103 // On success, fail_value will be overwritten with the next
104 // character in the stream
105 GetHexU8Ex(fail_value, set_eof_on_fail);
106 return fail_value;
Dawn Perchik554a8572015-09-17 17:55:32107}
108
Kate Stoneb9c1b512016-09-06 20:57:50109bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
110 int byte = DecodeHexU8();
111 if (byte == -1) {
112 if (set_eof_on_fail || m_index >= m_packet.size())
113 m_index = UINT64_MAX;
114 // ch should not be changed in case of failure
115 return false;
116 }
117 ch = (uint8_t)byte;
118 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24119}
120
Kate Stoneb9c1b512016-09-06 20:57:50121uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) {
122 if (m_index < m_packet.size()) {
123 char *end = nullptr;
124 const char *start = m_packet.c_str();
125 const char *cstr = start + m_index;
126 uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
Greg Clayton32e0a752011-03-30 18:16:51127
Kate Stoneb9c1b512016-09-06 20:57:50128 if (end && end != cstr) {
129 m_index = end - start;
130 return result;
Daniel Maleae0f8f572013-08-26 23:57:52131 }
Kate Stoneb9c1b512016-09-06 20:57:50132 }
133 return fail_value;
Daniel Maleae0f8f572013-08-26 23:57:52134}
135
Kate Stoneb9c1b512016-09-06 20:57:50136int32_t StringExtractor::GetS32(int32_t fail_value, int base) {
137 if (m_index < m_packet.size()) {
138 char *end = nullptr;
139 const char *start = m_packet.c_str();
140 const char *cstr = start + m_index;
141 int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
142
143 if (end && end != cstr) {
144 m_index = end - start;
145 return result;
Daniel Maleae0f8f572013-08-26 23:57:52146 }
Kate Stoneb9c1b512016-09-06 20:57:50147 }
148 return fail_value;
Daniel Maleae0f8f572013-08-26 23:57:52149}
150
Kate Stoneb9c1b512016-09-06 20:57:50151uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) {
152 if (m_index < m_packet.size()) {
153 char *end = nullptr;
154 const char *start = m_packet.c_str();
155 const char *cstr = start + m_index;
156 uint64_t result = ::strtoull(cstr, &end, base);
Daniel Maleae0f8f572013-08-26 23:57:52157
Kate Stoneb9c1b512016-09-06 20:57:50158 if (end && end != cstr) {
159 m_index = end - start;
160 return result;
Daniel Maleae0f8f572013-08-26 23:57:52161 }
Kate Stoneb9c1b512016-09-06 20:57:50162 }
163 return fail_value;
Daniel Maleae0f8f572013-08-26 23:57:52164}
165
Kate Stoneb9c1b512016-09-06 20:57:50166int64_t StringExtractor::GetS64(int64_t fail_value, int base) {
167 if (m_index < m_packet.size()) {
168 char *end = nullptr;
169 const char *start = m_packet.c_str();
170 const char *cstr = start + m_index;
171 int64_t result = ::strtoll(cstr, &end, base);
172
173 if (end && end != cstr) {
174 m_index = end - start;
175 return result;
Greg Clayton32e0a752011-03-30 18:16:51176 }
Kate Stoneb9c1b512016-09-06 20:57:50177 }
178 return fail_value;
Greg Clayton32e0a752011-03-30 18:16:51179}
180
Kate Stoneb9c1b512016-09-06 20:57:50181uint32_t StringExtractor::GetHexMaxU32(bool little_endian,
182 uint32_t fail_value) {
183 uint32_t result = 0;
184 uint32_t nibble_count = 0;
Pavel Labathb9739d42016-08-31 08:43:37185
Kate Stoneb9c1b512016-09-06 20:57:50186 SkipSpaces();
187 if (little_endian) {
188 uint32_t shift_amount = 0;
189 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
190 // Make sure we don't exceed the size of a uint32_t...
191 if (nibble_count >= (sizeof(uint32_t) * 2)) {
192 m_index = UINT64_MAX;
193 return fail_value;
194 }
Pavel Labathb9739d42016-08-31 08:43:37195
Kate Stoneb9c1b512016-09-06 20:57:50196 uint8_t nibble_lo;
197 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
198 ++m_index;
199 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
200 nibble_lo = xdigit_to_sint(m_packet[m_index]);
201 ++m_index;
202 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
203 result |= ((uint32_t)nibble_lo << shift_amount);
204 nibble_count += 2;
205 shift_amount += 8;
206 } else {
207 result |= ((uint32_t)nibble_hi << shift_amount);
208 nibble_count += 1;
209 shift_amount += 4;
210 }
Pavel Labathb9739d42016-08-31 08:43:37211 }
Kate Stoneb9c1b512016-09-06 20:57:50212 } else {
213 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
214 // Make sure we don't exceed the size of a uint32_t...
215 if (nibble_count >= (sizeof(uint32_t) * 2)) {
216 m_index = UINT64_MAX;
217 return fail_value;
218 }
Pavel Labathb9739d42016-08-31 08:43:37219
Kate Stoneb9c1b512016-09-06 20:57:50220 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
221 // Big Endian
222 result <<= 4;
223 result |= nibble;
Pavel Labathb9739d42016-08-31 08:43:37224
Kate Stoneb9c1b512016-09-06 20:57:50225 ++m_index;
226 ++nibble_count;
Chris Lattner30fdc8d2010-06-08 16:52:24227 }
Kate Stoneb9c1b512016-09-06 20:57:50228 }
229 return result;
Chris Lattner30fdc8d2010-06-08 16:52:24230}
231
Kate Stoneb9c1b512016-09-06 20:57:50232uint64_t StringExtractor::GetHexMaxU64(bool little_endian,
233 uint64_t fail_value) {
234 uint64_t result = 0;
235 uint32_t nibble_count = 0;
Pavel Labathb9739d42016-08-31 08:43:37236
Kate Stoneb9c1b512016-09-06 20:57:50237 SkipSpaces();
238 if (little_endian) {
239 uint32_t shift_amount = 0;
240 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
241 // Make sure we don't exceed the size of a uint64_t...
242 if (nibble_count >= (sizeof(uint64_t) * 2)) {
243 m_index = UINT64_MAX;
244 return fail_value;
245 }
Pavel Labathb9739d42016-08-31 08:43:37246
Kate Stoneb9c1b512016-09-06 20:57:50247 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 nibble_lo = xdigit_to_sint(m_packet[m_index]);
252 ++m_index;
253 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
254 result |= ((uint64_t)nibble_lo << shift_amount);
255 nibble_count += 2;
256 shift_amount += 8;
257 } else {
258 result |= ((uint64_t)nibble_hi << shift_amount);
259 nibble_count += 1;
260 shift_amount += 4;
261 }
Pavel Labathb9739d42016-08-31 08:43:37262 }
Kate Stoneb9c1b512016-09-06 20:57:50263 } else {
264 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
265 // Make sure we don't exceed the size of a uint64_t...
266 if (nibble_count >= (sizeof(uint64_t) * 2)) {
267 m_index = UINT64_MAX;
268 return fail_value;
269 }
Pavel Labathb9739d42016-08-31 08:43:37270
Kate Stoneb9c1b512016-09-06 20:57:50271 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
272 // Big Endian
273 result <<= 4;
274 result |= nibble;
Pavel Labathb9739d42016-08-31 08:43:37275
Kate Stoneb9c1b512016-09-06 20:57:50276 ++m_index;
277 ++nibble_count;
Chris Lattner30fdc8d2010-06-08 16:52:24278 }
Kate Stoneb9c1b512016-09-06 20:57:50279 }
280 return result;
Chris Lattner30fdc8d2010-06-08 16:52:24281}
282
Ravitheja Addepallye714c4f2017-05-26 11:46:27283bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
284 llvm::StringRef S = GetStringRef();
285 if (!S.startswith(str))
286 return false;
287 else
288 m_index += str.size();
289 return true;
290}
291
Kate Stoneb9c1b512016-09-06 20:57:50292size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
293 uint8_t fail_fill_value) {
294 size_t bytes_extracted = 0;
295 while (!dest.empty() && GetBytesLeft() > 0) {
296 dest[0] = GetHexU8(fail_fill_value);
297 if (!IsGood())
298 break;
299 ++bytes_extracted;
300 dest = dest.drop_front();
301 }
Chris Lattner30fdc8d2010-06-08 16:52:24302
Kate Stoneb9c1b512016-09-06 20:57:50303 if (!dest.empty())
304 ::memset(dest.data(), fail_fill_value, dest.size());
Chris Lattner30fdc8d2010-06-08 16:52:24305
Kate Stoneb9c1b512016-09-06 20:57:50306 return bytes_extracted;
Chris Lattner30fdc8d2010-06-08 16:52:24307}
308
Vince Harron6eddf8d2014-12-01 22:19:33309//----------------------------------------------------------------------
310// Decodes all valid hex encoded bytes at the head of the
311// StringExtractor, limited by dst_len.
312//
313// Returns the number of bytes successfully decoded
314//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50315size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) {
316 size_t bytes_extracted = 0;
317 while (!dest.empty()) {
318 int decode = DecodeHexU8();
319 if (decode == -1)
320 break;
321 dest[0] = (uint8_t)decode;
322 dest = dest.drop_front();
323 ++bytes_extracted;
324 }
325 return bytes_extracted;
Vince Harron6eddf8d2014-12-01 22:19:33326}
Chris Lattner30fdc8d2010-06-08 16:52:24327
Pavel Labathb9739d42016-08-31 08:43:37328// Consume ASCII hex nibble character pairs until we have decoded byte_size
329// bytes of data.
330
Kate Stoneb9c1b512016-09-06 20:57:50331uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size,
332 bool little_endian,
333 uint64_t fail_value) {
334 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) {
335 uint64_t result = 0;
336 uint32_t i;
337 if (little_endian) {
338 // Little Endian
339 uint32_t shift_amount;
340 for (i = 0, shift_amount = 0; i < byte_size && IsGood();
341 ++i, shift_amount += 8) {
342 result |= ((uint64_t)GetHexU8() << shift_amount);
343 }
344 } else {
345 // Big Endian
346 for (i = 0; i < byte_size && IsGood(); ++i) {
347 result <<= 8;
348 result |= GetHexU8();
349 }
Pavel Labathb9739d42016-08-31 08:43:37350 }
Kate Stoneb9c1b512016-09-06 20:57:50351 }
352 m_index = UINT64_MAX;
353 return fail_value;
Pavel Labathb9739d42016-08-31 08:43:37354}
355
Kate Stoneb9c1b512016-09-06 20:57:50356size_t StringExtractor::GetHexByteString(std::string &str) {
357 str.clear();
358 str.reserve(GetBytesLeft() / 2);
359 char ch;
360 while ((ch = GetHexU8()) != '\0')
361 str.append(1, ch);
362 return str.size();
363}
364
365size_t StringExtractor::GetHexByteStringFixedLength(std::string &str,
366 uint32_t nibble_length) {
367 str.clear();
368
369 uint32_t nibble_count = 0;
370 for (const char *pch = Peek();
371 (nibble_count < nibble_length) && (pch != nullptr);
372 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
373 }
374
375 return str.size();
376}
377
378size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
379 char terminator) {
380 str.clear();
381 char ch;
382 while ((ch = GetHexU8(0, false)) != '\0')
383 str.append(1, ch);
384 if (Peek() && *Peek() == terminator)
Greg Claytonde9d0492011-01-08 03:17:57385 return str.size();
Kate Stoneb9c1b512016-09-06 20:57:50386
387 str.clear();
388 return str.size();
Greg Claytonde9d0492011-01-08 03:17:57389}
390
Kate Stoneb9c1b512016-09-06 20:57:50391bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
392 llvm::StringRef &value) {
393 // Read something in the form of NNNN:VVVV; where NNNN is any character
394 // that is not a colon, followed by a ':' character, then a value (one or
395 // more ';' chars), followed by a ';'
396 if (m_index >= m_packet.size())
397 return fail();
Pavel Labathb9739d42016-08-31 08:43:37398
Kate Stoneb9c1b512016-09-06 20:57:50399 llvm::StringRef view(m_packet);
400 if (view.empty())
401 return fail();
Pavel Labathb9739d42016-08-31 08:43:37402
Kate Stoneb9c1b512016-09-06 20:57:50403 llvm::StringRef a, b, c, d;
404 view = view.substr(m_index);
405 std::tie(a, b) = view.split(':');
406 if (a.empty() || b.empty())
407 return fail();
408 std::tie(c, d) = b.split(';');
409 if (b == c && d.empty())
410 return fail();
411
412 name = a;
413 value = c;
414 if (d.empty())
415 m_index = m_packet.size();
416 else {
417 size_t bytes_consumed = d.data() - view.data();
418 m_index += bytes_consumed;
419 }
420 return true;
Todd Fialaaf245d12014-06-30 21:05:18421}
422
Kate Stoneb9c1b512016-09-06 20:57:50423void StringExtractor::SkipSpaces() {
424 const size_t n = m_packet.size();
425 while (m_index < n && isspace(m_packet[m_index]))
426 ++m_index;
Daniel Maleae0f8f572013-08-26 23:57:52427}