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 // C Includes 13 #include <stdlib.h> 14 15 // C++ Includes 16 #include <tuple> 17 // Other libraries and framework includes 18 // Project includes 19 20 static inline int 21 xdigit_to_sint (char ch) 22 { 23 if (ch >= 'a' && ch <= 'f') 24 return 10 + ch - 'a'; 25 if (ch >= 'A' && ch <= 'F') 26 return 10 + ch - 'A'; 27 if (ch >= '0' && ch <= '9') 28 return ch - '0'; 29 return -1; 30 } 31 32 //---------------------------------------------------------------------- 33 // StringExtractor constructor 34 //---------------------------------------------------------------------- 35 StringExtractor::StringExtractor() : 36 m_packet(), 37 m_index (0) 38 { 39 } 40 41 StringExtractor::StringExtractor(llvm::StringRef packet_str) : m_packet(), m_index(0) 42 { 43 m_packet.assign(packet_str.begin(), packet_str.end()); 44 } 45 46 StringExtractor::StringExtractor(const char *packet_cstr) : 47 m_packet(), 48 m_index (0) 49 { 50 if (packet_cstr) 51 m_packet.assign (packet_cstr); 52 } 53 54 55 //---------------------------------------------------------------------- 56 // StringExtractor copy constructor 57 //---------------------------------------------------------------------- 58 StringExtractor::StringExtractor(const StringExtractor& rhs) : 59 m_packet (rhs.m_packet), 60 m_index (rhs.m_index) 61 { 62 63 } 64 65 //---------------------------------------------------------------------- 66 // StringExtractor assignment operator 67 //---------------------------------------------------------------------- 68 const StringExtractor& 69 StringExtractor::operator=(const StringExtractor& rhs) 70 { 71 if (this != &rhs) 72 { 73 m_packet = rhs.m_packet; 74 m_index = rhs.m_index; 75 76 } 77 return *this; 78 } 79 80 //---------------------------------------------------------------------- 81 // Destructor 82 //---------------------------------------------------------------------- 83 StringExtractor::~StringExtractor() 84 { 85 } 86 87 88 char 89 StringExtractor::GetChar (char fail_value) 90 { 91 if (m_index < m_packet.size()) 92 { 93 char ch = m_packet[m_index]; 94 ++m_index; 95 return ch; 96 } 97 m_index = UINT64_MAX; 98 return fail_value; 99 } 100 101 //---------------------------------------------------------------------- 102 // If a pair of valid hex digits exist at the head of the 103 // StringExtractor they are decoded into an unsigned byte and returned 104 // by this function 105 // 106 // If there is not a pair of valid hex digits at the head of the 107 // StringExtractor, it is left unchanged and -1 is returned 108 //---------------------------------------------------------------------- 109 int 110 StringExtractor::DecodeHexU8() 111 { 112 SkipSpaces(); 113 if (GetBytesLeft() < 2) 114 { 115 return -1; 116 } 117 const int hi_nibble = xdigit_to_sint(m_packet[m_index]); 118 const int lo_nibble = xdigit_to_sint(m_packet[m_index+1]); 119 if (hi_nibble == -1 || lo_nibble == -1) 120 { 121 return -1; 122 } 123 m_index += 2; 124 return (uint8_t)((hi_nibble << 4) + lo_nibble); 125 } 126 127 //---------------------------------------------------------------------- 128 // Extract an unsigned character from two hex ASCII chars in the packet 129 // string, or return fail_value on failure 130 //---------------------------------------------------------------------- 131 uint8_t 132 StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail) 133 { 134 // On success, fail_value will be overwritten with the next 135 // character in the stream 136 GetHexU8Ex(fail_value, set_eof_on_fail); 137 return fail_value; 138 } 139 140 bool 141 StringExtractor::GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail) 142 { 143 int byte = DecodeHexU8(); 144 if (byte == -1) 145 { 146 if (set_eof_on_fail || m_index >= m_packet.size()) 147 m_index = UINT64_MAX; 148 // ch should not be changed in case of failure 149 return false; 150 } 151 ch = (uint8_t)byte; 152 return true; 153 } 154 155 uint32_t 156 StringExtractor::GetU32 (uint32_t fail_value, int base) 157 { 158 if (m_index < m_packet.size()) 159 { 160 char *end = nullptr; 161 const char *start = m_packet.c_str(); 162 const char *cstr = start + m_index; 163 uint32_t result = static_cast<uint32_t>(::strtoul (cstr, &end, base)); 164 165 if (end && end != cstr) 166 { 167 m_index = end - start; 168 return result; 169 } 170 } 171 return fail_value; 172 } 173 174 int32_t 175 StringExtractor::GetS32 (int32_t fail_value, int base) 176 { 177 if (m_index < m_packet.size()) 178 { 179 char *end = nullptr; 180 const char *start = m_packet.c_str(); 181 const char *cstr = start + m_index; 182 int32_t result = static_cast<int32_t>(::strtol (cstr, &end, base)); 183 184 if (end && end != cstr) 185 { 186 m_index = end - start; 187 return result; 188 } 189 } 190 return fail_value; 191 } 192 193 194 uint64_t 195 StringExtractor::GetU64 (uint64_t fail_value, int base) 196 { 197 if (m_index < m_packet.size()) 198 { 199 char *end = nullptr; 200 const char *start = m_packet.c_str(); 201 const char *cstr = start + m_index; 202 uint64_t result = ::strtoull (cstr, &end, base); 203 204 if (end && end != cstr) 205 { 206 m_index = end - start; 207 return result; 208 } 209 } 210 return fail_value; 211 } 212 213 int64_t 214 StringExtractor::GetS64 (int64_t fail_value, int base) 215 { 216 if (m_index < m_packet.size()) 217 { 218 char *end = nullptr; 219 const char *start = m_packet.c_str(); 220 const char *cstr = start + m_index; 221 int64_t result = ::strtoll (cstr, &end, base); 222 223 if (end && end != cstr) 224 { 225 m_index = end - start; 226 return result; 227 } 228 } 229 return fail_value; 230 } 231 232 233 uint32_t 234 StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value) 235 { 236 uint32_t result = 0; 237 uint32_t nibble_count = 0; 238 239 SkipSpaces(); 240 if (little_endian) 241 { 242 uint32_t shift_amount = 0; 243 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 244 { 245 // Make sure we don't exceed the size of a uint32_t... 246 if (nibble_count >= (sizeof(uint32_t) * 2)) 247 { 248 m_index = UINT64_MAX; 249 return fail_value; 250 } 251 252 uint8_t nibble_lo; 253 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]); 254 ++m_index; 255 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 256 { 257 nibble_lo = xdigit_to_sint (m_packet[m_index]); 258 ++m_index; 259 result |= ((uint32_t)nibble_hi << (shift_amount + 4)); 260 result |= ((uint32_t)nibble_lo << shift_amount); 261 nibble_count += 2; 262 shift_amount += 8; 263 } 264 else 265 { 266 result |= ((uint32_t)nibble_hi << shift_amount); 267 nibble_count += 1; 268 shift_amount += 4; 269 } 270 271 } 272 } 273 else 274 { 275 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 276 { 277 // Make sure we don't exceed the size of a uint32_t... 278 if (nibble_count >= (sizeof(uint32_t) * 2)) 279 { 280 m_index = UINT64_MAX; 281 return fail_value; 282 } 283 284 uint8_t nibble = xdigit_to_sint (m_packet[m_index]); 285 // Big Endian 286 result <<= 4; 287 result |= nibble; 288 289 ++m_index; 290 ++nibble_count; 291 } 292 } 293 return result; 294 } 295 296 uint64_t 297 StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value) 298 { 299 uint64_t result = 0; 300 uint32_t nibble_count = 0; 301 302 SkipSpaces(); 303 if (little_endian) 304 { 305 uint32_t shift_amount = 0; 306 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 307 { 308 // Make sure we don't exceed the size of a uint64_t... 309 if (nibble_count >= (sizeof(uint64_t) * 2)) 310 { 311 m_index = UINT64_MAX; 312 return fail_value; 313 } 314 315 uint8_t nibble_lo; 316 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]); 317 ++m_index; 318 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 319 { 320 nibble_lo = xdigit_to_sint (m_packet[m_index]); 321 ++m_index; 322 result |= ((uint64_t)nibble_hi << (shift_amount + 4)); 323 result |= ((uint64_t)nibble_lo << shift_amount); 324 nibble_count += 2; 325 shift_amount += 8; 326 } 327 else 328 { 329 result |= ((uint64_t)nibble_hi << shift_amount); 330 nibble_count += 1; 331 shift_amount += 4; 332 } 333 334 } 335 } 336 else 337 { 338 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 339 { 340 // Make sure we don't exceed the size of a uint64_t... 341 if (nibble_count >= (sizeof(uint64_t) * 2)) 342 { 343 m_index = UINT64_MAX; 344 return fail_value; 345 } 346 347 uint8_t nibble = xdigit_to_sint (m_packet[m_index]); 348 // Big Endian 349 result <<= 4; 350 result |= nibble; 351 352 ++m_index; 353 ++nibble_count; 354 } 355 } 356 return result; 357 } 358 359 size_t 360 StringExtractor::GetHexBytes (llvm::MutableArrayRef<uint8_t> dest, uint8_t fail_fill_value) 361 { 362 size_t bytes_extracted = 0; 363 while (!dest.empty() && GetBytesLeft() > 0) 364 { 365 dest[0] = GetHexU8 (fail_fill_value); 366 if (!IsGood()) 367 break; 368 ++bytes_extracted; 369 dest = dest.drop_front(); 370 } 371 372 if (!dest.empty()) 373 ::memset(dest.data(), fail_fill_value, dest.size()); 374 375 return bytes_extracted; 376 } 377 378 //---------------------------------------------------------------------- 379 // Decodes all valid hex encoded bytes at the head of the 380 // StringExtractor, limited by dst_len. 381 // 382 // Returns the number of bytes successfully decoded 383 //---------------------------------------------------------------------- 384 size_t 385 StringExtractor::GetHexBytesAvail (llvm::MutableArrayRef<uint8_t> dest) 386 { 387 size_t bytes_extracted = 0; 388 while (!dest.empty()) 389 { 390 int decode = DecodeHexU8(); 391 if (decode == -1) 392 break; 393 dest[0] = (uint8_t)decode; 394 dest = dest.drop_front(); 395 ++bytes_extracted; 396 } 397 return bytes_extracted; 398 } 399 400 // Consume ASCII hex nibble character pairs until we have decoded byte_size 401 // bytes of data. 402 403 uint64_t 404 StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value) 405 { 406 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) 407 { 408 uint64_t result = 0; 409 uint32_t i; 410 if (little_endian) 411 { 412 // Little Endian 413 uint32_t shift_amount; 414 for (i = 0, shift_amount = 0; 415 i < byte_size && IsGood(); 416 ++i, shift_amount += 8) 417 { 418 result |= ((uint64_t)GetHexU8() << shift_amount); 419 } 420 } 421 else 422 { 423 // Big Endian 424 for (i = 0; i < byte_size && IsGood(); ++i) 425 { 426 result <<= 8; 427 result |= GetHexU8(); 428 } 429 } 430 } 431 m_index = UINT64_MAX; 432 return fail_value; 433 } 434 435 size_t 436 StringExtractor::GetHexByteString (std::string &str) 437 { 438 str.clear(); 439 str.reserve(GetBytesLeft() / 2); 440 char ch; 441 while ((ch = GetHexU8()) != '\0') 442 str.append(1, ch); 443 return str.size(); 444 } 445 446 size_t 447 StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length) 448 { 449 str.clear(); 450 451 uint32_t nibble_count = 0; 452 for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2) 453 {} 454 455 return str.size(); 456 } 457 458 size_t 459 StringExtractor::GetHexByteStringTerminatedBy (std::string &str, 460 char terminator) 461 { 462 str.clear(); 463 char ch; 464 while ((ch = GetHexU8(0,false)) != '\0') 465 str.append(1, ch); 466 if (Peek() && *Peek() == terminator) 467 return str.size(); 468 469 str.clear(); 470 return str.size(); 471 } 472 473 bool 474 StringExtractor::GetNameColonValue(llvm::StringRef &name, llvm::StringRef &value) 475 { 476 // Read something in the form of NNNN:VVVV; where NNNN is any character 477 // that is not a colon, followed by a ':' character, then a value (one or 478 // more ';' chars), followed by a ';' 479 if (m_index >= m_packet.size()) 480 return fail(); 481 482 llvm::StringRef view(m_packet); 483 if (view.empty()) 484 return fail(); 485 486 llvm::StringRef a, b, c, d; 487 view = view.substr(m_index); 488 std::tie(a, b) = view.split(':'); 489 if (a.empty() || b.empty()) 490 return fail(); 491 std::tie(c, d) = b.split(';'); 492 if (b == c && d.empty()) 493 return fail(); 494 495 name = a; 496 value = c; 497 if (d.empty()) 498 m_index = m_packet.size(); 499 else 500 { 501 size_t bytes_consumed = d.data() - view.data(); 502 m_index += bytes_consumed; 503 } 504 return true; 505 } 506 507 void 508 StringExtractor::SkipSpaces () 509 { 510 const size_t n = m_packet.size(); 511 while (m_index < n && isspace(m_packet[m_index])) 512 ++m_index; 513 } 514 515