blob: 0553a63a021e2ee54bbb748b2360fbaea168605a [file] [log] [blame]
Raphael Isemann80814282020-01-24 07:23:271//===-- StringExtractor.cpp -----------------------------------------------===//
Chris Lattner30fdc8d2010-06-08 16:52:242//
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"
Raphael Isemannf5eaa2a2020-06-19 17:17:2410#include "llvm/ADT/StringExtras.h"
Chris Lattner30fdc8d2010-06-08 16:52:2411
Zachary Turner54695a32016-08-29 19:58:1412#include <tuple>
Zachary Turner4479ac12017-04-06 18:12:2413
Jonas Devlieghere672d2c12018-11-11 23:16:4314#include <ctype.h>
Zachary Turner4479ac12017-04-06 18:12:2415#include <stdlib.h>
Jonas Devlieghere672d2c12018-11-11 23:16:4316#include <string.h>
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// StringExtractor constructor
Kate Stoneb9c1b512016-09-06 20:57:5029StringExtractor::StringExtractor() : m_packet(), m_index(0) {}
30
31StringExtractor::StringExtractor(llvm::StringRef packet_str)
32 : m_packet(), m_index(0) {
33 m_packet.assign(packet_str.begin(), packet_str.end());
Chris Lattner30fdc8d2010-06-08 16:52:2434}
35
Kate Stoneb9c1b512016-09-06 20:57:5036StringExtractor::StringExtractor(const char *packet_cstr)
37 : m_packet(), m_index(0) {
38 if (packet_cstr)
39 m_packet.assign(packet_cstr);
Zachary Turner54695a32016-08-29 19:58:1440}
Chris Lattner30fdc8d2010-06-08 16:52:2441
Chris Lattner30fdc8d2010-06-08 16:52:2442// Destructor
Kate Stoneb9c1b512016-09-06 20:57:5043StringExtractor::~StringExtractor() {}
Chris Lattner30fdc8d2010-06-08 16:52:2444
Kate Stoneb9c1b512016-09-06 20:57:5045char StringExtractor::GetChar(char fail_value) {
46 if (m_index < m_packet.size()) {
47 char ch = m_packet[m_index];
48 ++m_index;
49 return ch;
50 }
51 m_index = UINT64_MAX;
52 return fail_value;
Chris Lattner30fdc8d2010-06-08 16:52:2453}
54
Adrian Prantl05097242018-04-30 16:49:0455// If a pair of valid hex digits exist at the head of the StringExtractor they
56// are decoded into an unsigned byte and returned by this function
Vince Harron6eddf8d2014-12-01 22:19:3357//
58// If there is not a pair of valid hex digits at the head of the
59// StringExtractor, it is left unchanged and -1 is returned
Kate Stoneb9c1b512016-09-06 20:57:5060int StringExtractor::DecodeHexU8() {
61 SkipSpaces();
62 if (GetBytesLeft() < 2) {
63 return -1;
64 }
65 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
66 const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
67 if (hi_nibble == -1 || lo_nibble == -1) {
68 return -1;
69 }
70 m_index += 2;
Jonas Devlieghere24374ae2019-05-23 05:12:1171 return static_cast<uint8_t>((hi_nibble << 4) + lo_nibble);
Vince Harron6eddf8d2014-12-01 22:19:3372}
73
Adrian Prantl05097242018-04-30 16:49:0474// Extract an unsigned character from two hex ASCII chars in the packet string,
75// or return fail_value on failure
Kate Stoneb9c1b512016-09-06 20:57:5076uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
Adrian Prantl05097242018-04-30 16:49:0477 // On success, fail_value will be overwritten with the next character in the
78 // stream
Kate Stoneb9c1b512016-09-06 20:57:5079 GetHexU8Ex(fail_value, set_eof_on_fail);
80 return fail_value;
Dawn Perchik554a8572015-09-17 17:55:3281}
82
Kate Stoneb9c1b512016-09-06 20:57:5083bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
84 int byte = DecodeHexU8();
85 if (byte == -1) {
86 if (set_eof_on_fail || m_index >= m_packet.size())
87 m_index = UINT64_MAX;
88 // ch should not be changed in case of failure
89 return false;
90 }
Jonas Devlieghere24374ae2019-05-23 05:12:1191 ch = static_cast<uint8_t>(byte);
Kate Stoneb9c1b512016-09-06 20:57:5092 return true;
Chris Lattner30fdc8d2010-06-08 16:52:2493}
94
Kate Stoneb9c1b512016-09-06 20:57:5095uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) {
96 if (m_index < m_packet.size()) {
97 char *end = nullptr;
98 const char *start = m_packet.c_str();
99 const char *cstr = start + m_index;
100 uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
Greg Clayton32e0a752011-03-30 18:16:51101
Kate Stoneb9c1b512016-09-06 20:57:50102 if (end && end != cstr) {
103 m_index = end - start;
104 return result;
Daniel Maleae0f8f572013-08-26 23:57:52105 }
Kate Stoneb9c1b512016-09-06 20:57:50106 }
107 return fail_value;
Daniel Maleae0f8f572013-08-26 23:57:52108}
109
Kate Stoneb9c1b512016-09-06 20:57:50110int32_t StringExtractor::GetS32(int32_t fail_value, int base) {
111 if (m_index < m_packet.size()) {
112 char *end = nullptr;
113 const char *start = m_packet.c_str();
114 const char *cstr = start + m_index;
115 int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
116
117 if (end && end != cstr) {
118 m_index = end - start;
119 return result;
Daniel Maleae0f8f572013-08-26 23:57:52120 }
Kate Stoneb9c1b512016-09-06 20:57:50121 }
122 return fail_value;
Daniel Maleae0f8f572013-08-26 23:57:52123}
124
Kate Stoneb9c1b512016-09-06 20:57:50125uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) {
126 if (m_index < m_packet.size()) {
127 char *end = nullptr;
128 const char *start = m_packet.c_str();
129 const char *cstr = start + m_index;
130 uint64_t result = ::strtoull(cstr, &end, base);
Daniel Maleae0f8f572013-08-26 23:57:52131
Kate Stoneb9c1b512016-09-06 20:57:50132 if (end && end != cstr) {
133 m_index = end - start;
134 return result;
Daniel Maleae0f8f572013-08-26 23:57:52135 }
Kate Stoneb9c1b512016-09-06 20:57:50136 }
137 return fail_value;
Daniel Maleae0f8f572013-08-26 23:57:52138}
139
Kate Stoneb9c1b512016-09-06 20:57:50140int64_t StringExtractor::GetS64(int64_t fail_value, int base) {
141 if (m_index < m_packet.size()) {
142 char *end = nullptr;
143 const char *start = m_packet.c_str();
144 const char *cstr = start + m_index;
145 int64_t result = ::strtoll(cstr, &end, base);
146
147 if (end && end != cstr) {
148 m_index = end - start;
149 return result;
Greg Clayton32e0a752011-03-30 18:16:51150 }
Kate Stoneb9c1b512016-09-06 20:57:50151 }
152 return fail_value;
Greg Clayton32e0a752011-03-30 18:16:51153}
154
Kate Stoneb9c1b512016-09-06 20:57:50155uint32_t StringExtractor::GetHexMaxU32(bool little_endian,
156 uint32_t fail_value) {
157 uint32_t result = 0;
158 uint32_t nibble_count = 0;
Pavel Labathb9739d42016-08-31 08:43:37159
Kate Stoneb9c1b512016-09-06 20:57:50160 SkipSpaces();
161 if (little_endian) {
162 uint32_t shift_amount = 0;
163 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
164 // Make sure we don't exceed the size of a uint32_t...
165 if (nibble_count >= (sizeof(uint32_t) * 2)) {
166 m_index = UINT64_MAX;
167 return fail_value;
168 }
Pavel Labathb9739d42016-08-31 08:43:37169
Kate Stoneb9c1b512016-09-06 20:57:50170 uint8_t nibble_lo;
171 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
172 ++m_index;
173 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
174 nibble_lo = xdigit_to_sint(m_packet[m_index]);
175 ++m_index;
Jonas Devlieghere24374ae2019-05-23 05:12:11176 result |= (static_cast<uint32_t>(nibble_hi) << (shift_amount + 4));
177 result |= (static_cast<uint32_t>(nibble_lo) << shift_amount);
Kate Stoneb9c1b512016-09-06 20:57:50178 nibble_count += 2;
179 shift_amount += 8;
180 } else {
Jonas Devlieghere24374ae2019-05-23 05:12:11181 result |= (static_cast<uint32_t>(nibble_hi) << shift_amount);
Kate Stoneb9c1b512016-09-06 20:57:50182 nibble_count += 1;
183 shift_amount += 4;
184 }
Pavel Labathb9739d42016-08-31 08:43:37185 }
Kate Stoneb9c1b512016-09-06 20:57:50186 } else {
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 = xdigit_to_sint(m_packet[m_index]);
195 // Big Endian
196 result <<= 4;
197 result |= nibble;
Pavel Labathb9739d42016-08-31 08:43:37198
Kate Stoneb9c1b512016-09-06 20:57:50199 ++m_index;
200 ++nibble_count;
Chris Lattner30fdc8d2010-06-08 16:52:24201 }
Kate Stoneb9c1b512016-09-06 20:57:50202 }
203 return result;
Chris Lattner30fdc8d2010-06-08 16:52:24204}
205
Kate Stoneb9c1b512016-09-06 20:57:50206uint64_t StringExtractor::GetHexMaxU64(bool little_endian,
207 uint64_t fail_value) {
208 uint64_t result = 0;
209 uint32_t nibble_count = 0;
Pavel Labathb9739d42016-08-31 08:43:37210
Kate Stoneb9c1b512016-09-06 20:57:50211 SkipSpaces();
212 if (little_endian) {
213 uint32_t shift_amount = 0;
214 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
215 // Make sure we don't exceed the size of a uint64_t...
216 if (nibble_count >= (sizeof(uint64_t) * 2)) {
217 m_index = UINT64_MAX;
218 return fail_value;
219 }
Pavel Labathb9739d42016-08-31 08:43:37220
Kate Stoneb9c1b512016-09-06 20:57:50221 uint8_t nibble_lo;
222 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
223 ++m_index;
224 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
225 nibble_lo = xdigit_to_sint(m_packet[m_index]);
226 ++m_index;
Jonas Devlieghere24374ae2019-05-23 05:12:11227 result |= (static_cast<uint64_t>(nibble_hi) << (shift_amount + 4));
228 result |= (static_cast<uint64_t>(nibble_lo) << shift_amount);
Kate Stoneb9c1b512016-09-06 20:57:50229 nibble_count += 2;
230 shift_amount += 8;
231 } else {
Jonas Devlieghere24374ae2019-05-23 05:12:11232 result |= (static_cast<uint64_t>(nibble_hi) << shift_amount);
Kate Stoneb9c1b512016-09-06 20:57:50233 nibble_count += 1;
234 shift_amount += 4;
235 }
Pavel Labathb9739d42016-08-31 08:43:37236 }
Kate Stoneb9c1b512016-09-06 20:57:50237 } else {
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 = xdigit_to_sint(m_packet[m_index]);
246 // Big Endian
247 result <<= 4;
248 result |= nibble;
Pavel Labathb9739d42016-08-31 08:43:37249
Kate Stoneb9c1b512016-09-06 20:57:50250 ++m_index;
251 ++nibble_count;
Chris Lattner30fdc8d2010-06-08 16:52:24252 }
Kate Stoneb9c1b512016-09-06 20:57:50253 }
254 return result;
Chris Lattner30fdc8d2010-06-08 16:52:24255}
256
Ravitheja Addepallye714c4f2017-05-26 11:46:27257bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
258 llvm::StringRef S = GetStringRef();
259 if (!S.startswith(str))
260 return false;
261 else
262 m_index += str.size();
263 return true;
264}
265
Kate Stoneb9c1b512016-09-06 20:57:50266size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
267 uint8_t fail_fill_value) {
268 size_t bytes_extracted = 0;
269 while (!dest.empty() && GetBytesLeft() > 0) {
270 dest[0] = GetHexU8(fail_fill_value);
271 if (!IsGood())
272 break;
273 ++bytes_extracted;
274 dest = dest.drop_front();
275 }
Chris Lattner30fdc8d2010-06-08 16:52:24276
Kate Stoneb9c1b512016-09-06 20:57:50277 if (!dest.empty())
278 ::memset(dest.data(), fail_fill_value, dest.size());
Chris Lattner30fdc8d2010-06-08 16:52:24279
Kate Stoneb9c1b512016-09-06 20:57:50280 return bytes_extracted;
Chris Lattner30fdc8d2010-06-08 16:52:24281}
282
Adrian Prantl05097242018-04-30 16:49:04283// Decodes all valid hex encoded bytes at the head of the StringExtractor,
284// limited by dst_len.
Vince Harron6eddf8d2014-12-01 22:19:33285//
286// Returns the number of bytes successfully decoded
Kate Stoneb9c1b512016-09-06 20:57:50287size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) {
288 size_t bytes_extracted = 0;
289 while (!dest.empty()) {
290 int decode = DecodeHexU8();
291 if (decode == -1)
292 break;
Jonas Devlieghere24374ae2019-05-23 05:12:11293 dest[0] = static_cast<uint8_t>(decode);
Kate Stoneb9c1b512016-09-06 20:57:50294 dest = dest.drop_front();
295 ++bytes_extracted;
296 }
297 return bytes_extracted;
Vince Harron6eddf8d2014-12-01 22:19:33298}
Chris Lattner30fdc8d2010-06-08 16:52:24299
Kate Stoneb9c1b512016-09-06 20:57:50300size_t StringExtractor::GetHexByteString(std::string &str) {
301 str.clear();
302 str.reserve(GetBytesLeft() / 2);
303 char ch;
304 while ((ch = GetHexU8()) != '\0')
305 str.append(1, ch);
306 return str.size();
307}
308
309size_t StringExtractor::GetHexByteStringFixedLength(std::string &str,
310 uint32_t nibble_length) {
311 str.clear();
312
313 uint32_t nibble_count = 0;
314 for (const char *pch = Peek();
315 (nibble_count < nibble_length) && (pch != nullptr);
316 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
317 }
318
319 return str.size();
320}
321
322size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
323 char terminator) {
324 str.clear();
325 char ch;
326 while ((ch = GetHexU8(0, false)) != '\0')
327 str.append(1, ch);
328 if (Peek() && *Peek() == terminator)
Greg Claytonde9d0492011-01-08 03:17:57329 return str.size();
Kate Stoneb9c1b512016-09-06 20:57:50330
331 str.clear();
332 return str.size();
Greg Claytonde9d0492011-01-08 03:17:57333}
334
Kate Stoneb9c1b512016-09-06 20:57:50335bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
336 llvm::StringRef &value) {
Adrian Prantl05097242018-04-30 16:49:04337 // Read something in the form of NNNN:VVVV; where NNNN is any character that
338 // is not a colon, followed by a ':' character, then a value (one or more ';'
339 // chars), followed by a ';'
Kate Stoneb9c1b512016-09-06 20:57:50340 if (m_index >= m_packet.size())
341 return fail();
Pavel Labathb9739d42016-08-31 08:43:37342
Kate Stoneb9c1b512016-09-06 20:57:50343 llvm::StringRef view(m_packet);
344 if (view.empty())
345 return fail();
Pavel Labathb9739d42016-08-31 08:43:37346
Kate Stoneb9c1b512016-09-06 20:57:50347 llvm::StringRef a, b, c, d;
348 view = view.substr(m_index);
349 std::tie(a, b) = view.split(':');
350 if (a.empty() || b.empty())
351 return fail();
352 std::tie(c, d) = b.split(';');
353 if (b == c && d.empty())
354 return fail();
355
356 name = a;
357 value = c;
358 if (d.empty())
359 m_index = m_packet.size();
360 else {
361 size_t bytes_consumed = d.data() - view.data();
362 m_index += bytes_consumed;
363 }
364 return true;
Todd Fialaaf245d12014-06-30 21:05:18365}
366
Kate Stoneb9c1b512016-09-06 20:57:50367void StringExtractor::SkipSpaces() {
368 const size_t n = m_packet.size();
Raphael Isemannf5eaa2a2020-06-19 17:17:24369 while (m_index < n && llvm::isSpace(m_packet[m_index]))
Kate Stoneb9c1b512016-09-06 20:57:50370 ++m_index;
Daniel Maleae0f8f572013-08-26 23:57:52371}