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