1 //===-- StringExtractor.cpp -----------------------------------------------===//
3 // 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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Utility/StringExtractor.h"
10 #include "llvm/ADT/StringExtras.h"
18 static inline int xdigit_to_sint(char ch
) {
19 if (ch
>= 'a' && ch
<= 'f')
21 if (ch
>= 'A' && ch
<= 'F')
23 if (ch
>= '0' && ch
<= '9')
28 // StringExtractor constructor
29 StringExtractor::StringExtractor() : m_packet() {}
31 StringExtractor::StringExtractor(llvm::StringRef packet_str
)
32 : m_packet(), m_index(0) {
33 m_packet
.assign(packet_str
.begin(), packet_str
.end());
36 StringExtractor::StringExtractor(const char *packet_cstr
)
37 : m_packet(), m_index(0) {
39 m_packet
.assign(packet_cstr
);
43 StringExtractor::~StringExtractor() = default;
45 char StringExtractor::GetChar(char fail_value
) {
46 if (m_index
< m_packet
.size()) {
47 char ch
= m_packet
[m_index
];
55 // 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
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
60 int StringExtractor::DecodeHexU8() {
62 if (GetBytesLeft() < 2) {
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) {
71 return static_cast<uint8_t>((hi_nibble
<< 4) + lo_nibble
);
74 // Extract an unsigned character from two hex ASCII chars in the packet string,
75 // or return fail_value on failure
76 uint8_t StringExtractor::GetHexU8(uint8_t fail_value
, bool set_eof_on_fail
) {
77 // On success, fail_value will be overwritten with the next character in the
79 GetHexU8Ex(fail_value
, set_eof_on_fail
);
83 bool StringExtractor::GetHexU8Ex(uint8_t &ch
, bool set_eof_on_fail
) {
84 int byte
= DecodeHexU8();
86 if (set_eof_on_fail
|| m_index
>= m_packet
.size())
88 // ch should not be changed in case of failure
91 ch
= static_cast<uint8_t>(byte
);
95 uint32_t StringExtractor::GetU32(uint32_t fail_value
, int base
) {
96 if (m_index
< m_packet
.size()) {
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
));
102 if (end
&& end
!= cstr
) {
103 m_index
= end
- start
;
110 int32_t StringExtractor::GetS32(int32_t fail_value
, int base
) {
111 if (m_index
< m_packet
.size()) {
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
));
117 if (end
&& end
!= cstr
) {
118 m_index
= end
- start
;
125 uint64_t StringExtractor::GetU64(uint64_t fail_value
, int base
) {
126 if (m_index
< m_packet
.size()) {
128 const char *start
= m_packet
.c_str();
129 const char *cstr
= start
+ m_index
;
130 uint64_t result
= ::strtoull(cstr
, &end
, base
);
132 if (end
&& end
!= cstr
) {
133 m_index
= end
- start
;
140 int64_t StringExtractor::GetS64(int64_t fail_value
, int base
) {
141 if (m_index
< m_packet
.size()) {
143 const char *start
= m_packet
.c_str();
144 const char *cstr
= start
+ m_index
;
145 int64_t result
= ::strtoll(cstr
, &end
, base
);
147 if (end
&& end
!= cstr
) {
148 m_index
= end
- start
;
155 uint32_t StringExtractor::GetHexMaxU32(bool little_endian
,
156 uint32_t fail_value
) {
158 uint32_t nibble_count
= 0;
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
;
171 uint8_t nibble_hi
= xdigit_to_sint(m_packet
[m_index
]);
173 if (m_index
< m_packet
.size() && ::isxdigit(m_packet
[m_index
])) {
174 nibble_lo
= xdigit_to_sint(m_packet
[m_index
]);
176 result
|= (static_cast<uint32_t>(nibble_hi
) << (shift_amount
+ 4));
177 result
|= (static_cast<uint32_t>(nibble_lo
) << shift_amount
);
181 result
|= (static_cast<uint32_t>(nibble_hi
) << shift_amount
);
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
;
194 uint8_t nibble
= xdigit_to_sint(m_packet
[m_index
]);
206 uint64_t StringExtractor::GetHexMaxU64(bool little_endian
,
207 uint64_t fail_value
) {
209 uint32_t nibble_count
= 0;
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
;
222 uint8_t nibble_hi
= xdigit_to_sint(m_packet
[m_index
]);
224 if (m_index
< m_packet
.size() && ::isxdigit(m_packet
[m_index
])) {
225 nibble_lo
= xdigit_to_sint(m_packet
[m_index
]);
227 result
|= (static_cast<uint64_t>(nibble_hi
) << (shift_amount
+ 4));
228 result
|= (static_cast<uint64_t>(nibble_lo
) << shift_amount
);
232 result
|= (static_cast<uint64_t>(nibble_hi
) << shift_amount
);
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
;
245 uint8_t nibble
= xdigit_to_sint(m_packet
[m_index
]);
257 bool StringExtractor::ConsumeFront(const llvm::StringRef
&str
) {
258 llvm::StringRef S
= GetStringRef();
259 if (!S
.startswith(str
))
262 m_index
+= str
.size();
266 size_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
);
274 dest
= dest
.drop_front();
278 ::memset(dest
.data(), fail_fill_value
, dest
.size());
280 return bytes_extracted
;
283 // Decodes all valid hex encoded bytes at the head of the StringExtractor,
284 // limited by dst_len.
286 // Returns the number of bytes successfully decoded
287 size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef
<uint8_t> dest
) {
288 size_t bytes_extracted
= 0;
289 while (!dest
.empty()) {
290 int decode
= DecodeHexU8();
293 dest
[0] = static_cast<uint8_t>(decode
);
294 dest
= dest
.drop_front();
297 return bytes_extracted
;
300 size_t StringExtractor::GetHexByteString(std::string
&str
) {
302 str
.reserve(GetBytesLeft() / 2);
304 while ((ch
= GetHexU8()) != '\0')
309 size_t StringExtractor::GetHexByteStringFixedLength(std::string
&str
,
310 uint32_t nibble_length
) {
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) {
322 size_t StringExtractor::GetHexByteStringTerminatedBy(std::string
&str
,
326 while ((ch
= GetHexU8(0, false)) != '\0')
328 if (Peek() && *Peek() == terminator
)
335 bool StringExtractor::GetNameColonValue(llvm::StringRef
&name
,
336 llvm::StringRef
&value
) {
337 // 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 ';'
340 if (m_index
>= m_packet
.size())
343 llvm::StringRef
view(m_packet
);
347 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())
352 std::tie(c
, d
) = b
.split(';');
353 if (b
== c
&& d
.empty())
359 m_index
= m_packet
.size();
361 size_t bytes_consumed
= d
.data() - view
.data();
362 m_index
+= bytes_consumed
;
367 void StringExtractor::SkipSpaces() {
368 const size_t n
= m_packet
.size();
369 while (m_index
< n
&& llvm::isSpace(m_packet
[m_index
]))