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