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