blob: c439edde22b7a35adebd5a04563877740786e4fa [file] [log] [blame]
Zachary Turner44c35e82016-08-29 19:45:59 +00001//===-- StdStringExtractor.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/StdStringExtractor.h"
11
12// C Includes
13#include <stdlib.h>
14
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18
Kate Stoneb9c1b512016-09-06 20:57:50 +000019static inline int xdigit_to_sint(char ch) {
20 if (ch >= 'a' && ch <= 'f')
21 return 10 + ch - 'a';
22 if (ch >= 'A' && ch <= 'F')
23 return 10 + ch - 'A';
24 if (ch >= '0' && ch <= '9')
25 return ch - '0';
26 return -1;
Zachary Turner44c35e82016-08-29 19:45:59 +000027}
28
29//----------------------------------------------------------------------
30// StdStringExtractor constructor
31//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000032StdStringExtractor::StdStringExtractor() : m_packet(), m_index(0) {}
33
34StdStringExtractor::StdStringExtractor(const char *packet_cstr)
35 : m_packet(), m_index(0) {
36 if (packet_cstr)
37 m_packet.assign(packet_cstr);
Zachary Turner44c35e82016-08-29 19:45:59 +000038}
39
Zachary Turner44c35e82016-08-29 19:45:59 +000040//----------------------------------------------------------------------
41// StdStringExtractor copy constructor
42//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000043StdStringExtractor::StdStringExtractor(const StdStringExtractor &rhs)
44 : m_packet(rhs.m_packet), m_index(rhs.m_index) {}
Zachary Turner44c35e82016-08-29 19:45:59 +000045
46//----------------------------------------------------------------------
47// StdStringExtractor assignment operator
48//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000049const StdStringExtractor &StdStringExtractor::
50operator=(const StdStringExtractor &rhs) {
51 if (this != &rhs) {
52 m_packet = rhs.m_packet;
53 m_index = rhs.m_index;
54 }
55 return *this;
Zachary Turner44c35e82016-08-29 19:45:59 +000056}
57
58//----------------------------------------------------------------------
59// Destructor
60//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000061StdStringExtractor::~StdStringExtractor() {}
Zachary Turner44c35e82016-08-29 19:45:59 +000062
Kate Stoneb9c1b512016-09-06 20:57:50 +000063char StdStringExtractor::GetChar(char fail_value) {
64 if (m_index < m_packet.size()) {
65 char ch = m_packet[m_index];
66 ++m_index;
67 return ch;
68 }
69 m_index = UINT64_MAX;
70 return fail_value;
Zachary Turner44c35e82016-08-29 19:45:59 +000071}
72
73//----------------------------------------------------------------------
74// If a pair of valid hex digits exist at the head of the
75// StdStringExtractor they are decoded into an unsigned byte and returned
76// by this function
77//
78// If there is not a pair of valid hex digits at the head of the
79// StdStringExtractor, it is left unchanged and -1 is returned
80//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000081int StdStringExtractor::DecodeHexU8() {
82 SkipSpaces();
83 if (GetBytesLeft() < 2) {
84 return -1;
85 }
86 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
87 const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
88 if (hi_nibble == -1 || lo_nibble == -1) {
89 return -1;
90 }
91 m_index += 2;
92 return (uint8_t)((hi_nibble << 4) + lo_nibble);
Zachary Turner44c35e82016-08-29 19:45:59 +000093}
94
95//----------------------------------------------------------------------
96// Extract an unsigned character from two hex ASCII chars in the packet
97// string, or return fail_value on failure
98//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000099uint8_t StdStringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
100 // On success, fail_value will be overwritten with the next
101 // character in the stream
102 GetHexU8Ex(fail_value, set_eof_on_fail);
103 return fail_value;
Zachary Turner44c35e82016-08-29 19:45:59 +0000104}
105
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106bool StdStringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
107 int byte = DecodeHexU8();
108 if (byte == -1) {
109 if (set_eof_on_fail || m_index >= m_packet.size())
110 m_index = UINT64_MAX;
111 // ch should not be changed in case of failure
112 return false;
113 }
114 ch = (uint8_t)byte;
115 return true;
Zachary Turner44c35e82016-08-29 19:45:59 +0000116}
117
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118uint32_t StdStringExtractor::GetU32(uint32_t fail_value, int base) {
119 if (m_index < m_packet.size()) {
120 char *end = nullptr;
121 const char *start = m_packet.c_str();
122 const char *cstr = start + m_index;
123 uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
Zachary Turner44c35e82016-08-29 19:45:59 +0000124
Kate Stoneb9c1b512016-09-06 20:57:50 +0000125 if (end && end != cstr) {
126 m_index = end - start;
127 return result;
Zachary Turner44c35e82016-08-29 19:45:59 +0000128 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000129 }
130 return fail_value;
Zachary Turner44c35e82016-08-29 19:45:59 +0000131}
132
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133int32_t StdStringExtractor::GetS32(int32_t fail_value, int base) {
134 if (m_index < m_packet.size()) {
135 char *end = nullptr;
136 const char *start = m_packet.c_str();
137 const char *cstr = start + m_index;
138 int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
139
140 if (end && end != cstr) {
141 m_index = end - start;
142 return result;
Zachary Turner44c35e82016-08-29 19:45:59 +0000143 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 }
145 return fail_value;
Zachary Turner44c35e82016-08-29 19:45:59 +0000146}
147
Kate Stoneb9c1b512016-09-06 20:57:50 +0000148uint64_t StdStringExtractor::GetU64(uint64_t fail_value, int base) {
149 if (m_index < m_packet.size()) {
150 char *end = nullptr;
151 const char *start = m_packet.c_str();
152 const char *cstr = start + m_index;
153 uint64_t result = ::strtoull(cstr, &end, base);
Zachary Turner44c35e82016-08-29 19:45:59 +0000154
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 if (end && end != cstr) {
156 m_index = end - start;
157 return result;
Zachary Turner44c35e82016-08-29 19:45:59 +0000158 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000159 }
160 return fail_value;
Zachary Turner44c35e82016-08-29 19:45:59 +0000161}
162
Kate Stoneb9c1b512016-09-06 20:57:50 +0000163int64_t StdStringExtractor::GetS64(int64_t fail_value, int base) {
164 if (m_index < m_packet.size()) {
165 char *end = nullptr;
166 const char *start = m_packet.c_str();
167 const char *cstr = start + m_index;
168 int64_t result = ::strtoll(cstr, &end, base);
169
170 if (end && end != cstr) {
171 m_index = end - start;
172 return result;
Zachary Turner44c35e82016-08-29 19:45:59 +0000173 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174 }
175 return fail_value;
Zachary Turner44c35e82016-08-29 19:45:59 +0000176}
177
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178uint32_t StdStringExtractor::GetHexMaxU32(bool little_endian,
179 uint32_t fail_value) {
180 uint32_t result = 0;
181 uint32_t nibble_count = 0;
Zachary Turner44c35e82016-08-29 19:45:59 +0000182
Kate Stoneb9c1b512016-09-06 20:57:50 +0000183 SkipSpaces();
184 if (little_endian) {
185 uint32_t shift_amount = 0;
186 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
187 // Make sure we don't exceed the size of a uint32_t...
188 if (nibble_count >= (sizeof(uint32_t) * 2)) {
189 m_index = UINT64_MAX;
190 return fail_value;
191 }
Zachary Turner44c35e82016-08-29 19:45:59 +0000192
Kate Stoneb9c1b512016-09-06 20:57:50 +0000193 uint8_t nibble_lo;
194 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
195 ++m_index;
196 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
197 nibble_lo = xdigit_to_sint(m_packet[m_index]);
198 ++m_index;
199 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
200 result |= ((uint32_t)nibble_lo << shift_amount);
201 nibble_count += 2;
202 shift_amount += 8;
203 } else {
204 result |= ((uint32_t)nibble_hi << shift_amount);
205 nibble_count += 1;
206 shift_amount += 4;
207 }
Zachary Turner44c35e82016-08-29 19:45:59 +0000208 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000209 } else {
210 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
211 // Make sure we don't exceed the size of a uint32_t...
212 if (nibble_count >= (sizeof(uint32_t) * 2)) {
213 m_index = UINT64_MAX;
214 return fail_value;
215 }
216
217 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
218 // Big Endian
219 result <<= 4;
220 result |= nibble;
221
222 ++m_index;
223 ++nibble_count;
224 }
225 }
226 return result;
227}
228
229uint64_t StdStringExtractor::GetHexMaxU64(bool little_endian,
230 uint64_t fail_value) {
231 uint64_t result = 0;
232 uint32_t nibble_count = 0;
233
234 SkipSpaces();
235 if (little_endian) {
236 uint32_t shift_amount = 0;
237 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
238 // Make sure we don't exceed the size of a uint64_t...
239 if (nibble_count >= (sizeof(uint64_t) * 2)) {
240 m_index = UINT64_MAX;
241 return fail_value;
242 }
243
244 uint8_t nibble_lo;
245 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
246 ++m_index;
247 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
248 nibble_lo = xdigit_to_sint(m_packet[m_index]);
249 ++m_index;
250 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
251 result |= ((uint64_t)nibble_lo << shift_amount);
252 nibble_count += 2;
253 shift_amount += 8;
254 } else {
255 result |= ((uint64_t)nibble_hi << shift_amount);
256 nibble_count += 1;
257 shift_amount += 4;
258 }
259 }
260 } else {
261 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
262 // Make sure we don't exceed the size of a uint64_t...
263 if (nibble_count >= (sizeof(uint64_t) * 2)) {
264 m_index = UINT64_MAX;
265 return fail_value;
266 }
267
268 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
269 // Big Endian
270 result <<= 4;
271 result |= nibble;
272
273 ++m_index;
274 ++nibble_count;
275 }
276 }
277 return result;
278}
279
280size_t StdStringExtractor::GetHexBytes(void *dst_void, size_t dst_len,
281 uint8_t fail_fill_value) {
282 uint8_t *dst = (uint8_t *)dst_void;
283 size_t bytes_extracted = 0;
284 while (bytes_extracted < dst_len && GetBytesLeft()) {
285 dst[bytes_extracted] = GetHexU8(fail_fill_value);
286 if (IsGood())
287 ++bytes_extracted;
Zachary Turner44c35e82016-08-29 19:45:59 +0000288 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 break;
290 }
Zachary Turner44c35e82016-08-29 19:45:59 +0000291
Kate Stoneb9c1b512016-09-06 20:57:50 +0000292 for (size_t i = bytes_extracted; i < dst_len; ++i)
293 dst[i] = fail_fill_value;
Zachary Turner44c35e82016-08-29 19:45:59 +0000294
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 return bytes_extracted;
Zachary Turner44c35e82016-08-29 19:45:59 +0000296}
297
298//----------------------------------------------------------------------
299// Decodes all valid hex encoded bytes at the head of the
300// StdStringExtractor, limited by dst_len.
301//
302// Returns the number of bytes successfully decoded
303//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000304size_t StdStringExtractor::GetHexBytesAvail(void *dst_void, size_t dst_len) {
305 uint8_t *dst = (uint8_t *)dst_void;
306 size_t bytes_extracted = 0;
307 while (bytes_extracted < dst_len) {
308 int decode = DecodeHexU8();
309 if (decode == -1) {
310 break;
Zachary Turner44c35e82016-08-29 19:45:59 +0000311 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000312 dst[bytes_extracted++] = (uint8_t)decode;
313 }
314 return bytes_extracted;
Zachary Turner44c35e82016-08-29 19:45:59 +0000315}
316
317// Consume ASCII hex nibble character pairs until we have decoded byte_size
318// bytes of data.
319
Kate Stoneb9c1b512016-09-06 20:57:50 +0000320uint64_t StdStringExtractor::GetHexWithFixedSize(uint32_t byte_size,
321 bool little_endian,
322 uint64_t fail_value) {
323 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) {
324 uint64_t result = 0;
325 uint32_t i;
326 if (little_endian) {
327 // Little Endian
328 uint32_t shift_amount;
329 for (i = 0, shift_amount = 0; i < byte_size && IsGood();
330 ++i, shift_amount += 8) {
331 result |= ((uint64_t)GetHexU8() << shift_amount);
332 }
333 } else {
334 // Big Endian
335 for (i = 0; i < byte_size && IsGood(); ++i) {
336 result <<= 8;
337 result |= GetHexU8();
338 }
Zachary Turner44c35e82016-08-29 19:45:59 +0000339 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000340 }
341 m_index = UINT64_MAX;
342 return fail_value;
Zachary Turner44c35e82016-08-29 19:45:59 +0000343}
344
Kate Stoneb9c1b512016-09-06 20:57:50 +0000345size_t StdStringExtractor::GetHexByteString(std::string &str) {
346 str.clear();
347 str.reserve(GetBytesLeft() / 2);
348 char ch;
349 while ((ch = GetHexU8()) != '\0')
350 str.append(1, ch);
351 return str.size();
352}
353
354size_t StdStringExtractor::GetHexByteStringFixedLength(std::string &str,
355 uint32_t nibble_length) {
356 str.clear();
357
358 uint32_t nibble_count = 0;
359 for (const char *pch = Peek();
360 (nibble_count < nibble_length) && (pch != nullptr);
361 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
362 }
363
364 return str.size();
365}
366
367size_t StdStringExtractor::GetHexByteStringTerminatedBy(std::string &str,
368 char terminator) {
369 str.clear();
370 char ch;
371 while ((ch = GetHexU8(0, false)) != '\0')
372 str.append(1, ch);
373 if (Peek() && *Peek() == terminator)
Zachary Turner44c35e82016-08-29 19:45:59 +0000374 return str.size();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000375
376 str.clear();
377 return str.size();
Zachary Turner44c35e82016-08-29 19:45:59 +0000378}
379
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380bool StdStringExtractor::GetNameColonValue(std::string &name,
381 std::string &value) {
382 // Read something in the form of NNNN:VVVV; where NNNN is any character
383 // that is not a colon, followed by a ':' character, then a value (one or
384 // more ';' chars), followed by a ';'
385 if (m_index < m_packet.size()) {
386 const size_t colon_idx = m_packet.find(':', m_index);
387 if (colon_idx != std::string::npos) {
388 const size_t semicolon_idx = m_packet.find(';', colon_idx);
389 if (semicolon_idx != std::string::npos) {
390 name.assign(m_packet, m_index, colon_idx - m_index);
391 value.assign(m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
392 m_index = semicolon_idx + 1;
393 return true;
394 }
Zachary Turner44c35e82016-08-29 19:45:59 +0000395 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396 }
397 m_index = UINT64_MAX;
398 return false;
Zachary Turner44c35e82016-08-29 19:45:59 +0000399}
400
Kate Stoneb9c1b512016-09-06 20:57:50 +0000401void StdStringExtractor::SkipSpaces() {
402 const size_t n = m_packet.size();
403 while (m_index < n && isspace(m_packet[m_index]))
404 ++m_index;
Zachary Turner44c35e82016-08-29 19:45:59 +0000405}