[mlir][int-range] Limit xor int range inference to i1 (#116968)
[llvm-project.git] / lldb / source / Utility / StringExtractor.cpp
blob579faa3da42f3d771d3ef3734ae631948b31c6a2
1 //===-- StringExtractor.cpp -----------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Utility/StringExtractor.h"
10 #include "llvm/ADT/StringExtras.h"
12 #include <tuple>
14 #include <cctype>
15 #include <cstdlib>
16 #include <cstring>
18 static 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;
28 // StringExtractor constructor
29 StringExtractor::StringExtractor() : m_packet() {}
31 StringExtractor::StringExtractor(llvm::StringRef packet_str) : m_packet() {
32 m_packet.assign(packet_str.begin(), packet_str.end());
35 StringExtractor::StringExtractor(const char *packet_cstr) : m_packet() {
36 if (packet_cstr)
37 m_packet.assign(packet_cstr);
40 // Destructor
41 StringExtractor::~StringExtractor() = default;
43 char StringExtractor::GetChar(char fail_value) {
44 if (m_index < m_packet.size()) {
45 char ch = m_packet[m_index];
46 ++m_index;
47 return ch;
49 m_index = UINT64_MAX;
50 return fail_value;
53 // If a pair of valid hex digits exist at the head of the StringExtractor they
54 // are decoded into an unsigned byte and returned by this function
56 // If there is not a pair of valid hex digits at the head of the
57 // StringExtractor, it is left unchanged and -1 is returned
58 int StringExtractor::DecodeHexU8() {
59 SkipSpaces();
60 if (GetBytesLeft() < 2) {
61 return -1;
63 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
64 const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
65 if (hi_nibble == -1 || lo_nibble == -1) {
66 return -1;
68 m_index += 2;
69 return static_cast<uint8_t>((hi_nibble << 4) + lo_nibble);
72 // Extract an unsigned character from two hex ASCII chars in the packet string,
73 // or return fail_value on failure
74 uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
75 // On success, fail_value will be overwritten with the next character in the
76 // stream
77 GetHexU8Ex(fail_value, set_eof_on_fail);
78 return fail_value;
81 bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
82 int byte = DecodeHexU8();
83 if (byte == -1) {
84 if (set_eof_on_fail || m_index >= m_packet.size())
85 m_index = UINT64_MAX;
86 // ch should not be changed in case of failure
87 return false;
89 ch = static_cast<uint8_t>(byte);
90 return true;
93 uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) {
94 if (m_index < m_packet.size()) {
95 char *end = nullptr;
96 const char *start = m_packet.c_str();
97 const char *cstr = start + m_index;
98 uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
100 if (end && end != cstr) {
101 m_index = end - start;
102 return result;
105 return fail_value;
108 int32_t StringExtractor::GetS32(int32_t fail_value, int base) {
109 if (m_index < m_packet.size()) {
110 char *end = nullptr;
111 const char *start = m_packet.c_str();
112 const char *cstr = start + m_index;
113 int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
115 if (end && end != cstr) {
116 m_index = end - start;
117 return result;
120 return fail_value;
123 uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) {
124 if (m_index < m_packet.size()) {
125 char *end = nullptr;
126 const char *start = m_packet.c_str();
127 const char *cstr = start + m_index;
128 uint64_t result = ::strtoull(cstr, &end, base);
130 if (end && end != cstr) {
131 m_index = end - start;
132 return result;
135 return fail_value;
138 int64_t StringExtractor::GetS64(int64_t fail_value, int base) {
139 if (m_index < m_packet.size()) {
140 char *end = nullptr;
141 const char *start = m_packet.c_str();
142 const char *cstr = start + m_index;
143 int64_t result = ::strtoll(cstr, &end, base);
145 if (end && end != cstr) {
146 m_index = end - start;
147 return result;
150 return fail_value;
153 uint32_t StringExtractor::GetHexMaxU32(bool little_endian,
154 uint32_t fail_value) {
155 uint32_t result = 0;
156 uint32_t nibble_count = 0;
158 SkipSpaces();
159 if (little_endian) {
160 uint32_t shift_amount = 0;
161 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
162 // Make sure we don't exceed the size of a uint32_t...
163 if (nibble_count >= (sizeof(uint32_t) * 2)) {
164 m_index = UINT64_MAX;
165 return fail_value;
168 uint8_t nibble_lo;
169 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
170 ++m_index;
171 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
172 nibble_lo = xdigit_to_sint(m_packet[m_index]);
173 ++m_index;
174 result |= (static_cast<uint32_t>(nibble_hi) << (shift_amount + 4));
175 result |= (static_cast<uint32_t>(nibble_lo) << shift_amount);
176 nibble_count += 2;
177 shift_amount += 8;
178 } else {
179 result |= (static_cast<uint32_t>(nibble_hi) << shift_amount);
180 nibble_count += 1;
181 shift_amount += 4;
184 } else {
185 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
186 // Make sure we don't exceed the size of a uint32_t...
187 if (nibble_count >= (sizeof(uint32_t) * 2)) {
188 m_index = UINT64_MAX;
189 return fail_value;
192 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
193 // Big Endian
194 result <<= 4;
195 result |= nibble;
197 ++m_index;
198 ++nibble_count;
201 return result;
204 uint64_t StringExtractor::GetHexMaxU64(bool little_endian,
205 uint64_t fail_value) {
206 uint64_t result = 0;
207 uint32_t nibble_count = 0;
209 SkipSpaces();
210 if (little_endian) {
211 uint32_t shift_amount = 0;
212 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
213 // Make sure we don't exceed the size of a uint64_t...
214 if (nibble_count >= (sizeof(uint64_t) * 2)) {
215 m_index = UINT64_MAX;
216 return fail_value;
219 uint8_t nibble_lo;
220 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
221 ++m_index;
222 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
223 nibble_lo = xdigit_to_sint(m_packet[m_index]);
224 ++m_index;
225 result |= (static_cast<uint64_t>(nibble_hi) << (shift_amount + 4));
226 result |= (static_cast<uint64_t>(nibble_lo) << shift_amount);
227 nibble_count += 2;
228 shift_amount += 8;
229 } else {
230 result |= (static_cast<uint64_t>(nibble_hi) << shift_amount);
231 nibble_count += 1;
232 shift_amount += 4;
235 } else {
236 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
237 // Make sure we don't exceed the size of a uint64_t...
238 if (nibble_count >= (sizeof(uint64_t) * 2)) {
239 m_index = UINT64_MAX;
240 return fail_value;
243 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
244 // Big Endian
245 result <<= 4;
246 result |= nibble;
248 ++m_index;
249 ++nibble_count;
252 return result;
255 bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
256 llvm::StringRef S = GetStringRef();
257 if (!S.starts_with(str))
258 return false;
259 else
260 m_index += str.size();
261 return true;
264 size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
265 uint8_t fail_fill_value) {
266 size_t bytes_extracted = 0;
267 while (!dest.empty() && GetBytesLeft() > 0) {
268 dest[0] = GetHexU8(fail_fill_value);
269 if (!IsGood())
270 break;
271 ++bytes_extracted;
272 dest = dest.drop_front();
275 if (!dest.empty())
276 ::memset(dest.data(), fail_fill_value, dest.size());
278 return bytes_extracted;
281 // Decodes all valid hex encoded bytes at the head of the StringExtractor,
282 // limited by dst_len.
284 // Returns the number of bytes successfully decoded
285 size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) {
286 size_t bytes_extracted = 0;
287 while (!dest.empty()) {
288 int decode = DecodeHexU8();
289 if (decode == -1)
290 break;
291 dest[0] = static_cast<uint8_t>(decode);
292 dest = dest.drop_front();
293 ++bytes_extracted;
295 return bytes_extracted;
298 size_t StringExtractor::GetHexByteString(std::string &str) {
299 str.clear();
300 str.reserve(GetBytesLeft() / 2);
301 char ch;
302 while ((ch = GetHexU8()) != '\0')
303 str.append(1, ch);
304 return str.size();
307 size_t StringExtractor::GetHexByteStringFixedLength(std::string &str,
308 uint32_t nibble_length) {
309 str.clear();
311 uint32_t nibble_count = 0;
312 for (const char *pch = Peek();
313 (nibble_count < nibble_length) && (pch != nullptr);
314 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
317 return str.size();
320 size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
321 char terminator) {
322 str.clear();
323 char ch;
324 while ((ch = GetHexU8(0, false)) != '\0')
325 str.append(1, ch);
326 if (Peek() && *Peek() == terminator)
327 return str.size();
329 str.clear();
330 return str.size();
333 bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
334 llvm::StringRef &value) {
335 // Read something in the form of NNNN:VVVV; where NNNN is any character that
336 // is not a colon, followed by a ':' character, then a value (one or more ';'
337 // chars), followed by a ';'
338 if (m_index >= m_packet.size())
339 return fail();
341 llvm::StringRef view(m_packet);
342 if (view.empty())
343 return fail();
345 llvm::StringRef a, b, c, d;
346 view = view.substr(m_index);
347 std::tie(a, b) = view.split(':');
348 if (a.empty() || b.empty())
349 return fail();
350 std::tie(c, d) = b.split(';');
351 if (b == c && d.empty())
352 return fail();
354 name = a;
355 value = c;
356 if (d.empty())
357 m_index = m_packet.size();
358 else {
359 size_t bytes_consumed = d.data() - view.data();
360 m_index += bytes_consumed;
362 return true;
365 void StringExtractor::SkipSpaces() {
366 const size_t n = m_packet.size();
367 while (m_index < n && llvm::isSpace(m_packet[m_index]))
368 ++m_index;