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