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