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