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