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