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