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 *uint_cstr = start + m_index; 172 uint32_t result = ::strtoul (uint_cstr, &end, base); 173 174 if (end && end != uint_cstr) 175 { 176 m_index = end - start; 177 return result; 178 } 179 } 180 return fail_value; 181 } 182 183 184 uint32_t 185 StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value) 186 { 187 uint32_t result = 0; 188 uint32_t nibble_count = 0; 189 190 if (little_endian) 191 { 192 uint32_t shift_amount = 0; 193 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 194 { 195 // Make sure we don't exceed the size of a uint32_t... 196 if (nibble_count >= (sizeof(uint32_t) * 2)) 197 { 198 m_index = UINT64_MAX; 199 return fail_value; 200 } 201 202 uint8_t nibble_lo; 203 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]); 204 ++m_index; 205 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 206 { 207 nibble_lo = xdigit_to_sint (m_packet[m_index]); 208 ++m_index; 209 result |= ((uint32_t)nibble_hi << (shift_amount + 4)); 210 result |= ((uint32_t)nibble_lo << shift_amount); 211 nibble_count += 2; 212 shift_amount += 8; 213 } 214 else 215 { 216 result |= ((uint32_t)nibble_hi << shift_amount); 217 nibble_count += 1; 218 shift_amount += 4; 219 } 220 221 } 222 } 223 else 224 { 225 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 226 { 227 // Make sure we don't exceed the size of a uint32_t... 228 if (nibble_count >= (sizeof(uint32_t) * 2)) 229 { 230 m_index = UINT64_MAX; 231 return fail_value; 232 } 233 234 uint8_t nibble = xdigit_to_sint (m_packet[m_index]); 235 // Big Endian 236 result <<= 4; 237 result |= nibble; 238 239 ++m_index; 240 ++nibble_count; 241 } 242 } 243 return result; 244 } 245 246 uint64_t 247 StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value) 248 { 249 uint64_t result = 0; 250 uint32_t nibble_count = 0; 251 252 if (little_endian) 253 { 254 uint32_t shift_amount = 0; 255 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 256 { 257 // Make sure we don't exceed the size of a uint64_t... 258 if (nibble_count >= (sizeof(uint64_t) * 2)) 259 { 260 m_index = UINT64_MAX; 261 return fail_value; 262 } 263 264 uint8_t nibble_lo; 265 uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]); 266 ++m_index; 267 if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 268 { 269 nibble_lo = xdigit_to_sint (m_packet[m_index]); 270 ++m_index; 271 result |= ((uint64_t)nibble_hi << (shift_amount + 4)); 272 result |= ((uint64_t)nibble_lo << shift_amount); 273 nibble_count += 2; 274 shift_amount += 8; 275 } 276 else 277 { 278 result |= ((uint64_t)nibble_hi << shift_amount); 279 nibble_count += 1; 280 shift_amount += 4; 281 } 282 283 } 284 } 285 else 286 { 287 while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) 288 { 289 // Make sure we don't exceed the size of a uint64_t... 290 if (nibble_count >= (sizeof(uint64_t) * 2)) 291 { 292 m_index = UINT64_MAX; 293 return fail_value; 294 } 295 296 uint8_t nibble = xdigit_to_sint (m_packet[m_index]); 297 // Big Endian 298 result <<= 4; 299 result |= nibble; 300 301 ++m_index; 302 ++nibble_count; 303 } 304 } 305 return result; 306 } 307 308 size_t 309 StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value) 310 { 311 uint8_t *dst = (uint8_t*)dst_void; 312 size_t bytes_extracted = 0; 313 while (bytes_extracted < dst_len && GetBytesLeft ()) 314 { 315 dst[bytes_extracted] = GetHexU8 (fail_fill_value); 316 if (IsGood()) 317 ++bytes_extracted; 318 else 319 break; 320 } 321 322 for (size_t i = bytes_extracted; i < dst_len; ++i) 323 dst[i] = fail_fill_value; 324 325 return bytes_extracted; 326 } 327 328 329 // Consume ASCII hex nibble character pairs until we have decoded byte_size 330 // bytes of data. 331 332 uint64_t 333 StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value) 334 { 335 if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) 336 { 337 uint64_t result = 0; 338 uint32_t i; 339 if (little_endian) 340 { 341 // Little Endian 342 uint32_t shift_amount; 343 for (i = 0, shift_amount = 0; 344 i < byte_size && IsGood(); 345 ++i, shift_amount += 8) 346 { 347 result |= ((uint64_t)GetHexU8() << shift_amount); 348 } 349 } 350 else 351 { 352 // Big Endian 353 for (i = 0; i < byte_size && IsGood(); ++i) 354 { 355 result <<= 8; 356 result |= GetHexU8(); 357 } 358 } 359 } 360 m_index = UINT64_MAX; 361 return fail_value; 362 } 363 364 size_t 365 StringExtractor::GetHexByteString (std::string &str) 366 { 367 str.clear(); 368 char ch; 369 while ((ch = GetHexU8()) != '\0') 370 str.append(1, ch); 371 return str.size(); 372 } 373 374 bool 375 StringExtractor::GetNameColonValue (std::string &name, std::string &value) 376 { 377 // Read something in the form of NNNN:VVVV; where NNNN is any character 378 // that is not a colon, followed by a ':' character, then a value (one or 379 // more ';' chars), followed by a ';' 380 if (m_index < m_packet.size()) 381 { 382 const size_t colon_idx = m_packet.find (':', m_index); 383 if (colon_idx != std::string::npos) 384 { 385 const size_t semicolon_idx = m_packet.find (';', colon_idx); 386 if (semicolon_idx != std::string::npos) 387 { 388 name.assign (m_packet, m_index, colon_idx - m_index); 389 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1)); 390 m_index = semicolon_idx + 1; 391 return true; 392 } 393 } 394 } 395 m_index = UINT64_MAX; 396 return false; 397 } 398