130fdc8d8SChris Lattner //===-- StringExtractor.cpp -------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 9f805e190SPavel Labath #include "lldb/Utility/StringExtractor.h" 1030fdc8d8SChris Lattner 1154695a33SZachary Turner #include <tuple> 124479ac15SZachary Turner 13672d2c12SJonas Devlieghere #include <ctype.h> 144479ac15SZachary Turner #include <stdlib.h> 15672d2c12SJonas Devlieghere #include <string.h> 1630fdc8d8SChris Lattner 17b9c1b51eSKate Stone static inline int xdigit_to_sint(char ch) { 1830fdc8d8SChris Lattner if (ch >= 'a' && ch <= 'f') 1930fdc8d8SChris Lattner return 10 + ch - 'a'; 201e89cd80SBenjamin Kramer if (ch >= 'A' && ch <= 'F') 211e89cd80SBenjamin Kramer return 10 + ch - 'A'; 226eddf8dfSVince Harron if (ch >= '0' && ch <= '9') 2330fdc8d8SChris Lattner return ch - '0'; 246eddf8dfSVince Harron return -1; 2530fdc8d8SChris Lattner } 2630fdc8d8SChris Lattner 2730fdc8d8SChris Lattner //---------------------------------------------------------------------- 2830fdc8d8SChris Lattner // StringExtractor constructor 2930fdc8d8SChris Lattner //---------------------------------------------------------------------- 30b9c1b51eSKate Stone StringExtractor::StringExtractor() : m_packet(), m_index(0) {} 3130fdc8d8SChris Lattner 32b9c1b51eSKate Stone StringExtractor::StringExtractor(llvm::StringRef packet_str) 33b9c1b51eSKate Stone : m_packet(), m_index(0) { 3454695a33SZachary Turner m_packet.assign(packet_str.begin(), packet_str.end()); 3554695a33SZachary Turner } 3630fdc8d8SChris Lattner 37b9c1b51eSKate Stone StringExtractor::StringExtractor(const char *packet_cstr) 38b9c1b51eSKate Stone : m_packet(), m_index(0) { 3930fdc8d8SChris Lattner if (packet_cstr) 4030fdc8d8SChris Lattner m_packet.assign(packet_cstr); 4130fdc8d8SChris Lattner } 4230fdc8d8SChris Lattner 4330fdc8d8SChris Lattner //---------------------------------------------------------------------- 4430fdc8d8SChris Lattner // StringExtractor copy constructor 4530fdc8d8SChris Lattner //---------------------------------------------------------------------- 46b9c1b51eSKate Stone StringExtractor::StringExtractor(const StringExtractor &rhs) 47b9c1b51eSKate Stone : m_packet(rhs.m_packet), m_index(rhs.m_index) {} 4830fdc8d8SChris Lattner 4930fdc8d8SChris Lattner //---------------------------------------------------------------------- 5030fdc8d8SChris Lattner // StringExtractor assignment operator 5130fdc8d8SChris Lattner //---------------------------------------------------------------------- 52b9c1b51eSKate Stone const StringExtractor &StringExtractor::operator=(const StringExtractor &rhs) { 53b9c1b51eSKate Stone if (this != &rhs) { 5430fdc8d8SChris Lattner m_packet = rhs.m_packet; 5530fdc8d8SChris Lattner m_index = rhs.m_index; 5630fdc8d8SChris Lattner } 5730fdc8d8SChris Lattner return *this; 5830fdc8d8SChris Lattner } 5930fdc8d8SChris Lattner 6030fdc8d8SChris Lattner //---------------------------------------------------------------------- 6130fdc8d8SChris Lattner // Destructor 6230fdc8d8SChris Lattner //---------------------------------------------------------------------- 63b9c1b51eSKate Stone StringExtractor::~StringExtractor() {} 6430fdc8d8SChris Lattner 65b9c1b51eSKate Stone char StringExtractor::GetChar(char fail_value) { 66b9c1b51eSKate Stone if (m_index < m_packet.size()) { 6730fdc8d8SChris Lattner char ch = m_packet[m_index]; 6830fdc8d8SChris Lattner ++m_index; 6930fdc8d8SChris Lattner return ch; 7030fdc8d8SChris Lattner } 71c7bece56SGreg Clayton m_index = UINT64_MAX; 7230fdc8d8SChris Lattner return fail_value; 7330fdc8d8SChris Lattner } 7430fdc8d8SChris Lattner 7530fdc8d8SChris Lattner //---------------------------------------------------------------------- 7605097246SAdrian Prantl // If a pair of valid hex digits exist at the head of the StringExtractor they 7705097246SAdrian Prantl // are decoded into an unsigned byte and returned by this function 786eddf8dfSVince Harron // 796eddf8dfSVince Harron // If there is not a pair of valid hex digits at the head of the 806eddf8dfSVince Harron // StringExtractor, it is left unchanged and -1 is returned 816eddf8dfSVince Harron //---------------------------------------------------------------------- 82b9c1b51eSKate Stone int StringExtractor::DecodeHexU8() { 8315a2165dSFrancis Ricci SkipSpaces(); 84b9c1b51eSKate Stone if (GetBytesLeft() < 2) { 856eddf8dfSVince Harron return -1; 86b9739d40SPavel Labath } 87b9739d40SPavel Labath const int hi_nibble = xdigit_to_sint(m_packet[m_index]); 88b9739d40SPavel Labath const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]); 89b9c1b51eSKate Stone if (hi_nibble == -1 || lo_nibble == -1) { 906eddf8dfSVince Harron return -1; 91b9739d40SPavel Labath } 926eddf8dfSVince Harron m_index += 2; 93b9739d40SPavel Labath return (uint8_t)((hi_nibble << 4) + lo_nibble); 946eddf8dfSVince Harron } 956eddf8dfSVince Harron 966eddf8dfSVince Harron //---------------------------------------------------------------------- 9705097246SAdrian Prantl // Extract an unsigned character from two hex ASCII chars in the packet string, 9805097246SAdrian Prantl // or return fail_value on failure 9930fdc8d8SChris Lattner //---------------------------------------------------------------------- 100b9c1b51eSKate Stone uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) { 10105097246SAdrian Prantl // On success, fail_value will be overwritten with the next character in the 10205097246SAdrian Prantl // stream 103554a8571SDawn Perchik GetHexU8Ex(fail_value, set_eof_on_fail); 104554a8571SDawn Perchik return fail_value; 105554a8571SDawn Perchik } 106554a8571SDawn Perchik 107b9c1b51eSKate Stone bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) { 1086eddf8dfSVince Harron int byte = DecodeHexU8(); 109b9c1b51eSKate Stone if (byte == -1) { 1107b70be39SGreg Clayton if (set_eof_on_fail || m_index >= m_packet.size()) 111c7bece56SGreg Clayton m_index = UINT64_MAX; 112554a8571SDawn Perchik // ch should not be changed in case of failure 113554a8571SDawn Perchik return false; 11430fdc8d8SChris Lattner } 115554a8571SDawn Perchik ch = (uint8_t)byte; 116554a8571SDawn Perchik return true; 1176eddf8dfSVince Harron } 11830fdc8d8SChris Lattner 119b9c1b51eSKate Stone uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) { 120b9c1b51eSKate Stone if (m_index < m_packet.size()) { 121d4612ad0SEd Maste char *end = nullptr; 12232e0a750SGreg Clayton const char *start = m_packet.c_str(); 123e0f8f574SDaniel Malea const char *cstr = start + m_index; 124f2d44ca8SEnrico Granata uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base)); 12532e0a750SGreg Clayton 126b9c1b51eSKate Stone if (end && end != cstr) { 127e0f8f574SDaniel Malea m_index = end - start; 128e0f8f574SDaniel Malea return result; 129e0f8f574SDaniel Malea } 130e0f8f574SDaniel Malea } 131e0f8f574SDaniel Malea return fail_value; 132e0f8f574SDaniel Malea } 133e0f8f574SDaniel Malea 134b9c1b51eSKate Stone int32_t StringExtractor::GetS32(int32_t fail_value, int base) { 135b9c1b51eSKate Stone if (m_index < m_packet.size()) { 136d4612ad0SEd Maste char *end = nullptr; 137e0f8f574SDaniel Malea const char *start = m_packet.c_str(); 138e0f8f574SDaniel Malea const char *cstr = start + m_index; 139f2d44ca8SEnrico Granata int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base)); 140e0f8f574SDaniel Malea 141b9c1b51eSKate Stone if (end && end != cstr) { 142e0f8f574SDaniel Malea m_index = end - start; 143e0f8f574SDaniel Malea return result; 144e0f8f574SDaniel Malea } 145e0f8f574SDaniel Malea } 146e0f8f574SDaniel Malea return fail_value; 147e0f8f574SDaniel Malea } 148e0f8f574SDaniel Malea 149b9c1b51eSKate Stone uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) { 150b9c1b51eSKate Stone if (m_index < m_packet.size()) { 151d4612ad0SEd Maste char *end = nullptr; 152e0f8f574SDaniel Malea const char *start = m_packet.c_str(); 153e0f8f574SDaniel Malea const char *cstr = start + m_index; 154e0f8f574SDaniel Malea uint64_t result = ::strtoull(cstr, &end, base); 155e0f8f574SDaniel Malea 156b9c1b51eSKate Stone if (end && end != cstr) { 157e0f8f574SDaniel Malea m_index = end - start; 158e0f8f574SDaniel Malea return result; 159e0f8f574SDaniel Malea } 160e0f8f574SDaniel Malea } 161e0f8f574SDaniel Malea return fail_value; 162e0f8f574SDaniel Malea } 163e0f8f574SDaniel Malea 164b9c1b51eSKate Stone int64_t StringExtractor::GetS64(int64_t fail_value, int base) { 165b9c1b51eSKate Stone if (m_index < m_packet.size()) { 166d4612ad0SEd Maste char *end = nullptr; 167e0f8f574SDaniel Malea const char *start = m_packet.c_str(); 168e0f8f574SDaniel Malea const char *cstr = start + m_index; 169e0f8f574SDaniel Malea int64_t result = ::strtoll(cstr, &end, base); 170e0f8f574SDaniel Malea 171b9c1b51eSKate Stone if (end && end != cstr) { 17232e0a750SGreg Clayton m_index = end - start; 17332e0a750SGreg Clayton return result; 17432e0a750SGreg Clayton } 17532e0a750SGreg Clayton } 17632e0a750SGreg Clayton return fail_value; 17732e0a750SGreg Clayton } 17832e0a750SGreg Clayton 179b9c1b51eSKate Stone uint32_t StringExtractor::GetHexMaxU32(bool little_endian, 180b9c1b51eSKate Stone uint32_t fail_value) { 181b9739d40SPavel Labath uint32_t result = 0; 182b9739d40SPavel Labath uint32_t nibble_count = 0; 183b9739d40SPavel Labath 18415a2165dSFrancis Ricci SkipSpaces(); 185b9c1b51eSKate Stone if (little_endian) { 186b9739d40SPavel Labath uint32_t shift_amount = 0; 187b9c1b51eSKate Stone while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 188b9739d40SPavel Labath // Make sure we don't exceed the size of a uint32_t... 189b9c1b51eSKate Stone if (nibble_count >= (sizeof(uint32_t) * 2)) { 190b9739d40SPavel Labath m_index = UINT64_MAX; 191b9739d40SPavel Labath return fail_value; 192b9739d40SPavel Labath } 193b9739d40SPavel Labath 194b9739d40SPavel Labath uint8_t nibble_lo; 195b9739d40SPavel Labath uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]); 196b9739d40SPavel Labath ++m_index; 197b9c1b51eSKate Stone if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 198b9739d40SPavel Labath nibble_lo = xdigit_to_sint(m_packet[m_index]); 199b9739d40SPavel Labath ++m_index; 200b9739d40SPavel Labath result |= ((uint32_t)nibble_hi << (shift_amount + 4)); 201b9739d40SPavel Labath result |= ((uint32_t)nibble_lo << shift_amount); 202b9739d40SPavel Labath nibble_count += 2; 203b9739d40SPavel Labath shift_amount += 8; 204b9c1b51eSKate Stone } else { 205b9739d40SPavel Labath result |= ((uint32_t)nibble_hi << shift_amount); 206b9739d40SPavel Labath nibble_count += 1; 207b9739d40SPavel Labath shift_amount += 4; 20830fdc8d8SChris Lattner } 209b9739d40SPavel Labath } 210b9c1b51eSKate Stone } else { 211b9c1b51eSKate Stone while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 212b9739d40SPavel Labath // Make sure we don't exceed the size of a uint32_t... 213b9c1b51eSKate Stone if (nibble_count >= (sizeof(uint32_t) * 2)) { 214b9739d40SPavel Labath m_index = UINT64_MAX; 215b9739d40SPavel Labath return fail_value; 216b9739d40SPavel Labath } 217b9739d40SPavel Labath 218b9739d40SPavel Labath uint8_t nibble = xdigit_to_sint(m_packet[m_index]); 219b9739d40SPavel Labath // Big Endian 220b9739d40SPavel Labath result <<= 4; 221b9739d40SPavel Labath result |= nibble; 222b9739d40SPavel Labath 223b9739d40SPavel Labath ++m_index; 224b9739d40SPavel Labath ++nibble_count; 225b9739d40SPavel Labath } 226b9739d40SPavel Labath } 227b9739d40SPavel Labath return result; 22830fdc8d8SChris Lattner } 22930fdc8d8SChris Lattner 230b9c1b51eSKate Stone uint64_t StringExtractor::GetHexMaxU64(bool little_endian, 231b9c1b51eSKate Stone uint64_t fail_value) { 232b9739d40SPavel Labath uint64_t result = 0; 233b9739d40SPavel Labath uint32_t nibble_count = 0; 234b9739d40SPavel Labath 23515a2165dSFrancis Ricci SkipSpaces(); 236b9c1b51eSKate Stone if (little_endian) { 237b9739d40SPavel Labath uint32_t shift_amount = 0; 238b9c1b51eSKate Stone while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 239b9739d40SPavel Labath // Make sure we don't exceed the size of a uint64_t... 240b9c1b51eSKate Stone if (nibble_count >= (sizeof(uint64_t) * 2)) { 241b9739d40SPavel Labath m_index = UINT64_MAX; 242b9739d40SPavel Labath return fail_value; 243b9739d40SPavel Labath } 244b9739d40SPavel Labath 245b9739d40SPavel Labath uint8_t nibble_lo; 246b9739d40SPavel Labath uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]); 247b9739d40SPavel Labath ++m_index; 248b9c1b51eSKate Stone if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 249b9739d40SPavel Labath nibble_lo = xdigit_to_sint(m_packet[m_index]); 250b9739d40SPavel Labath ++m_index; 251b9739d40SPavel Labath result |= ((uint64_t)nibble_hi << (shift_amount + 4)); 252b9739d40SPavel Labath result |= ((uint64_t)nibble_lo << shift_amount); 253b9739d40SPavel Labath nibble_count += 2; 254b9739d40SPavel Labath shift_amount += 8; 255b9c1b51eSKate Stone } else { 256b9739d40SPavel Labath result |= ((uint64_t)nibble_hi << shift_amount); 257b9739d40SPavel Labath nibble_count += 1; 258b9739d40SPavel Labath shift_amount += 4; 25930fdc8d8SChris Lattner } 260b9739d40SPavel Labath } 261b9c1b51eSKate Stone } else { 262b9c1b51eSKate Stone while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { 263b9739d40SPavel Labath // Make sure we don't exceed the size of a uint64_t... 264b9c1b51eSKate Stone if (nibble_count >= (sizeof(uint64_t) * 2)) { 265b9739d40SPavel Labath m_index = UINT64_MAX; 266b9739d40SPavel Labath return fail_value; 267b9739d40SPavel Labath } 268b9739d40SPavel Labath 269b9739d40SPavel Labath uint8_t nibble = xdigit_to_sint(m_packet[m_index]); 270b9739d40SPavel Labath // Big Endian 271b9739d40SPavel Labath result <<= 4; 272b9739d40SPavel Labath result |= nibble; 273b9739d40SPavel Labath 274b9739d40SPavel Labath ++m_index; 275b9739d40SPavel Labath ++nibble_count; 276b9739d40SPavel Labath } 277b9739d40SPavel Labath } 278b9739d40SPavel Labath return result; 27930fdc8d8SChris Lattner } 28030fdc8d8SChris Lattner 281e714c4f5SRavitheja Addepally bool StringExtractor::ConsumeFront(const llvm::StringRef &str) { 282e714c4f5SRavitheja Addepally llvm::StringRef S = GetStringRef(); 283e714c4f5SRavitheja Addepally if (!S.startswith(str)) 284e714c4f5SRavitheja Addepally return false; 285e714c4f5SRavitheja Addepally else 286e714c4f5SRavitheja Addepally m_index += str.size(); 287e714c4f5SRavitheja Addepally return true; 288e714c4f5SRavitheja Addepally } 289e714c4f5SRavitheja Addepally 290b9c1b51eSKate Stone size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest, 291b9c1b51eSKate Stone uint8_t fail_fill_value) { 29230fdc8d8SChris Lattner size_t bytes_extracted = 0; 293b9c1b51eSKate Stone while (!dest.empty() && GetBytesLeft() > 0) { 294d08f09c1SZachary Turner dest[0] = GetHexU8(fail_fill_value); 295d08f09c1SZachary Turner if (!IsGood()) 29630fdc8d8SChris Lattner break; 297d08f09c1SZachary Turner ++bytes_extracted; 298d08f09c1SZachary Turner dest = dest.drop_front(); 29930fdc8d8SChris Lattner } 30030fdc8d8SChris Lattner 301d08f09c1SZachary Turner if (!dest.empty()) 302d08f09c1SZachary Turner ::memset(dest.data(), fail_fill_value, dest.size()); 30330fdc8d8SChris Lattner 30430fdc8d8SChris Lattner return bytes_extracted; 30530fdc8d8SChris Lattner } 30630fdc8d8SChris Lattner 3076eddf8dfSVince Harron //---------------------------------------------------------------------- 30805097246SAdrian Prantl // Decodes all valid hex encoded bytes at the head of the StringExtractor, 30905097246SAdrian Prantl // limited by dst_len. 3106eddf8dfSVince Harron // 3116eddf8dfSVince Harron // Returns the number of bytes successfully decoded 3126eddf8dfSVince Harron //---------------------------------------------------------------------- 313b9c1b51eSKate Stone size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) { 3146eddf8dfSVince Harron size_t bytes_extracted = 0; 315b9c1b51eSKate Stone while (!dest.empty()) { 3166eddf8dfSVince Harron int decode = DecodeHexU8(); 3176eddf8dfSVince Harron if (decode == -1) 3186eddf8dfSVince Harron break; 319d08f09c1SZachary Turner dest[0] = (uint8_t)decode; 320d08f09c1SZachary Turner dest = dest.drop_front(); 321d08f09c1SZachary Turner ++bytes_extracted; 3226eddf8dfSVince Harron } 3236eddf8dfSVince Harron return bytes_extracted; 3246eddf8dfSVince Harron } 32530fdc8d8SChris Lattner 326b9739d40SPavel Labath // Consume ASCII hex nibble character pairs until we have decoded byte_size 327b9739d40SPavel Labath // bytes of data. 328b9739d40SPavel Labath 329b9c1b51eSKate Stone uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size, 330b9c1b51eSKate Stone bool little_endian, 331b9c1b51eSKate Stone uint64_t fail_value) { 332b9c1b51eSKate Stone if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) { 333b9739d40SPavel Labath uint64_t result = 0; 334b9739d40SPavel Labath uint32_t i; 335b9c1b51eSKate Stone if (little_endian) { 336b9739d40SPavel Labath // Little Endian 337b9739d40SPavel Labath uint32_t shift_amount; 338b9c1b51eSKate Stone for (i = 0, shift_amount = 0; i < byte_size && IsGood(); 339b9c1b51eSKate Stone ++i, shift_amount += 8) { 340b9739d40SPavel Labath result |= ((uint64_t)GetHexU8() << shift_amount); 341b9739d40SPavel Labath } 342b9c1b51eSKate Stone } else { 343b9739d40SPavel Labath // Big Endian 344b9c1b51eSKate Stone for (i = 0; i < byte_size && IsGood(); ++i) { 345b9739d40SPavel Labath result <<= 8; 346b9739d40SPavel Labath result |= GetHexU8(); 347b9739d40SPavel Labath } 348b9739d40SPavel Labath } 349b9739d40SPavel Labath } 350b9739d40SPavel Labath m_index = UINT64_MAX; 351b9739d40SPavel Labath return fail_value; 352b9739d40SPavel Labath } 353b9739d40SPavel Labath 354b9c1b51eSKate Stone size_t StringExtractor::GetHexByteString(std::string &str) { 355de9d0494SGreg Clayton str.clear(); 3568c1b6bd7SPavel Labath str.reserve(GetBytesLeft() / 2); 357de9d0494SGreg Clayton char ch; 358de9d0494SGreg Clayton while ((ch = GetHexU8()) != '\0') 359de9d0494SGreg Clayton str.append(1, ch); 360de9d0494SGreg Clayton return str.size(); 361de9d0494SGreg Clayton } 362de9d0494SGreg Clayton 363b9c1b51eSKate Stone size_t StringExtractor::GetHexByteStringFixedLength(std::string &str, 364b9c1b51eSKate Stone uint32_t nibble_length) { 365af245d11STodd Fiala str.clear(); 366b9739d40SPavel Labath 367b9739d40SPavel Labath uint32_t nibble_count = 0; 368b9c1b51eSKate Stone for (const char *pch = Peek(); 369b9c1b51eSKate Stone (nibble_count < nibble_length) && (pch != nullptr); 370b9c1b51eSKate Stone str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) { 371b9c1b51eSKate Stone } 372b9739d40SPavel Labath 373af245d11STodd Fiala return str.size(); 374af245d11STodd Fiala } 375af245d11STodd Fiala 376b9c1b51eSKate Stone size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str, 377b9c1b51eSKate Stone char terminator) { 378e0f8f574SDaniel Malea str.clear(); 379e0f8f574SDaniel Malea char ch; 380e0f8f574SDaniel Malea while ((ch = GetHexU8(0, false)) != '\0') 381e0f8f574SDaniel Malea str.append(1, ch); 382b9739d40SPavel Labath if (Peek() && *Peek() == terminator) 383e0f8f574SDaniel Malea return str.size(); 384af245d11STodd Fiala 385e0f8f574SDaniel Malea str.clear(); 386e0f8f574SDaniel Malea return str.size(); 387e0f8f574SDaniel Malea } 388e0f8f574SDaniel Malea 389b9c1b51eSKate Stone bool StringExtractor::GetNameColonValue(llvm::StringRef &name, 390b9c1b51eSKate Stone llvm::StringRef &value) { 39105097246SAdrian Prantl // Read something in the form of NNNN:VVVV; where NNNN is any character that 39205097246SAdrian Prantl // is not a colon, followed by a ':' character, then a value (one or more ';' 39305097246SAdrian Prantl // chars), followed by a ';' 39454695a33SZachary Turner if (m_index >= m_packet.size()) 39554695a33SZachary Turner return fail(); 39654695a33SZachary Turner 39754695a33SZachary Turner llvm::StringRef view(m_packet); 39854695a33SZachary Turner if (view.empty()) 39954695a33SZachary Turner return fail(); 40054695a33SZachary Turner 40154695a33SZachary Turner llvm::StringRef a, b, c, d; 40254695a33SZachary Turner view = view.substr(m_index); 40354695a33SZachary Turner std::tie(a, b) = view.split(':'); 40454695a33SZachary Turner if (a.empty() || b.empty()) 40554695a33SZachary Turner return fail(); 40654695a33SZachary Turner std::tie(c, d) = b.split(';'); 40754695a33SZachary Turner if (b == c && d.empty()) 40854695a33SZachary Turner return fail(); 40954695a33SZachary Turner 41054695a33SZachary Turner name = a; 41154695a33SZachary Turner value = c; 41254695a33SZachary Turner if (d.empty()) 41354695a33SZachary Turner m_index = m_packet.size(); 414b9c1b51eSKate Stone else { 41554695a33SZachary Turner size_t bytes_consumed = d.data() - view.data(); 41654695a33SZachary Turner m_index += bytes_consumed; 41754695a33SZachary Turner } 41830fdc8d8SChris Lattner return true; 41930fdc8d8SChris Lattner } 42098424c44SGreg Clayton 421b9c1b51eSKate Stone void StringExtractor::SkipSpaces() { 42298424c44SGreg Clayton const size_t n = m_packet.size(); 42398424c44SGreg Clayton while (m_index < n && isspace(m_packet[m_index])) 42498424c44SGreg Clayton ++m_index; 42598424c44SGreg Clayton } 426