blob: f0f6ad131c64d8e20dff464d65f7e19223a2a07f [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:241//===-- StringExtractor.cpp -------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:563// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Chris Lattner30fdc8d2010-06-08 16:52:246//
7//===----------------------------------------------------------------------===//
8
Pavel Labathf805e192015-07-07 10:08:419#include "lldb/Utility/StringExtractor.h"
Chris Lattner30fdc8d2010-06-08 16:52:2410
Zachary Turner54695a32016-08-29 19:58:1411#include <tuple>
Zachary Turner4479ac12017-04-06 18:12:2412
Jonas Devlieghere672d2c12018-11-11 23:16:4313#include <ctype.h>
Zachary Turner4479ac12017-04-06 18:12:2414#include <stdlib.h>
Jonas Devlieghere672d2c12018-11-11 23:16:4315#include <string.h>
Chris Lattner30fdc8d2010-06-08 16:52:2416
Kate Stoneb9c1b512016-09-06 20:57:5017static inline int xdigit_to_sint(char ch) {
18 if (ch >= 'a' && ch <= 'f')
19 return 10 + ch - 'a';
20 if (ch >= 'A' && ch <= 'F')
21 return 10 + ch - 'A';
22 if (ch >= '0' && ch <= '9')
23 return ch - '0';
24 return -1;
Chris Lattner30fdc8d2010-06-08 16:52:2425}
26
Chris Lattner30fdc8d2010-06-08 16:52:2427//----------------------------------------------------------------------
28// StringExtractor constructor
29//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5030StringExtractor::StringExtractor() : m_packet(), m_index(0) {}
31
32StringExtractor::StringExtractor(llvm::StringRef packet_str)
33 : m_packet(), m_index(0) {
34 m_packet.assign(packet_str.begin(), packet_str.end());
Chris Lattner30fdc8d2010-06-08 16:52:2435}
36
Kate Stoneb9c1b512016-09-06 20:57:5037StringExtractor::StringExtractor(const char *packet_cstr)
38 : m_packet(), m_index(0) {
39 if (packet_cstr)
40 m_packet.assign(packet_cstr);
Zachary Turner54695a32016-08-29 19:58:1441}
Chris Lattner30fdc8d2010-06-08 16:52:2442
Chris Lattner30fdc8d2010-06-08 16:52:2443//----------------------------------------------------------------------
44// StringExtractor copy constructor
45//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5046StringExtractor::StringExtractor(const StringExtractor &rhs)
47 : m_packet(rhs.m_packet), m_index(rhs.m_index) {}
Chris Lattner30fdc8d2010-06-08 16:52:2448
49//----------------------------------------------------------------------
50// StringExtractor assignment operator
51//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5052const StringExtractor &StringExtractor::operator=(const StringExtractor &rhs) {
53 if (this != &rhs) {
54 m_packet = rhs.m_packet;
55 m_index = rhs.m_index;
56 }
57 return *this;
Chris Lattner30fdc8d2010-06-08 16:52:2458}
59
60//----------------------------------------------------------------------
61// Destructor
62//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5063StringExtractor::~StringExtractor() {}
Chris Lattner30fdc8d2010-06-08 16:52:2464
Kate Stoneb9c1b512016-09-06 20:57:5065char StringExtractor::GetChar(char fail_value) {
66 if (m_index < m_packet.size()) {
67 char ch = m_packet[m_index];
68 ++m_index;
69 return ch;
70 }
71 m_index = UINT64_MAX;
72 return fail_value;
Chris Lattner30fdc8d2010-06-08 16:52:2473}
74
Chris Lattner30fdc8d2010-06-08 16:52:2475//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:0476// If a pair of valid hex digits exist at the head of the StringExtractor they
77// are decoded into an unsigned byte and returned by this function
Vince Harron6eddf8d2014-12-01 22:19:3378//
79// If there is not a pair of valid hex digits at the head of the
80// StringExtractor, it is left unchanged and -1 is returned
81//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5082int StringExtractor::DecodeHexU8() {
83 SkipSpaces();
84 if (GetBytesLeft() < 2) {
85 return -1;
86 }
87 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
88 const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
89 if (hi_nibble == -1 || lo_nibble == -1) {
90 return -1;
91 }
92 m_index += 2;
93 return (uint8_t)((hi_nibble << 4) + lo_nibble);
Vince Harron6eddf8d2014-12-01 22:19:3394}
95
96//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:0497// Extract an unsigned character from two hex ASCII chars in the packet string,
98// or return fail_value on failure
Chris Lattner30fdc8d2010-06-08 16:52:2499//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50100uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
Adrian Prantl05097242018-04-30 16:49:04101 // On success, fail_value will be overwritten with the next character in the
102 // stream
Kate Stoneb9c1b512016-09-06 20:57:50103 GetHexU8Ex(fail_value, set_eof_on_fail);
104 return fail_value;
Dawn Perchik554a8572015-09-17 17:55:32105}
106
Kate Stoneb9c1b512016-09-06 20:57:50107bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
108 int byte = DecodeHexU8();
109 if (byte == -1) {
110 if (set_eof_on_fail || m_index >= m_packet.size())
111 m_index = UINT64_MAX;
112 // ch should not be changed in case of failure
113 return false;
114 }
115 ch = (uint8_t)byte;
116 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24117}
118
Kate Stoneb9c1b512016-09-06 20:57:50119uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) {
120 if (m_index < m_packet.size()) {
121 char *end = nullptr;
122 const char *start = m_packet.c_str();
123 const char *cstr = start + m_index;
124 uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
Greg Clayton32e0a752011-03-30 18:16:51125
Kate Stoneb9c1b512016-09-06 20:57:50126 if (end && end != cstr) {
127 m_index = end - start;
128 return result;
Daniel Maleae0f8f572013-08-26 23:57:52129 }
Kate Stoneb9c1b512016-09-06 20:57:50130 }
131 return fail_value;
Daniel Maleae0f8f572013-08-26 23:57:52132}
133
Kate Stoneb9c1b512016-09-06 20:57:50134int32_t StringExtractor::GetS32(int32_t fail_value, int base) {
135 if (m_index < m_packet.size()) {
136 char *end = nullptr;
137 const char *start = m_packet.c_str();
138 const char *cstr = start + m_index;
139 int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
140
141 if (end && end != cstr) {
142 m_index = end - start;
143 return result;
Daniel Maleae0f8f572013-08-26 23:57:52144 }
Kate Stoneb9c1b512016-09-06 20:57:50145 }
146 return fail_value;
Daniel Maleae0f8f572013-08-26 23:57:52147}
148
Kate Stoneb9c1b512016-09-06 20:57:50149uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) {
150 if (m_index < m_packet.size()) {
151 char *end = nullptr;
152 const char *start = m_packet.c_str();
153 const char *cstr = start + m_index;
154 uint64_t result = ::strtoull(cstr, &end, base);
Daniel Maleae0f8f572013-08-26 23:57:52155
Kate Stoneb9c1b512016-09-06 20:57:50156 if (end && end != cstr) {
157 m_index = end - start;
158 return result;
Daniel Maleae0f8f572013-08-26 23:57:52159 }
Kate Stoneb9c1b512016-09-06 20:57:50160 }
161 return fail_value;
Daniel Maleae0f8f572013-08-26 23:57:52162}
163
Kate Stoneb9c1b512016-09-06 20:57:50164int64_t StringExtractor::GetS64(int64_t fail_value, int base) {
165 if (m_index < m_packet.size()) {
166 char *end = nullptr;
167 const char *start = m_packet.c_str();
168 const char *cstr = start + m_index;
169 int64_t result = ::strtoll(cstr, &end, base);
170
171 if (end && end != cstr) {
172 m_index = end - start;
173 return result;
Greg Clayton32e0a752011-03-30 18:16:51174 }
Kate Stoneb9c1b512016-09-06 20:57:50175 }
176 return fail_value;
Greg Clayton32e0a752011-03-30 18:16:51177}
178
Kate Stoneb9c1b512016-09-06 20:57:50179uint32_t StringExtractor::GetHexMaxU32(bool little_endian,
180 uint32_t fail_value) {
181 uint32_t result = 0;
182 uint32_t nibble_count = 0;
Pavel Labathb9739d42016-08-31 08:43:37183
Kate Stoneb9c1b512016-09-06 20:57:50184 SkipSpaces();
185 if (little_endian) {
186 uint32_t shift_amount = 0;
187 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
188 // Make sure we don't exceed the size of a uint32_t...
189 if (nibble_count >= (sizeof(uint32_t) * 2)) {
190 m_index = UINT64_MAX;
191 return fail_value;
192 }
Pavel Labathb9739d42016-08-31 08:43:37193
Kate Stoneb9c1b512016-09-06 20:57:50194 uint8_t nibble_lo;
195 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
196 ++m_index;
197 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
198 nibble_lo = xdigit_to_sint(m_packet[m_index]);
199 ++m_index;
200 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
201 result |= ((uint32_t)nibble_lo << shift_amount);
202 nibble_count += 2;
203 shift_amount += 8;
204 } else {
205 result |= ((uint32_t)nibble_hi << shift_amount);
206 nibble_count += 1;
207 shift_amount += 4;
208 }
Pavel Labathb9739d42016-08-31 08:43:37209 }
Kate Stoneb9c1b512016-09-06 20:57:50210 } else {
211 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
212 // Make sure we don't exceed the size of a uint32_t...
213 if (nibble_count >= (sizeof(uint32_t) * 2)) {
214 m_index = UINT64_MAX;
215 return fail_value;
216 }
Pavel Labathb9739d42016-08-31 08:43:37217
Kate Stoneb9c1b512016-09-06 20:57:50218 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
219 // Big Endian
220 result <<= 4;
221 result |= nibble;
Pavel Labathb9739d42016-08-31 08:43:37222
Kate Stoneb9c1b512016-09-06 20:57:50223 ++m_index;
224 ++nibble_count;
Chris Lattner30fdc8d2010-06-08 16:52:24225 }
Kate Stoneb9c1b512016-09-06 20:57:50226 }
227 return result;
Chris Lattner30fdc8d2010-06-08 16:52:24228}
229
Kate Stoneb9c1b512016-09-06 20:57:50230uint64_t StringExtractor::GetHexMaxU64(bool little_endian,
231 uint64_t fail_value) {
232 uint64_t result = 0;
233 uint32_t nibble_count = 0;
Pavel Labathb9739d42016-08-31 08:43:37234
Kate Stoneb9c1b512016-09-06 20:57:50235 SkipSpaces();
236 if (little_endian) {
237 uint32_t shift_amount = 0;
238 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
239 // Make sure we don't exceed the size of a uint64_t...
240 if (nibble_count >= (sizeof(uint64_t) * 2)) {
241 m_index = UINT64_MAX;
242 return fail_value;
243 }
Pavel Labathb9739d42016-08-31 08:43:37244
Kate Stoneb9c1b512016-09-06 20:57:50245 uint8_t nibble_lo;
246 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
247 ++m_index;
248 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
249 nibble_lo = xdigit_to_sint(m_packet[m_index]);
250 ++m_index;
251 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
252 result |= ((uint64_t)nibble_lo << shift_amount);
253 nibble_count += 2;
254 shift_amount += 8;
255 } else {
256 result |= ((uint64_t)nibble_hi << shift_amount);
257 nibble_count += 1;
258 shift_amount += 4;
259 }
Pavel Labathb9739d42016-08-31 08:43:37260 }
Kate Stoneb9c1b512016-09-06 20:57:50261 } else {
262 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
263 // Make sure we don't exceed the size of a uint64_t...
264 if (nibble_count >= (sizeof(uint64_t) * 2)) {
265 m_index = UINT64_MAX;
266 return fail_value;
267 }
Pavel Labathb9739d42016-08-31 08:43:37268
Kate Stoneb9c1b512016-09-06 20:57:50269 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
270 // Big Endian
271 result <<= 4;
272 result |= nibble;
Pavel Labathb9739d42016-08-31 08:43:37273
Kate Stoneb9c1b512016-09-06 20:57:50274 ++m_index;
275 ++nibble_count;
Chris Lattner30fdc8d2010-06-08 16:52:24276 }
Kate Stoneb9c1b512016-09-06 20:57:50277 }
278 return result;
Chris Lattner30fdc8d2010-06-08 16:52:24279}
280
Ravitheja Addepallye714c4f2017-05-26 11:46:27281bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
282 llvm::StringRef S = GetStringRef();
283 if (!S.startswith(str))
284 return false;
285 else
286 m_index += str.size();
287 return true;
288}
289
Kate Stoneb9c1b512016-09-06 20:57:50290size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
291 uint8_t fail_fill_value) {
292 size_t bytes_extracted = 0;
293 while (!dest.empty() && GetBytesLeft() > 0) {
294 dest[0] = GetHexU8(fail_fill_value);
295 if (!IsGood())
296 break;
297 ++bytes_extracted;
298 dest = dest.drop_front();
299 }
Chris Lattner30fdc8d2010-06-08 16:52:24300
Kate Stoneb9c1b512016-09-06 20:57:50301 if (!dest.empty())
302 ::memset(dest.data(), fail_fill_value, dest.size());
Chris Lattner30fdc8d2010-06-08 16:52:24303
Kate Stoneb9c1b512016-09-06 20:57:50304 return bytes_extracted;
Chris Lattner30fdc8d2010-06-08 16:52:24305}
306
Vince Harron6eddf8d2014-12-01 22:19:33307//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:04308// Decodes all valid hex encoded bytes at the head of the StringExtractor,
309// limited by dst_len.
Vince Harron6eddf8d2014-12-01 22:19:33310//
311// Returns the number of bytes successfully decoded
312//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50313size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) {
314 size_t bytes_extracted = 0;
315 while (!dest.empty()) {
316 int decode = DecodeHexU8();
317 if (decode == -1)
318 break;
319 dest[0] = (uint8_t)decode;
320 dest = dest.drop_front();
321 ++bytes_extracted;
322 }
323 return bytes_extracted;
Vince Harron6eddf8d2014-12-01 22:19:33324}
Chris Lattner30fdc8d2010-06-08 16:52:24325
Pavel Labathb9739d42016-08-31 08:43:37326// Consume ASCII hex nibble character pairs until we have decoded byte_size
327// bytes of data.
328
Kate Stoneb9c1b512016-09-06 20:57:50329uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size,
330 bool little_endian,
331 uint64_t fail_value) {
332 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) {
333 uint64_t result = 0;
334 uint32_t i;
335 if (little_endian) {
336 // Little Endian
337 uint32_t shift_amount;
338 for (i = 0, shift_amount = 0; i < byte_size && IsGood();
339 ++i, shift_amount += 8) {
340 result |= ((uint64_t)GetHexU8() << shift_amount);
341 }
342 } else {
343 // Big Endian
344 for (i = 0; i < byte_size && IsGood(); ++i) {
345 result <<= 8;
346 result |= GetHexU8();
347 }
Pavel Labathb9739d42016-08-31 08:43:37348 }
Kate Stoneb9c1b512016-09-06 20:57:50349 }
350 m_index = UINT64_MAX;
351 return fail_value;
Pavel Labathb9739d42016-08-31 08:43:37352}
353
Kate Stoneb9c1b512016-09-06 20:57:50354size_t StringExtractor::GetHexByteString(std::string &str) {
355 str.clear();
356 str.reserve(GetBytesLeft() / 2);
357 char ch;
358 while ((ch = GetHexU8()) != '\0')
359 str.append(1, ch);
360 return str.size();
361}
362
363size_t StringExtractor::GetHexByteStringFixedLength(std::string &str,
364 uint32_t nibble_length) {
365 str.clear();
366
367 uint32_t nibble_count = 0;
368 for (const char *pch = Peek();
369 (nibble_count < nibble_length) && (pch != nullptr);
370 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
371 }
372
373 return str.size();
374}
375
376size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
377 char terminator) {
378 str.clear();
379 char ch;
380 while ((ch = GetHexU8(0, false)) != '\0')
381 str.append(1, ch);
382 if (Peek() && *Peek() == terminator)
Greg Claytonde9d0492011-01-08 03:17:57383 return str.size();
Kate Stoneb9c1b512016-09-06 20:57:50384
385 str.clear();
386 return str.size();
Greg Claytonde9d0492011-01-08 03:17:57387}
388
Kate Stoneb9c1b512016-09-06 20:57:50389bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
390 llvm::StringRef &value) {
Adrian Prantl05097242018-04-30 16:49:04391 // Read something in the form of NNNN:VVVV; where NNNN is any character that
392 // is not a colon, followed by a ':' character, then a value (one or more ';'
393 // chars), followed by a ';'
Kate Stoneb9c1b512016-09-06 20:57:50394 if (m_index >= m_packet.size())
395 return fail();
Pavel Labathb9739d42016-08-31 08:43:37396
Kate Stoneb9c1b512016-09-06 20:57:50397 llvm::StringRef view(m_packet);
398 if (view.empty())
399 return fail();
Pavel Labathb9739d42016-08-31 08:43:37400
Kate Stoneb9c1b512016-09-06 20:57:50401 llvm::StringRef a, b, c, d;
402 view = view.substr(m_index);
403 std::tie(a, b) = view.split(':');
404 if (a.empty() || b.empty())
405 return fail();
406 std::tie(c, d) = b.split(';');
407 if (b == c && d.empty())
408 return fail();
409
410 name = a;
411 value = c;
412 if (d.empty())
413 m_index = m_packet.size();
414 else {
415 size_t bytes_consumed = d.data() - view.data();
416 m_index += bytes_consumed;
417 }
418 return true;
Todd Fialaaf245d12014-06-30 21:05:18419}
420
Kate Stoneb9c1b512016-09-06 20:57:50421void StringExtractor::SkipSpaces() {
422 const size_t n = m_packet.size();
423 while (m_index < n && isspace(m_packet[m_index]))
424 ++m_index;
Daniel Maleae0f8f572013-08-26 23:57:52425}