blob: a94f6bcd0087e743a6126c0d74a17faed7cff13b [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
Kate Stoneb9c1b512016-09-06 20:57:50283size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
284 uint8_t fail_fill_value) {
285 size_t bytes_extracted = 0;
286 while (!dest.empty() && GetBytesLeft() > 0) {
287 dest[0] = GetHexU8(fail_fill_value);
288 if (!IsGood())
289 break;
290 ++bytes_extracted;
291 dest = dest.drop_front();
292 }
Chris Lattner30fdc8d2010-06-08 16:52:24293
Kate Stoneb9c1b512016-09-06 20:57:50294 if (!dest.empty())
295 ::memset(dest.data(), fail_fill_value, dest.size());
Chris Lattner30fdc8d2010-06-08 16:52:24296
Kate Stoneb9c1b512016-09-06 20:57:50297 return bytes_extracted;
Chris Lattner30fdc8d2010-06-08 16:52:24298}
299
Vince Harron6eddf8d2014-12-01 22:19:33300//----------------------------------------------------------------------
301// Decodes all valid hex encoded bytes at the head of the
302// StringExtractor, limited by dst_len.
303//
304// Returns the number of bytes successfully decoded
305//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50306size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) {
307 size_t bytes_extracted = 0;
308 while (!dest.empty()) {
309 int decode = DecodeHexU8();
310 if (decode == -1)
311 break;
312 dest[0] = (uint8_t)decode;
313 dest = dest.drop_front();
314 ++bytes_extracted;
315 }
316 return bytes_extracted;
Vince Harron6eddf8d2014-12-01 22:19:33317}
Chris Lattner30fdc8d2010-06-08 16:52:24318
Pavel Labathb9739d42016-08-31 08:43:37319// Consume ASCII hex nibble character pairs until we have decoded byte_size
320// bytes of data.
321
Kate Stoneb9c1b512016-09-06 20:57:50322uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size,
323 bool little_endian,
324 uint64_t fail_value) {
325 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) {
326 uint64_t result = 0;
327 uint32_t i;
328 if (little_endian) {
329 // Little Endian
330 uint32_t shift_amount;
331 for (i = 0, shift_amount = 0; i < byte_size && IsGood();
332 ++i, shift_amount += 8) {
333 result |= ((uint64_t)GetHexU8() << shift_amount);
334 }
335 } else {
336 // Big Endian
337 for (i = 0; i < byte_size && IsGood(); ++i) {
338 result <<= 8;
339 result |= GetHexU8();
340 }
Pavel Labathb9739d42016-08-31 08:43:37341 }
Kate Stoneb9c1b512016-09-06 20:57:50342 }
343 m_index = UINT64_MAX;
344 return fail_value;
Pavel Labathb9739d42016-08-31 08:43:37345}
346
Kate Stoneb9c1b512016-09-06 20:57:50347size_t StringExtractor::GetHexByteString(std::string &str) {
348 str.clear();
349 str.reserve(GetBytesLeft() / 2);
350 char ch;
351 while ((ch = GetHexU8()) != '\0')
352 str.append(1, ch);
353 return str.size();
354}
355
356size_t StringExtractor::GetHexByteStringFixedLength(std::string &str,
357 uint32_t nibble_length) {
358 str.clear();
359
360 uint32_t nibble_count = 0;
361 for (const char *pch = Peek();
362 (nibble_count < nibble_length) && (pch != nullptr);
363 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
364 }
365
366 return str.size();
367}
368
369size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
370 char terminator) {
371 str.clear();
372 char ch;
373 while ((ch = GetHexU8(0, false)) != '\0')
374 str.append(1, ch);
375 if (Peek() && *Peek() == terminator)
Greg Claytonde9d0492011-01-08 03:17:57376 return str.size();
Kate Stoneb9c1b512016-09-06 20:57:50377
378 str.clear();
379 return str.size();
Greg Claytonde9d0492011-01-08 03:17:57380}
381
Kate Stoneb9c1b512016-09-06 20:57:50382bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
383 llvm::StringRef &value) {
384 // Read something in the form of NNNN:VVVV; where NNNN is any character
385 // that is not a colon, followed by a ':' character, then a value (one or
386 // more ';' chars), followed by a ';'
387 if (m_index >= m_packet.size())
388 return fail();
Pavel Labathb9739d42016-08-31 08:43:37389
Kate Stoneb9c1b512016-09-06 20:57:50390 llvm::StringRef view(m_packet);
391 if (view.empty())
392 return fail();
Pavel Labathb9739d42016-08-31 08:43:37393
Kate Stoneb9c1b512016-09-06 20:57:50394 llvm::StringRef a, b, c, d;
395 view = view.substr(m_index);
396 std::tie(a, b) = view.split(':');
397 if (a.empty() || b.empty())
398 return fail();
399 std::tie(c, d) = b.split(';');
400 if (b == c && d.empty())
401 return fail();
402
403 name = a;
404 value = c;
405 if (d.empty())
406 m_index = m_packet.size();
407 else {
408 size_t bytes_consumed = d.data() - view.data();
409 m_index += bytes_consumed;
410 }
411 return true;
Todd Fialaaf245d12014-06-30 21:05:18412}
413
Kate Stoneb9c1b512016-09-06 20:57:50414void StringExtractor::SkipSpaces() {
415 const size_t n = m_packet.size();
416 while (m_index < n && isspace(m_packet[m_index]))
417 ++m_index;
Daniel Maleae0f8f572013-08-26 23:57:52418}