130fdc8d8SChris Lattner //===-- StringExtractor.cpp -------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 10f805e190SPavel Labath #include "lldb/Utility/StringExtractor.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1378709173SStephen Wilson #include <stdlib.h> 1478709173SStephen Wilson 1530fdc8d8SChris Lattner // C++ Includes 1654695a33SZachary Turner #include <tuple> 1730fdc8d8SChris Lattner // Other libraries and framework includes 1830fdc8d8SChris Lattner // Project includes 1930fdc8d8SChris Lattner 20*b9c1b51eSKate Stone static inline int xdigit_to_sint(char ch) { 2130fdc8d8SChris Lattner if (ch >= 'a' && ch <= 'f') 2230fdc8d8SChris Lattner return 10 + ch - 'a'; 231e89cd80SBenjamin Kramer if (ch >= 'A' && ch <= 'F') 241e89cd80SBenjamin Kramer return 10 + ch - 'A'; 256eddf8dfSVince Harron if (ch >= '0' && ch <= '9') 2630fdc8d8SChris Lattner return ch - '0'; 276eddf8dfSVince Harron return -1; 2830fdc8d8SChris Lattner } 2930fdc8d8SChris Lattner 3030fdc8d8SChris Lattner //---------------------------------------------------------------------- 3130fdc8d8SChris Lattner // StringExtractor constructor 3230fdc8d8SChris Lattner //---------------------------------------------------------------------- 33*b9c1b51eSKate Stone StringExtractor::StringExtractor() : m_packet(), m_index(0) {} 3430fdc8d8SChris Lattner 35*b9c1b51eSKate Stone StringExtractor::StringExtractor(llvm::StringRef packet_str) 36*b9c1b51eSKate Stone : m_packet(), m_index(0) { 3754695a33SZachary Turner m_packet.assign(packet_str.begin(), packet_str.end()); 3854695a33SZachary Turner } 3930fdc8d8SChris Lattner 40*b9c1b51eSKate Stone StringExtractor::StringExtractor(const char *packet_cstr) 41*b9c1b51eSKate Stone : m_packet(), m_index(0) { 4230fdc8d8SChris Lattner if (packet_cstr) 4330fdc8d8SChris Lattner m_packet.assign(packet_cstr); 4430fdc8d8SChris Lattner } 4530fdc8d8SChris Lattner 4630fdc8d8SChris Lattner //---------------------------------------------------------------------- 4730fdc8d8SChris Lattner // StringExtractor copy constructor 4830fdc8d8SChris Lattner //---------------------------------------------------------------------- 49*b9c1b51eSKate Stone StringExtractor::StringExtractor(const StringExtractor &rhs) 50*b9c1b51eSKate Stone : m_packet(rhs.m_packet), m_index(rhs.m_index) {} 5130fdc8d8SChris Lattner 5230fdc8d8SChris Lattner //---------------------------------------------------------------------- 5330fdc8d8SChris Lattner // StringExtractor assignment operator 5430fdc8d8SChris Lattner //---------------------------------------------------------------------- 55*b9c1b51eSKate Stone const StringExtractor &StringExtractor::operator=(const StringExtractor &rhs) { 56*b9c1b51eSKate Stone if (this != &rhs) { 5730fdc8d8SChris Lattner m_packet = rhs.m_packet; 5830fdc8d8SChris Lattner m_index = rhs.m_index; 5930fdc8d8SChris Lattner } 6030fdc8d8SChris Lattner return *this; 6130fdc8d8SChris Lattner } 6230fdc8d8SChris Lattner 6330fdc8d8SChris Lattner //---------------------------------------------------------------------- 6430fdc8d8SChris Lattner // Destructor 6530fdc8d8SChris Lattner //---------------------------------------------------------------------- 66*b9c1b51eSKate Stone StringExtractor::~StringExtractor() {} 6730fdc8d8SChris Lattner 68*b9c1b51eSKate Stone char StringExtractor::GetChar(char fail_value) { 69*b9c1b51eSKate Stone if (m_index < m_packet.size()) { 7030fdc8d8SChris Lattner char ch = m_packet[m_index]; 7130fdc8d8SChris Lattner ++m_index; 7230fdc8d8SChris Lattner return ch; 7330fdc8d8SChris Lattner } 74c7bece56SGreg Clayton m_index = UINT64_MAX; 7530fdc8d8SChris Lattner return fail_value; 7630fdc8d8SChris Lattner } 7730fdc8d8SChris Lattner 7830fdc8d8SChris Lattner //---------------------------------------------------------------------- 796eddf8dfSVince Harron // If a pair of valid hex digits exist at the head of the 806eddf8dfSVince Harron // StringExtractor they are decoded into an unsigned byte and returned 816eddf8dfSVince Harron // by this function 826eddf8dfSVince Harron // 836eddf8dfSVince Harron // If there is not a pair of valid hex digits at the head of the 846eddf8dfSVince Harron // StringExtractor, it is left unchanged and -1 is returned 856eddf8dfSVince Harron //---------------------------------------------------------------------- 86*b9c1b51eSKate Stone int StringExtractor::DecodeHexU8() { 8715a2165dSFrancis Ricci SkipSpaces(); 88*b9c1b51eSKate Stone if (GetBytesLeft() < 2) { 896eddf8dfSVince Harron return -1; 90b9739d40SPavel Labath } 91b9739d40SPavel Labath const int hi_nibble = xdigit_to_sint(m_packet[m_index]); 92b9739d40SPavel Labath const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]); 93*b9c1b51eSKate Stone if (hi_nibble == -1 || lo_nibble == -1) { 946eddf8dfSVince Harron return -1; 95b9739d40SPavel Labath } 966eddf8dfSVince Harron m_index += 2; 97b9739d40SPavel Labath return (uint8_t)((hi_nibble << 4) + lo_nibble); 986eddf8dfSVince Harron } 996eddf8dfSVince Harron 1006eddf8dfSVince Harron //---------------------------------------------------------------------- 10130fdc8d8SChris Lattner // Extract an unsigned character from two hex ASCII chars in the packet 1025e8115b3SDawn Perchik // string, or return fail_value on failure 10330fdc8d8SChris Lattner //---------------------------------------------------------------------- 104*b9c1b51eSKate Stone uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) { 1055e8115b3SDawn Perchik // On success, fail_value will be overwritten with the next 1065e8115b3SDawn Perchik // character in the stream 107554a8571SDawn Perchik GetHexU8Ex(fail_value, set_eof_on_fail); 108554a8571SDawn Perchik return fail_value; 109554a8571SDawn Perchik } 110554a8571SDawn Perchik 111*b9c1b51eSKate Stone bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) { 1126eddf8dfSVince Harron int byte = DecodeHexU8(); 113*b9c1b51eSKate Stone if (byte == -1) { 1147b70be39SGreg Clayton if (set_eof_on_fail || m_index >= m_packet.size()) 115c7bece56SGreg Clayton m_index = UINT64_MAX; 116554a8571SDawn Perchik // ch should not be changed in case of failure 117554a8571SDawn Perchik return false; 11830fdc8d8SChris Lattner } 119554a8571SDawn Perchik ch = (uint8_t)byte; 120554a8571SDawn Perchik return true; 1216eddf8dfSVince Harron } 12230fdc8d8SChris Lattner 123*b9c1b51eSKate Stone uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) { 124*b9c1b51eSKate Stone if (m_index < m_packet.size()) { 125d4612ad0SEd Maste char *end = nullptr; 12632e0a750SGreg Clayton const char *start = m_packet.c_str(); 127e0f8f574SDaniel Malea const char *cstr = start + m_index; 128f2d44ca8SEnrico Granata uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base)); 12932e0a750SGreg Clayton 130*b9c1b51eSKate Stone if (end && end != cstr) { 131e0f8f574SDaniel Malea m_index = end - start; 132e0f8f574SDaniel Malea return result; 133e0f8f574SDaniel Malea } 134e0f8f574SDaniel Malea } 135e0f8f574SDaniel Malea return fail_value; 136e0f8f574SDaniel Malea } 137e0f8f574SDaniel Malea 138*b9c1b51eSKate Stone int32_t StringExtractor::GetS32(int32_t fail_value, int base) { 139*b9c1b51eSKate Stone if (m_index < m_packet.size()) { 140d4612ad0SEd Maste char *end = nullptr; 141e0f8f574SDaniel Malea const char *start = m_packet.c_str(); 142e0f8f574SDaniel Malea const char *cstr = start + m_index; 143f2d44ca8SEnrico Granata int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base)); 144e0f8f574SDaniel Malea 145*b9c1b51eSKate Stone if (end && end != cstr) { 146e0f8f574SDaniel Malea m_index = end - start; 147e0f8f574SDaniel Malea return result; 148e0f8f574SDaniel Malea } 149e0f8f574SDaniel Malea } 150e0f8f574SDaniel Malea return fail_value; 151e0f8f574SDaniel Malea } 152e0f8f574SDaniel Malea 153*b9c1b51eSKate Stone uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) { 154*b9c1b51eSKate Stone if (m_index < m_packet.size()) { 155d4612ad0SEd Maste char *end = nullptr; 156e0f8f574SDaniel Malea const char *start = m_packet.c_str(); 157e0f8f574SDaniel Malea const char *cstr = start + m_index; 158e0f8f574SDaniel Malea uint64_t result = ::strtoull(cstr, &end, base); 159e0f8f574SDaniel Malea 160*b9c1b51eSKate Stone if (end && end != cstr) { 161e0f8f574SDaniel Malea m_index = end - start; 162e0f8f574SDaniel Malea return result; 163e0f8f574SDaniel Malea } 164e0f8f574SDaniel Malea } 165e0f8f574SDaniel Malea return fail_value; 166e0f8f574SDaniel Malea } 167e0f8f574SDaniel Malea 168*b9c1b51eSKate Stone int64_t StringExtractor::GetS64(int64_t fail_value, int base) { 169*b9c1b51eSKate Stone if (m_index < m_packet.size()) { 170d4612ad0SEd Maste char *end = nullptr; 171e0f8f574SDaniel Malea const char *start = m_packet.c_str(); 172e0f8f574SDaniel Malea const char *cstr = start + m_index; 173e0f8f574SDaniel Malea int64_t result = ::strtoll(cstr, &end, base); 174e0f8f574SDaniel Malea 175*b9c1b51eSKate Stone if (end && end != cstr) { 17632e0a750SGreg Clayton m_index = end - start; 17732e0a750SGreg Clayton return result; 17832e0a750SGreg Clayton } 17932e0a750SGreg Clayton } 18032e0a750SGreg Clayton return fail_value; 18132e0a750SGreg Clayton } 18232e0a750SGreg Clayton 183*b9c1b51eSKate Stone uint32_t StringExtractor::GetHexMaxU32(bool little_endian, 184*b9c1b51eSKate Stone uint32_t fail_value) { 185b9739d40SPavel Labath uint32_t result = 0; 186b9739d40SPavel Labath uint32_t nibble_count = 0; 187b9739d40SPavel Labath 18815a2165dSFrancis Ricci SkipSpaces(); 189*b9c1b51eSKate Stone if (little_endian) { 190b9739d40SPavel Labath uint32_t shift_amount = 0; 191*b9c1b51eSKate Stone while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 192b9739d40SPavel Labath // Make sure we don't exceed the size of a uint32_t... 193*b9c1b51eSKate Stone if (nibble_count >= (sizeof(uint32_t) * 2)) { 194b9739d40SPavel Labath m_index = UINT64_MAX; 195b9739d40SPavel Labath return fail_value; 196b9739d40SPavel Labath } 197b9739d40SPavel Labath 198b9739d40SPavel Labath uint8_t nibble_lo; 199b9739d40SPavel Labath uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]); 200b9739d40SPavel Labath ++m_index; 201*b9c1b51eSKate Stone if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 202b9739d40SPavel Labath nibble_lo = xdigit_to_sint(m_packet[m_index]); 203b9739d40SPavel Labath ++m_index; 204b9739d40SPavel Labath result |= ((uint32_t)nibble_hi << (shift_amount + 4)); 205b9739d40SPavel Labath result |= ((uint32_t)nibble_lo << shift_amount); 206b9739d40SPavel Labath nibble_count += 2; 207b9739d40SPavel Labath shift_amount += 8; 208*b9c1b51eSKate Stone } else { 209b9739d40SPavel Labath result |= ((uint32_t)nibble_hi << shift_amount); 210b9739d40SPavel Labath nibble_count += 1; 211b9739d40SPavel Labath shift_amount += 4; 21230fdc8d8SChris Lattner } 213b9739d40SPavel Labath } 214*b9c1b51eSKate Stone } else { 215*b9c1b51eSKate Stone while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 216b9739d40SPavel Labath // Make sure we don't exceed the size of a uint32_t... 217*b9c1b51eSKate Stone if (nibble_count >= (sizeof(uint32_t) * 2)) { 218b9739d40SPavel Labath m_index = UINT64_MAX; 219b9739d40SPavel Labath return fail_value; 220b9739d40SPavel Labath } 221b9739d40SPavel Labath 222b9739d40SPavel Labath uint8_t nibble = xdigit_to_sint(m_packet[m_index]); 223b9739d40SPavel Labath // Big Endian 224b9739d40SPavel Labath result <<= 4; 225b9739d40SPavel Labath result |= nibble; 226b9739d40SPavel Labath 227b9739d40SPavel Labath ++m_index; 228b9739d40SPavel Labath ++nibble_count; 229b9739d40SPavel Labath } 230b9739d40SPavel Labath } 231b9739d40SPavel Labath return result; 23230fdc8d8SChris Lattner } 23330fdc8d8SChris Lattner 234*b9c1b51eSKate Stone uint64_t StringExtractor::GetHexMaxU64(bool little_endian, 235*b9c1b51eSKate Stone uint64_t fail_value) { 236b9739d40SPavel Labath uint64_t result = 0; 237b9739d40SPavel Labath uint32_t nibble_count = 0; 238b9739d40SPavel Labath 23915a2165dSFrancis Ricci SkipSpaces(); 240*b9c1b51eSKate Stone if (little_endian) { 241b9739d40SPavel Labath uint32_t shift_amount = 0; 242*b9c1b51eSKate Stone while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 243b9739d40SPavel Labath // Make sure we don't exceed the size of a uint64_t... 244*b9c1b51eSKate Stone if (nibble_count >= (sizeof(uint64_t) * 2)) { 245b9739d40SPavel Labath m_index = UINT64_MAX; 246b9739d40SPavel Labath return fail_value; 247b9739d40SPavel Labath } 248b9739d40SPavel Labath 249b9739d40SPavel Labath uint8_t nibble_lo; 250b9739d40SPavel Labath uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]); 251b9739d40SPavel Labath ++m_index; 252*b9c1b51eSKate Stone if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 253b9739d40SPavel Labath nibble_lo = xdigit_to_sint(m_packet[m_index]); 254b9739d40SPavel Labath ++m_index; 255b9739d40SPavel Labath result |= ((uint64_t)nibble_hi << (shift_amount + 4)); 256b9739d40SPavel Labath result |= ((uint64_t)nibble_lo << shift_amount); 257b9739d40SPavel Labath nibble_count += 2; 258b9739d40SPavel Labath shift_amount += 8; 259*b9c1b51eSKate Stone } else { 260b9739d40SPavel Labath result |= ((uint64_t)nibble_hi << shift_amount); 261b9739d40SPavel Labath nibble_count += 1; 262b9739d40SPavel Labath shift_amount += 4; 26330fdc8d8SChris Lattner } 264b9739d40SPavel Labath } 265*b9c1b51eSKate Stone } else { 266*b9c1b51eSKate Stone while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 267b9739d40SPavel Labath // Make sure we don't exceed the size of a uint64_t... 268*b9c1b51eSKate Stone if (nibble_count >= (sizeof(uint64_t) * 2)) { 269b9739d40SPavel Labath m_index = UINT64_MAX; 270b9739d40SPavel Labath return fail_value; 271b9739d40SPavel Labath } 272b9739d40SPavel Labath 273b9739d40SPavel Labath uint8_t nibble = xdigit_to_sint(m_packet[m_index]); 274b9739d40SPavel Labath // Big Endian 275b9739d40SPavel Labath result <<= 4; 276b9739d40SPavel Labath result |= nibble; 277b9739d40SPavel Labath 278b9739d40SPavel Labath ++m_index; 279b9739d40SPavel Labath ++nibble_count; 280b9739d40SPavel Labath } 281b9739d40SPavel Labath } 282b9739d40SPavel Labath return result; 28330fdc8d8SChris Lattner } 28430fdc8d8SChris Lattner 285*b9c1b51eSKate Stone size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest, 286*b9c1b51eSKate Stone uint8_t fail_fill_value) { 28730fdc8d8SChris Lattner size_t bytes_extracted = 0; 288*b9c1b51eSKate Stone while (!dest.empty() && GetBytesLeft() > 0) { 289d08f09c1SZachary Turner dest[0] = GetHexU8(fail_fill_value); 290d08f09c1SZachary Turner if (!IsGood()) 29130fdc8d8SChris Lattner break; 292d08f09c1SZachary Turner ++bytes_extracted; 293d08f09c1SZachary Turner dest = dest.drop_front(); 29430fdc8d8SChris Lattner } 29530fdc8d8SChris Lattner 296d08f09c1SZachary Turner if (!dest.empty()) 297d08f09c1SZachary Turner ::memset(dest.data(), fail_fill_value, dest.size()); 29830fdc8d8SChris Lattner 29930fdc8d8SChris Lattner return bytes_extracted; 30030fdc8d8SChris Lattner } 30130fdc8d8SChris Lattner 3026eddf8dfSVince Harron //---------------------------------------------------------------------- 3036eddf8dfSVince Harron // Decodes all valid hex encoded bytes at the head of the 3046eddf8dfSVince Harron // StringExtractor, limited by dst_len. 3056eddf8dfSVince Harron // 3066eddf8dfSVince Harron // Returns the number of bytes successfully decoded 3076eddf8dfSVince Harron //---------------------------------------------------------------------- 308*b9c1b51eSKate Stone size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) { 3096eddf8dfSVince Harron size_t bytes_extracted = 0; 310*b9c1b51eSKate Stone while (!dest.empty()) { 3116eddf8dfSVince Harron int decode = DecodeHexU8(); 3126eddf8dfSVince Harron if (decode == -1) 3136eddf8dfSVince Harron break; 314d08f09c1SZachary Turner dest[0] = (uint8_t)decode; 315d08f09c1SZachary Turner dest = dest.drop_front(); 316d08f09c1SZachary Turner ++bytes_extracted; 3176eddf8dfSVince Harron } 3186eddf8dfSVince Harron return bytes_extracted; 3196eddf8dfSVince Harron } 32030fdc8d8SChris Lattner 321b9739d40SPavel Labath // Consume ASCII hex nibble character pairs until we have decoded byte_size 322b9739d40SPavel Labath // bytes of data. 323b9739d40SPavel Labath 324*b9c1b51eSKate Stone uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size, 325*b9c1b51eSKate Stone bool little_endian, 326*b9c1b51eSKate Stone uint64_t fail_value) { 327*b9c1b51eSKate Stone if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) { 328b9739d40SPavel Labath uint64_t result = 0; 329b9739d40SPavel Labath uint32_t i; 330*b9c1b51eSKate Stone if (little_endian) { 331b9739d40SPavel Labath // Little Endian 332b9739d40SPavel Labath uint32_t shift_amount; 333*b9c1b51eSKate Stone for (i = 0, shift_amount = 0; i < byte_size && IsGood(); 334*b9c1b51eSKate Stone ++i, shift_amount += 8) { 335b9739d40SPavel Labath result |= ((uint64_t)GetHexU8() << shift_amount); 336b9739d40SPavel Labath } 337*b9c1b51eSKate Stone } else { 338b9739d40SPavel Labath // Big Endian 339*b9c1b51eSKate Stone for (i = 0; i < byte_size && IsGood(); ++i) { 340b9739d40SPavel Labath result <<= 8; 341b9739d40SPavel Labath result |= GetHexU8(); 342b9739d40SPavel Labath } 343b9739d40SPavel Labath } 344b9739d40SPavel Labath } 345b9739d40SPavel Labath m_index = UINT64_MAX; 346b9739d40SPavel Labath return fail_value; 347b9739d40SPavel Labath } 348b9739d40SPavel Labath 349*b9c1b51eSKate Stone size_t StringExtractor::GetHexByteString(std::string &str) { 350de9d0494SGreg Clayton str.clear(); 3518c1b6bd7SPavel Labath str.reserve(GetBytesLeft() / 2); 352de9d0494SGreg Clayton char ch; 353de9d0494SGreg Clayton while ((ch = GetHexU8()) != '\0') 354de9d0494SGreg Clayton str.append(1, ch); 355de9d0494SGreg Clayton return str.size(); 356de9d0494SGreg Clayton } 357de9d0494SGreg Clayton 358*b9c1b51eSKate Stone size_t StringExtractor::GetHexByteStringFixedLength(std::string &str, 359*b9c1b51eSKate Stone uint32_t nibble_length) { 360af245d11STodd Fiala str.clear(); 361b9739d40SPavel Labath 362b9739d40SPavel Labath uint32_t nibble_count = 0; 363*b9c1b51eSKate Stone for (const char *pch = Peek(); 364*b9c1b51eSKate Stone (nibble_count < nibble_length) && (pch != nullptr); 365*b9c1b51eSKate Stone str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) { 366*b9c1b51eSKate Stone } 367b9739d40SPavel Labath 368af245d11STodd Fiala return str.size(); 369af245d11STodd Fiala } 370af245d11STodd Fiala 371*b9c1b51eSKate Stone size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str, 372*b9c1b51eSKate Stone char terminator) { 373e0f8f574SDaniel Malea str.clear(); 374e0f8f574SDaniel Malea char ch; 375e0f8f574SDaniel Malea while ((ch = GetHexU8(0, false)) != '\0') 376e0f8f574SDaniel Malea str.append(1, ch); 377b9739d40SPavel Labath if (Peek() && *Peek() == terminator) 378e0f8f574SDaniel Malea return str.size(); 379af245d11STodd Fiala 380e0f8f574SDaniel Malea str.clear(); 381e0f8f574SDaniel Malea return str.size(); 382e0f8f574SDaniel Malea } 383e0f8f574SDaniel Malea 384*b9c1b51eSKate Stone bool StringExtractor::GetNameColonValue(llvm::StringRef &name, 385*b9c1b51eSKate Stone llvm::StringRef &value) { 38630fdc8d8SChris Lattner // Read something in the form of NNNN:VVVV; where NNNN is any character 38730fdc8d8SChris Lattner // that is not a colon, followed by a ':' character, then a value (one or 38830fdc8d8SChris Lattner // more ';' chars), followed by a ';' 38954695a33SZachary Turner if (m_index >= m_packet.size()) 39054695a33SZachary Turner return fail(); 39154695a33SZachary Turner 39254695a33SZachary Turner llvm::StringRef view(m_packet); 39354695a33SZachary Turner if (view.empty()) 39454695a33SZachary Turner return fail(); 39554695a33SZachary Turner 39654695a33SZachary Turner llvm::StringRef a, b, c, d; 39754695a33SZachary Turner view = view.substr(m_index); 39854695a33SZachary Turner std::tie(a, b) = view.split(':'); 39954695a33SZachary Turner if (a.empty() || b.empty()) 40054695a33SZachary Turner return fail(); 40154695a33SZachary Turner std::tie(c, d) = b.split(';'); 40254695a33SZachary Turner if (b == c && d.empty()) 40354695a33SZachary Turner return fail(); 40454695a33SZachary Turner 40554695a33SZachary Turner name = a; 40654695a33SZachary Turner value = c; 40754695a33SZachary Turner if (d.empty()) 40854695a33SZachary Turner m_index = m_packet.size(); 409*b9c1b51eSKate Stone else { 41054695a33SZachary Turner size_t bytes_consumed = d.data() - view.data(); 41154695a33SZachary Turner m_index += bytes_consumed; 41254695a33SZachary Turner } 41330fdc8d8SChris Lattner return true; 41430fdc8d8SChris Lattner } 41598424c44SGreg Clayton 416*b9c1b51eSKate Stone void StringExtractor::SkipSpaces() { 41798424c44SGreg Clayton const size_t n = m_packet.size(); 41898424c44SGreg Clayton while (m_index < n && isspace(m_packet[m_index])) 41998424c44SGreg Clayton ++m_index; 42098424c44SGreg Clayton } 421