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 StringExtractor they 78 // are decoded into an unsigned byte and returned by this function 79 // 80 // If there is not a pair of valid hex digits at the head of the 81 // StringExtractor, it is left unchanged and -1 is returned 82 //---------------------------------------------------------------------- 83 int StringExtractor::DecodeHexU8() { 84 SkipSpaces(); 85 if (GetBytesLeft() < 2) { 86 return -1; 87 } 88 const int hi_nibble = xdigit_to_sint(m_packet[m_index]); 89 const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]); 90 if (hi_nibble == -1 || lo_nibble == -1) { 91 return -1; 92 } 93 m_index += 2; 94 return (uint8_t)((hi_nibble << 4) + lo_nibble); 95 } 96 97 //---------------------------------------------------------------------- 98 // Extract an unsigned character from two hex ASCII chars in the packet string, 99 // or return fail_value on failure 100 //---------------------------------------------------------------------- 101 uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) { 102 // On success, fail_value will be overwritten with the next character in the 103 // stream 104 GetHexU8Ex(fail_value, set_eof_on_fail); 105 return fail_value; 106 } 107 108 bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) { 109 int byte = DecodeHexU8(); 110 if (byte == -1) { 111 if (set_eof_on_fail || m_index >= m_packet.size()) 112 m_index = UINT64_MAX; 113 // ch should not be changed in case of failure 114 return false; 115 } 116 ch = (uint8_t)byte; 117 return true; 118 } 119 120 uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) { 121 if (m_index < m_packet.size()) { 122 char *end = nullptr; 123 const char *start = m_packet.c_str(); 124 const char *cstr = start + m_index; 125 uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base)); 126 127 if (end && end != cstr) { 128 m_index = end - start; 129 return result; 130 } 131 } 132 return fail_value; 133 } 134 135 int32_t StringExtractor::GetS32(int32_t fail_value, int base) { 136 if (m_index < m_packet.size()) { 137 char *end = nullptr; 138 const char *start = m_packet.c_str(); 139 const char *cstr = start + m_index; 140 int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base)); 141 142 if (end && end != cstr) { 143 m_index = end - start; 144 return result; 145 } 146 } 147 return fail_value; 148 } 149 150 uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) { 151 if (m_index < m_packet.size()) { 152 char *end = nullptr; 153 const char *start = m_packet.c_str(); 154 const char *cstr = start + m_index; 155 uint64_t result = ::strtoull(cstr, &end, base); 156 157 if (end && end != cstr) { 158 m_index = end - start; 159 return result; 160 } 161 } 162 return fail_value; 163 } 164 165 int64_t StringExtractor::GetS64(int64_t fail_value, int base) { 166 if (m_index < m_packet.size()) { 167 char *end = nullptr; 168 const char *start = m_packet.c_str(); 169 const char *cstr = start + m_index; 170 int64_t result = ::strtoll(cstr, &end, base); 171 172 if (end && end != cstr) { 173 m_index = end - start; 174 return result; 175 } 176 } 177 return fail_value; 178 } 179 180 uint32_t StringExtractor::GetHexMaxU32(bool little_endian, 181 uint32_t fail_value) { 182 uint32_t result = 0; 183 uint32_t nibble_count = 0; 184 185 SkipSpaces(); 186 if (little_endian) { 187 uint32_t shift_amount = 0; 188 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 189 // Make sure we don't exceed the size of a uint32_t... 190 if (nibble_count >= (sizeof(uint32_t) * 2)) { 191 m_index = UINT64_MAX; 192 return fail_value; 193 } 194 195 uint8_t nibble_lo; 196 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]); 197 ++m_index; 198 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 199 nibble_lo = xdigit_to_sint(m_packet[m_index]); 200 ++m_index; 201 result |= ((uint32_t)nibble_hi << (shift_amount + 4)); 202 result |= ((uint32_t)nibble_lo << shift_amount); 203 nibble_count += 2; 204 shift_amount += 8; 205 } else { 206 result |= ((uint32_t)nibble_hi << shift_amount); 207 nibble_count += 1; 208 shift_amount += 4; 209 } 210 } 211 } else { 212 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 213 // Make sure we don't exceed the size of a uint32_t... 214 if (nibble_count >= (sizeof(uint32_t) * 2)) { 215 m_index = UINT64_MAX; 216 return fail_value; 217 } 218 219 uint8_t nibble = xdigit_to_sint(m_packet[m_index]); 220 // Big Endian 221 result <<= 4; 222 result |= nibble; 223 224 ++m_index; 225 ++nibble_count; 226 } 227 } 228 return result; 229 } 230 231 uint64_t StringExtractor::GetHexMaxU64(bool little_endian, 232 uint64_t fail_value) { 233 uint64_t result = 0; 234 uint32_t nibble_count = 0; 235 236 SkipSpaces(); 237 if (little_endian) { 238 uint32_t shift_amount = 0; 239 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 240 // Make sure we don't exceed the size of a uint64_t... 241 if (nibble_count >= (sizeof(uint64_t) * 2)) { 242 m_index = UINT64_MAX; 243 return fail_value; 244 } 245 246 uint8_t nibble_lo; 247 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]); 248 ++m_index; 249 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 250 nibble_lo = xdigit_to_sint(m_packet[m_index]); 251 ++m_index; 252 result |= ((uint64_t)nibble_hi << (shift_amount + 4)); 253 result |= ((uint64_t)nibble_lo << shift_amount); 254 nibble_count += 2; 255 shift_amount += 8; 256 } else { 257 result |= ((uint64_t)nibble_hi << shift_amount); 258 nibble_count += 1; 259 shift_amount += 4; 260 } 261 } 262 } else { 263 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 264 // Make sure we don't exceed the size of a uint64_t... 265 if (nibble_count >= (sizeof(uint64_t) * 2)) { 266 m_index = UINT64_MAX; 267 return fail_value; 268 } 269 270 uint8_t nibble = xdigit_to_sint(m_packet[m_index]); 271 // Big Endian 272 result <<= 4; 273 result |= nibble; 274 275 ++m_index; 276 ++nibble_count; 277 } 278 } 279 return result; 280 } 281 282 bool StringExtractor::ConsumeFront(const llvm::StringRef &str) { 283 llvm::StringRef S = GetStringRef(); 284 if (!S.startswith(str)) 285 return false; 286 else 287 m_index += str.size(); 288 return true; 289 } 290 291 size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest, 292 uint8_t fail_fill_value) { 293 size_t bytes_extracted = 0; 294 while (!dest.empty() && GetBytesLeft() > 0) { 295 dest[0] = GetHexU8(fail_fill_value); 296 if (!IsGood()) 297 break; 298 ++bytes_extracted; 299 dest = dest.drop_front(); 300 } 301 302 if (!dest.empty()) 303 ::memset(dest.data(), fail_fill_value, dest.size()); 304 305 return bytes_extracted; 306 } 307 308 //---------------------------------------------------------------------- 309 // Decodes all valid hex encoded bytes at the head of the StringExtractor, 310 // limited by dst_len. 311 // 312 // Returns the number of bytes successfully decoded 313 //---------------------------------------------------------------------- 314 size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) { 315 size_t bytes_extracted = 0; 316 while (!dest.empty()) { 317 int decode = DecodeHexU8(); 318 if (decode == -1) 319 break; 320 dest[0] = (uint8_t)decode; 321 dest = dest.drop_front(); 322 ++bytes_extracted; 323 } 324 return bytes_extracted; 325 } 326 327 // Consume ASCII hex nibble character pairs until we have decoded byte_size 328 // bytes of data. 329 330 uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size, 331 bool little_endian, 332 uint64_t fail_value) { 333 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) { 334 uint64_t result = 0; 335 uint32_t i; 336 if (little_endian) { 337 // Little Endian 338 uint32_t shift_amount; 339 for (i = 0, shift_amount = 0; i < byte_size && IsGood(); 340 ++i, shift_amount += 8) { 341 result |= ((uint64_t)GetHexU8() << shift_amount); 342 } 343 } else { 344 // Big Endian 345 for (i = 0; i < byte_size && IsGood(); ++i) { 346 result <<= 8; 347 result |= GetHexU8(); 348 } 349 } 350 } 351 m_index = UINT64_MAX; 352 return fail_value; 353 } 354 355 size_t StringExtractor::GetHexByteString(std::string &str) { 356 str.clear(); 357 str.reserve(GetBytesLeft() / 2); 358 char ch; 359 while ((ch = GetHexU8()) != '\0') 360 str.append(1, ch); 361 return str.size(); 362 } 363 364 size_t StringExtractor::GetHexByteStringFixedLength(std::string &str, 365 uint32_t nibble_length) { 366 str.clear(); 367 368 uint32_t nibble_count = 0; 369 for (const char *pch = Peek(); 370 (nibble_count < nibble_length) && (pch != nullptr); 371 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) { 372 } 373 374 return str.size(); 375 } 376 377 size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str, 378 char terminator) { 379 str.clear(); 380 char ch; 381 while ((ch = GetHexU8(0, false)) != '\0') 382 str.append(1, ch); 383 if (Peek() && *Peek() == terminator) 384 return str.size(); 385 386 str.clear(); 387 return str.size(); 388 } 389 390 bool StringExtractor::GetNameColonValue(llvm::StringRef &name, 391 llvm::StringRef &value) { 392 // Read something in the form of NNNN:VVVV; where NNNN is any character that 393 // is not a colon, followed by a ':' character, then a value (one or more ';' 394 // chars), followed by a ';' 395 if (m_index >= m_packet.size()) 396 return fail(); 397 398 llvm::StringRef view(m_packet); 399 if (view.empty()) 400 return fail(); 401 402 llvm::StringRef a, b, c, d; 403 view = view.substr(m_index); 404 std::tie(a, b) = view.split(':'); 405 if (a.empty() || b.empty()) 406 return fail(); 407 std::tie(c, d) = b.split(';'); 408 if (b == c && d.empty()) 409 return fail(); 410 411 name = a; 412 value = c; 413 if (d.empty()) 414 m_index = m_packet.size(); 415 else { 416 size_t bytes_consumed = d.data() - view.data(); 417 m_index += bytes_consumed; 418 } 419 return true; 420 } 421 422 void StringExtractor::SkipSpaces() { 423 const size_t n = m_packet.size(); 424 while (m_index < n && isspace(m_packet[m_index])) 425 ++m_index; 426 } 427