1 //===-- 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 10 #include "lldb/Utility/StringExtractor.h" 11 12 #include <tuple> 13 14 #include <ctype.h> // for isxdigit, isspace 15 #include <stdlib.h> 16 #include <string.h> // for memset 17 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; 26 } 27 28 //---------------------------------------------------------------------- 29 // StringExtractor constructor 30 //---------------------------------------------------------------------- 31 StringExtractor::StringExtractor() : m_packet(), m_index(0) {} 32 33 StringExtractor::StringExtractor(llvm::StringRef packet_str) 34 : m_packet(), m_index(0) { 35 m_packet.assign(packet_str.begin(), packet_str.end()); 36 } 37 38 StringExtractor::StringExtractor(const char *packet_cstr) 39 : m_packet(), m_index(0) { 40 if (packet_cstr) 41 m_packet.assign(packet_cstr); 42 } 43 44 //---------------------------------------------------------------------- 45 // StringExtractor copy constructor 46 //---------------------------------------------------------------------- 47 StringExtractor::StringExtractor(const StringExtractor &rhs) 48 : m_packet(rhs.m_packet), m_index(rhs.m_index) {} 49 50 //---------------------------------------------------------------------- 51 // StringExtractor assignment operator 52 //---------------------------------------------------------------------- 53 const 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; 59 } 60 61 //---------------------------------------------------------------------- 62 // Destructor 63 //---------------------------------------------------------------------- 64 StringExtractor::~StringExtractor() {} 65 66 char 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; 74 } 75 76 //---------------------------------------------------------------------- 77 // 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 //---------------------------------------------------------------------- 84 int 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); 96 } 97 98 //---------------------------------------------------------------------- 99 // Extract an unsigned character from two hex ASCII chars in the packet 100 // string, or return fail_value on failure 101 //---------------------------------------------------------------------- 102 uint8_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; 107 } 108 109 bool 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; 119 } 120 121 uint32_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)); 127 128 if (end && end != cstr) { 129 m_index = end - start; 130 return result; 131 } 132 } 133 return fail_value; 134 } 135 136 int32_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; 146 } 147 } 148 return fail_value; 149 } 150 151 uint64_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); 157 158 if (end && end != cstr) { 159 m_index = end - start; 160 return result; 161 } 162 } 163 return fail_value; 164 } 165 166 int64_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; 176 } 177 } 178 return fail_value; 179 } 180 181 uint32_t StringExtractor::GetHexMaxU32(bool little_endian, 182 uint32_t fail_value) { 183 uint32_t result = 0; 184 uint32_t nibble_count = 0; 185 186 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 } 195 196 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 } 211 } 212 } 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 } 219 220 uint8_t nibble = xdigit_to_sint(m_packet[m_index]); 221 // Big Endian 222 result <<= 4; 223 result |= nibble; 224 225 ++m_index; 226 ++nibble_count; 227 } 228 } 229 return result; 230 } 231 232 uint64_t StringExtractor::GetHexMaxU64(bool little_endian, 233 uint64_t fail_value) { 234 uint64_t result = 0; 235 uint32_t nibble_count = 0; 236 237 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 } 246 247 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 } 262 } 263 } 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 } 270 271 uint8_t nibble = xdigit_to_sint(m_packet[m_index]); 272 // Big Endian 273 result <<= 4; 274 result |= nibble; 275 276 ++m_index; 277 ++nibble_count; 278 } 279 } 280 return result; 281 } 282 283 bool StringExtractor::ConsumeFront(const llvm::StringRef &str) { 284 llvm::StringRef S = GetStringRef(); 285 if (!S.startswith(str)) 286 return false; 287 else 288 m_index += str.size(); 289 return true; 290 } 291 292 size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest, 293 uint8_t fail_fill_value) { 294 size_t bytes_extracted = 0; 295 while (!dest.empty() && GetBytesLeft() > 0) { 296 dest[0] = GetHexU8(fail_fill_value); 297 if (!IsGood()) 298 break; 299 ++bytes_extracted; 300 dest = dest.drop_front(); 301 } 302 303 if (!dest.empty()) 304 ::memset(dest.data(), fail_fill_value, dest.size()); 305 306 return bytes_extracted; 307 } 308 309 //---------------------------------------------------------------------- 310 // Decodes all valid hex encoded bytes at the head of the 311 // StringExtractor, limited by dst_len. 312 // 313 // Returns the number of bytes successfully decoded 314 //---------------------------------------------------------------------- 315 size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) { 316 size_t bytes_extracted = 0; 317 while (!dest.empty()) { 318 int decode = DecodeHexU8(); 319 if (decode == -1) 320 break; 321 dest[0] = (uint8_t)decode; 322 dest = dest.drop_front(); 323 ++bytes_extracted; 324 } 325 return bytes_extracted; 326 } 327 328 // Consume ASCII hex nibble character pairs until we have decoded byte_size 329 // bytes of data. 330 331 uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size, 332 bool little_endian, 333 uint64_t fail_value) { 334 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) { 335 uint64_t result = 0; 336 uint32_t i; 337 if (little_endian) { 338 // Little Endian 339 uint32_t shift_amount; 340 for (i = 0, shift_amount = 0; i < byte_size && IsGood(); 341 ++i, shift_amount += 8) { 342 result |= ((uint64_t)GetHexU8() << shift_amount); 343 } 344 } else { 345 // Big Endian 346 for (i = 0; i < byte_size && IsGood(); ++i) { 347 result <<= 8; 348 result |= GetHexU8(); 349 } 350 } 351 } 352 m_index = UINT64_MAX; 353 return fail_value; 354 } 355 356 size_t StringExtractor::GetHexByteString(std::string &str) { 357 str.clear(); 358 str.reserve(GetBytesLeft() / 2); 359 char ch; 360 while ((ch = GetHexU8()) != '\0') 361 str.append(1, ch); 362 return str.size(); 363 } 364 365 size_t StringExtractor::GetHexByteStringFixedLength(std::string &str, 366 uint32_t nibble_length) { 367 str.clear(); 368 369 uint32_t nibble_count = 0; 370 for (const char *pch = Peek(); 371 (nibble_count < nibble_length) && (pch != nullptr); 372 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) { 373 } 374 375 return str.size(); 376 } 377 378 size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str, 379 char terminator) { 380 str.clear(); 381 char ch; 382 while ((ch = GetHexU8(0, false)) != '\0') 383 str.append(1, ch); 384 if (Peek() && *Peek() == terminator) 385 return str.size(); 386 387 str.clear(); 388 return str.size(); 389 } 390 391 bool StringExtractor::GetNameColonValue(llvm::StringRef &name, 392 llvm::StringRef &value) { 393 // Read something in the form of NNNN:VVVV; where NNNN is any character 394 // that is not a colon, followed by a ':' character, then a value (one or 395 // more ';' chars), followed by a ';' 396 if (m_index >= m_packet.size()) 397 return fail(); 398 399 llvm::StringRef view(m_packet); 400 if (view.empty()) 401 return fail(); 402 403 llvm::StringRef a, b, c, d; 404 view = view.substr(m_index); 405 std::tie(a, b) = view.split(':'); 406 if (a.empty() || b.empty()) 407 return fail(); 408 std::tie(c, d) = b.split(';'); 409 if (b == c && d.empty()) 410 return fail(); 411 412 name = a; 413 value = c; 414 if (d.empty()) 415 m_index = m_packet.size(); 416 else { 417 size_t bytes_consumed = d.data() - view.data(); 418 m_index += bytes_consumed; 419 } 420 return true; 421 } 422 423 void StringExtractor::SkipSpaces() { 424 const size_t n = m_packet.size(); 425 while (m_index < n && isspace(m_packet[m_index])) 426 ++m_index; 427 } 428