1ac7ddfbfSEd Maste //===-- StringExtractor.cpp -------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
10b91a7dfcSDimitry Andric #include "lldb/Utility/StringExtractor.h"
11ac7ddfbfSEd Maste
12435933ddSDimitry Andric #include <tuple>
13f678e45dSDimitry Andric
14*b5893f02SDimitry Andric #include <ctype.h>
15f678e45dSDimitry Andric #include <stdlib.h>
16*b5893f02SDimitry Andric #include <string.h>
17ac7ddfbfSEd Maste
xdigit_to_sint(char ch)18435933ddSDimitry Andric static inline int xdigit_to_sint(char ch) {
19ac7ddfbfSEd Maste if (ch >= 'a' && ch <= 'f')
20ac7ddfbfSEd Maste return 10 + ch - 'a';
21ac7ddfbfSEd Maste if (ch >= 'A' && ch <= 'F')
22ac7ddfbfSEd Maste return 10 + ch - 'A';
237aa51b79SEd Maste if (ch >= '0' && ch <= '9')
24ac7ddfbfSEd Maste return ch - '0';
257aa51b79SEd Maste return -1;
26ac7ddfbfSEd Maste }
27ac7ddfbfSEd Maste
28ac7ddfbfSEd Maste //----------------------------------------------------------------------
29ac7ddfbfSEd Maste // StringExtractor constructor
30ac7ddfbfSEd Maste //----------------------------------------------------------------------
StringExtractor()31435933ddSDimitry Andric StringExtractor::StringExtractor() : m_packet(), m_index(0) {}
32435933ddSDimitry Andric
StringExtractor(llvm::StringRef packet_str)33435933ddSDimitry Andric StringExtractor::StringExtractor(llvm::StringRef packet_str)
34435933ddSDimitry Andric : m_packet(), m_index(0) {
35435933ddSDimitry Andric m_packet.assign(packet_str.begin(), packet_str.end());
36ac7ddfbfSEd Maste }
37ac7ddfbfSEd Maste
StringExtractor(const char * packet_cstr)38435933ddSDimitry Andric StringExtractor::StringExtractor(const char *packet_cstr)
39435933ddSDimitry Andric : m_packet(), m_index(0) {
40ac7ddfbfSEd Maste if (packet_cstr)
41ac7ddfbfSEd Maste m_packet.assign(packet_cstr);
42ac7ddfbfSEd Maste }
43ac7ddfbfSEd Maste
44ac7ddfbfSEd Maste //----------------------------------------------------------------------
45ac7ddfbfSEd Maste // StringExtractor copy constructor
46ac7ddfbfSEd Maste //----------------------------------------------------------------------
StringExtractor(const StringExtractor & rhs)47435933ddSDimitry Andric StringExtractor::StringExtractor(const StringExtractor &rhs)
48435933ddSDimitry Andric : m_packet(rhs.m_packet), m_index(rhs.m_index) {}
49ac7ddfbfSEd Maste
50ac7ddfbfSEd Maste //----------------------------------------------------------------------
51ac7ddfbfSEd Maste // StringExtractor assignment operator
52ac7ddfbfSEd Maste //----------------------------------------------------------------------
operator =(const StringExtractor & rhs)53435933ddSDimitry Andric const StringExtractor &StringExtractor::operator=(const StringExtractor &rhs) {
54435933ddSDimitry Andric if (this != &rhs) {
55ac7ddfbfSEd Maste m_packet = rhs.m_packet;
56ac7ddfbfSEd Maste m_index = rhs.m_index;
57ac7ddfbfSEd Maste }
58ac7ddfbfSEd Maste return *this;
59ac7ddfbfSEd Maste }
60ac7ddfbfSEd Maste
61ac7ddfbfSEd Maste //----------------------------------------------------------------------
62ac7ddfbfSEd Maste // Destructor
63ac7ddfbfSEd Maste //----------------------------------------------------------------------
~StringExtractor()64435933ddSDimitry Andric StringExtractor::~StringExtractor() {}
65ac7ddfbfSEd Maste
GetChar(char fail_value)66435933ddSDimitry Andric char StringExtractor::GetChar(char fail_value) {
67435933ddSDimitry Andric if (m_index < m_packet.size()) {
68ac7ddfbfSEd Maste char ch = m_packet[m_index];
69ac7ddfbfSEd Maste ++m_index;
70ac7ddfbfSEd Maste return ch;
71ac7ddfbfSEd Maste }
72ac7ddfbfSEd Maste m_index = UINT64_MAX;
73ac7ddfbfSEd Maste return fail_value;
74ac7ddfbfSEd Maste }
75ac7ddfbfSEd Maste
76ac7ddfbfSEd Maste //----------------------------------------------------------------------
774ba319b5SDimitry Andric // If a pair of valid hex digits exist at the head of the StringExtractor they
784ba319b5SDimitry Andric // are decoded into an unsigned byte and returned by this function
797aa51b79SEd Maste //
807aa51b79SEd Maste // If there is not a pair of valid hex digits at the head of the
817aa51b79SEd Maste // StringExtractor, it is left unchanged and -1 is returned
827aa51b79SEd Maste //----------------------------------------------------------------------
DecodeHexU8()83435933ddSDimitry Andric int StringExtractor::DecodeHexU8() {
844bb0738eSEd Maste SkipSpaces();
85435933ddSDimitry Andric if (GetBytesLeft() < 2) {
867aa51b79SEd Maste return -1;
877aa51b79SEd Maste }
887aa51b79SEd Maste const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
897aa51b79SEd Maste const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
90435933ddSDimitry Andric if (hi_nibble == -1 || lo_nibble == -1) {
917aa51b79SEd Maste return -1;
927aa51b79SEd Maste }
937aa51b79SEd Maste m_index += 2;
947aa51b79SEd Maste return (uint8_t)((hi_nibble << 4) + lo_nibble);
957aa51b79SEd Maste }
967aa51b79SEd Maste
977aa51b79SEd Maste //----------------------------------------------------------------------
984ba319b5SDimitry Andric // Extract an unsigned character from two hex ASCII chars in the packet string,
994ba319b5SDimitry Andric // or return fail_value on failure
100ac7ddfbfSEd Maste //----------------------------------------------------------------------
GetHexU8(uint8_t fail_value,bool set_eof_on_fail)101435933ddSDimitry Andric uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
1024ba319b5SDimitry Andric // On success, fail_value will be overwritten with the next character in the
1034ba319b5SDimitry Andric // stream
1049f2f44ceSEd Maste GetHexU8Ex(fail_value, set_eof_on_fail);
1059f2f44ceSEd Maste return fail_value;
1069f2f44ceSEd Maste }
1079f2f44ceSEd Maste
GetHexU8Ex(uint8_t & ch,bool set_eof_on_fail)108435933ddSDimitry Andric bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
1097aa51b79SEd Maste int byte = DecodeHexU8();
110435933ddSDimitry Andric if (byte == -1) {
111ac7ddfbfSEd Maste if (set_eof_on_fail || m_index >= m_packet.size())
112ac7ddfbfSEd Maste m_index = UINT64_MAX;
1139f2f44ceSEd Maste // ch should not be changed in case of failure
1149f2f44ceSEd Maste return false;
115ac7ddfbfSEd Maste }
1169f2f44ceSEd Maste ch = (uint8_t)byte;
1179f2f44ceSEd Maste return true;
1187aa51b79SEd Maste }
119ac7ddfbfSEd Maste
GetU32(uint32_t fail_value,int base)120435933ddSDimitry Andric uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) {
121435933ddSDimitry Andric if (m_index < m_packet.size()) {
1220127ef0fSEd Maste char *end = nullptr;
123ac7ddfbfSEd Maste const char *start = m_packet.c_str();
12435617911SEd Maste const char *cstr = start + m_index;
1251c3bbb01SEd Maste uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
126ac7ddfbfSEd Maste
127435933ddSDimitry Andric if (end && end != cstr) {
12835617911SEd Maste m_index = end - start;
12935617911SEd Maste return result;
13035617911SEd Maste }
13135617911SEd Maste }
13235617911SEd Maste return fail_value;
13335617911SEd Maste }
13435617911SEd Maste
GetS32(int32_t fail_value,int base)135435933ddSDimitry Andric int32_t StringExtractor::GetS32(int32_t fail_value, int base) {
136435933ddSDimitry Andric if (m_index < m_packet.size()) {
1370127ef0fSEd Maste char *end = nullptr;
13835617911SEd Maste const char *start = m_packet.c_str();
13935617911SEd Maste const char *cstr = start + m_index;
1401c3bbb01SEd Maste int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
14135617911SEd Maste
142435933ddSDimitry Andric if (end && end != cstr) {
14335617911SEd Maste m_index = end - start;
14435617911SEd Maste return result;
14535617911SEd Maste }
14635617911SEd Maste }
14735617911SEd Maste return fail_value;
14835617911SEd Maste }
14935617911SEd Maste
GetU64(uint64_t fail_value,int base)150435933ddSDimitry Andric uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) {
151435933ddSDimitry Andric if (m_index < m_packet.size()) {
1520127ef0fSEd Maste char *end = nullptr;
15335617911SEd Maste const char *start = m_packet.c_str();
15435617911SEd Maste const char *cstr = start + m_index;
15535617911SEd Maste uint64_t result = ::strtoull(cstr, &end, base);
15635617911SEd Maste
157435933ddSDimitry Andric if (end && end != cstr) {
15835617911SEd Maste m_index = end - start;
15935617911SEd Maste return result;
16035617911SEd Maste }
16135617911SEd Maste }
16235617911SEd Maste return fail_value;
16335617911SEd Maste }
16435617911SEd Maste
GetS64(int64_t fail_value,int base)165435933ddSDimitry Andric int64_t StringExtractor::GetS64(int64_t fail_value, int base) {
166435933ddSDimitry Andric if (m_index < m_packet.size()) {
1670127ef0fSEd Maste char *end = nullptr;
16835617911SEd Maste const char *start = m_packet.c_str();
16935617911SEd Maste const char *cstr = start + m_index;
17035617911SEd Maste int64_t result = ::strtoll(cstr, &end, base);
17135617911SEd Maste
172435933ddSDimitry Andric if (end && end != cstr) {
173ac7ddfbfSEd Maste m_index = end - start;
174ac7ddfbfSEd Maste return result;
175ac7ddfbfSEd Maste }
176ac7ddfbfSEd Maste }
177ac7ddfbfSEd Maste return fail_value;
178ac7ddfbfSEd Maste }
179ac7ddfbfSEd Maste
GetHexMaxU32(bool little_endian,uint32_t fail_value)180435933ddSDimitry Andric uint32_t StringExtractor::GetHexMaxU32(bool little_endian,
181435933ddSDimitry Andric uint32_t fail_value) {
182ac7ddfbfSEd Maste uint32_t result = 0;
183ac7ddfbfSEd Maste uint32_t nibble_count = 0;
184ac7ddfbfSEd Maste
1854bb0738eSEd Maste SkipSpaces();
186435933ddSDimitry Andric if (little_endian) {
187ac7ddfbfSEd Maste uint32_t shift_amount = 0;
188435933ddSDimitry Andric while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
189ac7ddfbfSEd Maste // Make sure we don't exceed the size of a uint32_t...
190435933ddSDimitry Andric if (nibble_count >= (sizeof(uint32_t) * 2)) {
191ac7ddfbfSEd Maste m_index = UINT64_MAX;
192ac7ddfbfSEd Maste return fail_value;
193ac7ddfbfSEd Maste }
194ac7ddfbfSEd Maste
195ac7ddfbfSEd Maste uint8_t nibble_lo;
196ac7ddfbfSEd Maste uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
197ac7ddfbfSEd Maste ++m_index;
198435933ddSDimitry Andric if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
199ac7ddfbfSEd Maste nibble_lo = xdigit_to_sint(m_packet[m_index]);
200ac7ddfbfSEd Maste ++m_index;
201ac7ddfbfSEd Maste result |= ((uint32_t)nibble_hi << (shift_amount + 4));
202ac7ddfbfSEd Maste result |= ((uint32_t)nibble_lo << shift_amount);
203ac7ddfbfSEd Maste nibble_count += 2;
204ac7ddfbfSEd Maste shift_amount += 8;
205435933ddSDimitry Andric } else {
206ac7ddfbfSEd Maste result |= ((uint32_t)nibble_hi << shift_amount);
207ac7ddfbfSEd Maste nibble_count += 1;
208ac7ddfbfSEd Maste shift_amount += 4;
209ac7ddfbfSEd Maste }
210ac7ddfbfSEd Maste }
211435933ddSDimitry Andric } else {
212435933ddSDimitry Andric while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
213ac7ddfbfSEd Maste // Make sure we don't exceed the size of a uint32_t...
214435933ddSDimitry Andric if (nibble_count >= (sizeof(uint32_t) * 2)) {
215ac7ddfbfSEd Maste m_index = UINT64_MAX;
216ac7ddfbfSEd Maste return fail_value;
217ac7ddfbfSEd Maste }
218ac7ddfbfSEd Maste
219ac7ddfbfSEd Maste uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
220ac7ddfbfSEd Maste // Big Endian
221ac7ddfbfSEd Maste result <<= 4;
222ac7ddfbfSEd Maste result |= nibble;
223ac7ddfbfSEd Maste
224ac7ddfbfSEd Maste ++m_index;
225ac7ddfbfSEd Maste ++nibble_count;
226ac7ddfbfSEd Maste }
227ac7ddfbfSEd Maste }
228ac7ddfbfSEd Maste return result;
229ac7ddfbfSEd Maste }
230ac7ddfbfSEd Maste
GetHexMaxU64(bool little_endian,uint64_t fail_value)231435933ddSDimitry Andric uint64_t StringExtractor::GetHexMaxU64(bool little_endian,
232435933ddSDimitry Andric uint64_t fail_value) {
233ac7ddfbfSEd Maste uint64_t result = 0;
234ac7ddfbfSEd Maste uint32_t nibble_count = 0;
235ac7ddfbfSEd Maste
2364bb0738eSEd Maste SkipSpaces();
237435933ddSDimitry Andric if (little_endian) {
238ac7ddfbfSEd Maste uint32_t shift_amount = 0;
239435933ddSDimitry Andric while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
240ac7ddfbfSEd Maste // Make sure we don't exceed the size of a uint64_t...
241435933ddSDimitry Andric if (nibble_count >= (sizeof(uint64_t) * 2)) {
242ac7ddfbfSEd Maste m_index = UINT64_MAX;
243ac7ddfbfSEd Maste return fail_value;
244ac7ddfbfSEd Maste }
245ac7ddfbfSEd Maste
246ac7ddfbfSEd Maste uint8_t nibble_lo;
247ac7ddfbfSEd Maste uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
248ac7ddfbfSEd Maste ++m_index;
249435933ddSDimitry Andric if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
250ac7ddfbfSEd Maste nibble_lo = xdigit_to_sint(m_packet[m_index]);
251ac7ddfbfSEd Maste ++m_index;
252ac7ddfbfSEd Maste result |= ((uint64_t)nibble_hi << (shift_amount + 4));
253ac7ddfbfSEd Maste result |= ((uint64_t)nibble_lo << shift_amount);
254ac7ddfbfSEd Maste nibble_count += 2;
255ac7ddfbfSEd Maste shift_amount += 8;
256435933ddSDimitry Andric } else {
257ac7ddfbfSEd Maste result |= ((uint64_t)nibble_hi << shift_amount);
258ac7ddfbfSEd Maste nibble_count += 1;
259ac7ddfbfSEd Maste shift_amount += 4;
260ac7ddfbfSEd Maste }
261ac7ddfbfSEd Maste }
262435933ddSDimitry Andric } else {
263435933ddSDimitry Andric while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
264ac7ddfbfSEd Maste // Make sure we don't exceed the size of a uint64_t...
265435933ddSDimitry Andric if (nibble_count >= (sizeof(uint64_t) * 2)) {
266ac7ddfbfSEd Maste m_index = UINT64_MAX;
267ac7ddfbfSEd Maste return fail_value;
268ac7ddfbfSEd Maste }
269ac7ddfbfSEd Maste
270ac7ddfbfSEd Maste uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
271ac7ddfbfSEd Maste // Big Endian
272ac7ddfbfSEd Maste result <<= 4;
273ac7ddfbfSEd Maste result |= nibble;
274ac7ddfbfSEd Maste
275ac7ddfbfSEd Maste ++m_index;
276ac7ddfbfSEd Maste ++nibble_count;
277ac7ddfbfSEd Maste }
278ac7ddfbfSEd Maste }
279ac7ddfbfSEd Maste return result;
280ac7ddfbfSEd Maste }
281ac7ddfbfSEd Maste
ConsumeFront(const llvm::StringRef & str)282302affcbSDimitry Andric bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
283302affcbSDimitry Andric llvm::StringRef S = GetStringRef();
284302affcbSDimitry Andric if (!S.startswith(str))
285302affcbSDimitry Andric return false;
286302affcbSDimitry Andric else
287302affcbSDimitry Andric m_index += str.size();
288302affcbSDimitry Andric return true;
289302affcbSDimitry Andric }
290302affcbSDimitry Andric
GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,uint8_t fail_fill_value)291435933ddSDimitry Andric size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
292435933ddSDimitry Andric uint8_t fail_fill_value) {
293ac7ddfbfSEd Maste size_t bytes_extracted = 0;
294435933ddSDimitry Andric while (!dest.empty() && GetBytesLeft() > 0) {
295435933ddSDimitry Andric dest[0] = GetHexU8(fail_fill_value);
296435933ddSDimitry Andric if (!IsGood())
297ac7ddfbfSEd Maste break;
298435933ddSDimitry Andric ++bytes_extracted;
299435933ddSDimitry Andric dest = dest.drop_front();
300ac7ddfbfSEd Maste }
301ac7ddfbfSEd Maste
302435933ddSDimitry Andric if (!dest.empty())
303435933ddSDimitry Andric ::memset(dest.data(), fail_fill_value, dest.size());
304ac7ddfbfSEd Maste
305ac7ddfbfSEd Maste return bytes_extracted;
306ac7ddfbfSEd Maste }
307ac7ddfbfSEd Maste
3087aa51b79SEd Maste //----------------------------------------------------------------------
3094ba319b5SDimitry Andric // Decodes all valid hex encoded bytes at the head of the StringExtractor,
3104ba319b5SDimitry Andric // limited by dst_len.
3117aa51b79SEd Maste //
3127aa51b79SEd Maste // Returns the number of bytes successfully decoded
3137aa51b79SEd Maste //----------------------------------------------------------------------
GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest)314435933ddSDimitry Andric size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) {
3157aa51b79SEd Maste size_t bytes_extracted = 0;
316435933ddSDimitry Andric while (!dest.empty()) {
3177aa51b79SEd Maste int decode = DecodeHexU8();
3187aa51b79SEd Maste if (decode == -1)
3197aa51b79SEd Maste break;
320435933ddSDimitry Andric dest[0] = (uint8_t)decode;
321435933ddSDimitry Andric dest = dest.drop_front();
322435933ddSDimitry Andric ++bytes_extracted;
3237aa51b79SEd Maste }
3247aa51b79SEd Maste return bytes_extracted;
3257aa51b79SEd Maste }
326ac7ddfbfSEd Maste
327ac7ddfbfSEd Maste // Consume ASCII hex nibble character pairs until we have decoded byte_size
328ac7ddfbfSEd Maste // bytes of data.
329ac7ddfbfSEd Maste
GetHexWithFixedSize(uint32_t byte_size,bool little_endian,uint64_t fail_value)330435933ddSDimitry Andric uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size,
331435933ddSDimitry Andric bool little_endian,
332435933ddSDimitry Andric uint64_t fail_value) {
333435933ddSDimitry Andric if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) {
334ac7ddfbfSEd Maste uint64_t result = 0;
335ac7ddfbfSEd Maste uint32_t i;
336435933ddSDimitry Andric if (little_endian) {
337ac7ddfbfSEd Maste // Little Endian
338ac7ddfbfSEd Maste uint32_t shift_amount;
339435933ddSDimitry Andric for (i = 0, shift_amount = 0; i < byte_size && IsGood();
340435933ddSDimitry Andric ++i, shift_amount += 8) {
341ac7ddfbfSEd Maste result |= ((uint64_t)GetHexU8() << shift_amount);
342ac7ddfbfSEd Maste }
343435933ddSDimitry Andric } else {
344ac7ddfbfSEd Maste // Big Endian
345435933ddSDimitry Andric for (i = 0; i < byte_size && IsGood(); ++i) {
346ac7ddfbfSEd Maste result <<= 8;
347ac7ddfbfSEd Maste result |= GetHexU8();
348ac7ddfbfSEd Maste }
349ac7ddfbfSEd Maste }
350ac7ddfbfSEd Maste }
351ac7ddfbfSEd Maste m_index = UINT64_MAX;
352ac7ddfbfSEd Maste return fail_value;
353ac7ddfbfSEd Maste }
354ac7ddfbfSEd Maste
GetHexByteString(std::string & str)355435933ddSDimitry Andric size_t StringExtractor::GetHexByteString(std::string &str) {
356ac7ddfbfSEd Maste str.clear();
357435933ddSDimitry Andric str.reserve(GetBytesLeft() / 2);
358ac7ddfbfSEd Maste char ch;
359ac7ddfbfSEd Maste while ((ch = GetHexU8()) != '\0')
360ac7ddfbfSEd Maste str.append(1, ch);
361ac7ddfbfSEd Maste return str.size();
362ac7ddfbfSEd Maste }
363ac7ddfbfSEd Maste
GetHexByteStringFixedLength(std::string & str,uint32_t nibble_length)364435933ddSDimitry Andric size_t StringExtractor::GetHexByteStringFixedLength(std::string &str,
365435933ddSDimitry Andric uint32_t nibble_length) {
3660127ef0fSEd Maste str.clear();
3670127ef0fSEd Maste
3680127ef0fSEd Maste uint32_t nibble_count = 0;
369435933ddSDimitry Andric for (const char *pch = Peek();
370435933ddSDimitry Andric (nibble_count < nibble_length) && (pch != nullptr);
371435933ddSDimitry Andric str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
372435933ddSDimitry Andric }
3730127ef0fSEd Maste
3740127ef0fSEd Maste return str.size();
3750127ef0fSEd Maste }
3760127ef0fSEd Maste
GetHexByteStringTerminatedBy(std::string & str,char terminator)377435933ddSDimitry Andric size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
378435933ddSDimitry Andric char terminator) {
37935617911SEd Maste str.clear();
38035617911SEd Maste char ch;
38135617911SEd Maste while ((ch = GetHexU8(0, false)) != '\0')
38235617911SEd Maste str.append(1, ch);
38335617911SEd Maste if (Peek() && *Peek() == terminator)
38435617911SEd Maste return str.size();
3850127ef0fSEd Maste
38635617911SEd Maste str.clear();
38735617911SEd Maste return str.size();
38835617911SEd Maste }
38935617911SEd Maste
GetNameColonValue(llvm::StringRef & name,llvm::StringRef & value)390435933ddSDimitry Andric bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
391435933ddSDimitry Andric llvm::StringRef &value) {
3924ba319b5SDimitry Andric // Read something in the form of NNNN:VVVV; where NNNN is any character that
3934ba319b5SDimitry Andric // is not a colon, followed by a ':' character, then a value (one or more ';'
3944ba319b5SDimitry Andric // chars), followed by a ';'
395435933ddSDimitry Andric if (m_index >= m_packet.size())
396435933ddSDimitry Andric return fail();
397435933ddSDimitry Andric
398435933ddSDimitry Andric llvm::StringRef view(m_packet);
399435933ddSDimitry Andric if (view.empty())
400435933ddSDimitry Andric return fail();
401435933ddSDimitry Andric
402435933ddSDimitry Andric llvm::StringRef a, b, c, d;
403435933ddSDimitry Andric view = view.substr(m_index);
404435933ddSDimitry Andric std::tie(a, b) = view.split(':');
405435933ddSDimitry Andric if (a.empty() || b.empty())
406435933ddSDimitry Andric return fail();
407435933ddSDimitry Andric std::tie(c, d) = b.split(';');
408435933ddSDimitry Andric if (b == c && d.empty())
409435933ddSDimitry Andric return fail();
410435933ddSDimitry Andric
411435933ddSDimitry Andric name = a;
412435933ddSDimitry Andric value = c;
413435933ddSDimitry Andric if (d.empty())
414435933ddSDimitry Andric m_index = m_packet.size();
415435933ddSDimitry Andric else {
416435933ddSDimitry Andric size_t bytes_consumed = d.data() - view.data();
417435933ddSDimitry Andric m_index += bytes_consumed;
418435933ddSDimitry Andric }
419ac7ddfbfSEd Maste return true;
420ac7ddfbfSEd Maste }
421b91a7dfcSDimitry Andric
SkipSpaces()422435933ddSDimitry Andric void StringExtractor::SkipSpaces() {
423b91a7dfcSDimitry Andric const size_t n = m_packet.size();
424b91a7dfcSDimitry Andric while (m_index < n && isspace(m_packet[m_index]))
425b91a7dfcSDimitry Andric ++m_index;
426b91a7dfcSDimitry Andric }
427