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