130fdc8d8SChris Lattner //===-- StringExtractor.cpp -------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler 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 // StringExtractor constructor
28b9c1b51eSKate Stone StringExtractor::StringExtractor() : m_packet(), m_index(0) {}
2930fdc8d8SChris Lattner 
30b9c1b51eSKate Stone StringExtractor::StringExtractor(llvm::StringRef packet_str)
31b9c1b51eSKate Stone     : m_packet(), m_index(0) {
3254695a33SZachary Turner   m_packet.assign(packet_str.begin(), packet_str.end());
3354695a33SZachary Turner }
3430fdc8d8SChris Lattner 
35b9c1b51eSKate Stone StringExtractor::StringExtractor(const char *packet_cstr)
36b9c1b51eSKate Stone     : m_packet(), m_index(0) {
3730fdc8d8SChris Lattner   if (packet_cstr)
3830fdc8d8SChris Lattner     m_packet.assign(packet_cstr);
3930fdc8d8SChris Lattner }
4030fdc8d8SChris Lattner 
4130fdc8d8SChris Lattner // Destructor
42b9c1b51eSKate Stone StringExtractor::~StringExtractor() {}
4330fdc8d8SChris Lattner 
44b9c1b51eSKate Stone char StringExtractor::GetChar(char fail_value) {
45b9c1b51eSKate Stone   if (m_index < m_packet.size()) {
4630fdc8d8SChris Lattner     char ch = m_packet[m_index];
4730fdc8d8SChris Lattner     ++m_index;
4830fdc8d8SChris Lattner     return ch;
4930fdc8d8SChris Lattner   }
50c7bece56SGreg Clayton   m_index = UINT64_MAX;
5130fdc8d8SChris Lattner   return fail_value;
5230fdc8d8SChris Lattner }
5330fdc8d8SChris Lattner 
5405097246SAdrian Prantl // If a pair of valid hex digits exist at the head of the StringExtractor they
5505097246SAdrian Prantl // are decoded into an unsigned byte and returned by this function
566eddf8dfSVince Harron //
576eddf8dfSVince Harron // If there is not a pair of valid hex digits at the head of the
586eddf8dfSVince Harron // StringExtractor, it is left unchanged and -1 is returned
59b9c1b51eSKate Stone int StringExtractor::DecodeHexU8() {
6015a2165dSFrancis Ricci   SkipSpaces();
61b9c1b51eSKate Stone   if (GetBytesLeft() < 2) {
626eddf8dfSVince Harron     return -1;
63b9739d40SPavel Labath   }
64b9739d40SPavel Labath   const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
65b9739d40SPavel Labath   const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
66b9c1b51eSKate Stone   if (hi_nibble == -1 || lo_nibble == -1) {
676eddf8dfSVince Harron     return -1;
68b9739d40SPavel Labath   }
696eddf8dfSVince Harron   m_index += 2;
70*24374aefSJonas Devlieghere   return static_cast<uint8_t>((hi_nibble << 4) + lo_nibble);
716eddf8dfSVince Harron }
726eddf8dfSVince Harron 
7305097246SAdrian Prantl // Extract an unsigned character from two hex ASCII chars in the packet string,
7405097246SAdrian Prantl // or return fail_value on failure
75b9c1b51eSKate Stone uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
7605097246SAdrian Prantl   // On success, fail_value will be overwritten with the next character in the
7705097246SAdrian Prantl   // stream
78554a8571SDawn Perchik   GetHexU8Ex(fail_value, set_eof_on_fail);
79554a8571SDawn Perchik   return fail_value;
80554a8571SDawn Perchik }
81554a8571SDawn Perchik 
82b9c1b51eSKate Stone bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
836eddf8dfSVince Harron   int byte = DecodeHexU8();
84b9c1b51eSKate Stone   if (byte == -1) {
857b70be39SGreg Clayton     if (set_eof_on_fail || m_index >= m_packet.size())
86c7bece56SGreg Clayton       m_index = UINT64_MAX;
87554a8571SDawn Perchik     // ch should not be changed in case of failure
88554a8571SDawn Perchik     return false;
8930fdc8d8SChris Lattner   }
90*24374aefSJonas Devlieghere   ch = static_cast<uint8_t>(byte);
91554a8571SDawn Perchik   return true;
926eddf8dfSVince Harron }
9330fdc8d8SChris Lattner 
94b9c1b51eSKate Stone uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) {
95b9c1b51eSKate Stone   if (m_index < m_packet.size()) {
96d4612ad0SEd Maste     char *end = nullptr;
9732e0a750SGreg Clayton     const char *start = m_packet.c_str();
98e0f8f574SDaniel Malea     const char *cstr = start + m_index;
99f2d44ca8SEnrico Granata     uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
10032e0a750SGreg Clayton 
101b9c1b51eSKate Stone     if (end && end != cstr) {
102e0f8f574SDaniel Malea       m_index = end - start;
103e0f8f574SDaniel Malea       return result;
104e0f8f574SDaniel Malea     }
105e0f8f574SDaniel Malea   }
106e0f8f574SDaniel Malea   return fail_value;
107e0f8f574SDaniel Malea }
108e0f8f574SDaniel Malea 
109b9c1b51eSKate Stone int32_t StringExtractor::GetS32(int32_t fail_value, int base) {
110b9c1b51eSKate Stone   if (m_index < m_packet.size()) {
111d4612ad0SEd Maste     char *end = nullptr;
112e0f8f574SDaniel Malea     const char *start = m_packet.c_str();
113e0f8f574SDaniel Malea     const char *cstr = start + m_index;
114f2d44ca8SEnrico Granata     int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
115e0f8f574SDaniel Malea 
116b9c1b51eSKate Stone     if (end && end != cstr) {
117e0f8f574SDaniel Malea       m_index = end - start;
118e0f8f574SDaniel Malea       return result;
119e0f8f574SDaniel Malea     }
120e0f8f574SDaniel Malea   }
121e0f8f574SDaniel Malea   return fail_value;
122e0f8f574SDaniel Malea }
123e0f8f574SDaniel Malea 
124b9c1b51eSKate Stone uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) {
125b9c1b51eSKate Stone   if (m_index < m_packet.size()) {
126d4612ad0SEd Maste     char *end = nullptr;
127e0f8f574SDaniel Malea     const char *start = m_packet.c_str();
128e0f8f574SDaniel Malea     const char *cstr = start + m_index;
129e0f8f574SDaniel Malea     uint64_t result = ::strtoull(cstr, &end, base);
130e0f8f574SDaniel Malea 
131b9c1b51eSKate Stone     if (end && end != cstr) {
132e0f8f574SDaniel Malea       m_index = end - start;
133e0f8f574SDaniel Malea       return result;
134e0f8f574SDaniel Malea     }
135e0f8f574SDaniel Malea   }
136e0f8f574SDaniel Malea   return fail_value;
137e0f8f574SDaniel Malea }
138e0f8f574SDaniel Malea 
139b9c1b51eSKate Stone int64_t StringExtractor::GetS64(int64_t fail_value, int base) {
140b9c1b51eSKate Stone   if (m_index < m_packet.size()) {
141d4612ad0SEd Maste     char *end = nullptr;
142e0f8f574SDaniel Malea     const char *start = m_packet.c_str();
143e0f8f574SDaniel Malea     const char *cstr = start + m_index;
144e0f8f574SDaniel Malea     int64_t result = ::strtoll(cstr, &end, base);
145e0f8f574SDaniel Malea 
146b9c1b51eSKate Stone     if (end && end != cstr) {
14732e0a750SGreg Clayton       m_index = end - start;
14832e0a750SGreg Clayton       return result;
14932e0a750SGreg Clayton     }
15032e0a750SGreg Clayton   }
15132e0a750SGreg Clayton   return fail_value;
15232e0a750SGreg Clayton }
15332e0a750SGreg Clayton 
154b9c1b51eSKate Stone uint32_t StringExtractor::GetHexMaxU32(bool little_endian,
155b9c1b51eSKate Stone                                        uint32_t fail_value) {
156b9739d40SPavel Labath   uint32_t result = 0;
157b9739d40SPavel Labath   uint32_t nibble_count = 0;
158b9739d40SPavel Labath 
15915a2165dSFrancis Ricci   SkipSpaces();
160b9c1b51eSKate Stone   if (little_endian) {
161b9739d40SPavel Labath     uint32_t shift_amount = 0;
162b9c1b51eSKate Stone     while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
163b9739d40SPavel Labath       // Make sure we don't exceed the size of a uint32_t...
164b9c1b51eSKate Stone       if (nibble_count >= (sizeof(uint32_t) * 2)) {
165b9739d40SPavel Labath         m_index = UINT64_MAX;
166b9739d40SPavel Labath         return fail_value;
167b9739d40SPavel Labath       }
168b9739d40SPavel Labath 
169b9739d40SPavel Labath       uint8_t nibble_lo;
170b9739d40SPavel Labath       uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
171b9739d40SPavel Labath       ++m_index;
172b9c1b51eSKate Stone       if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
173b9739d40SPavel Labath         nibble_lo = xdigit_to_sint(m_packet[m_index]);
174b9739d40SPavel Labath         ++m_index;
175*24374aefSJonas Devlieghere         result |= (static_cast<uint32_t>(nibble_hi) << (shift_amount + 4));
176*24374aefSJonas Devlieghere         result |= (static_cast<uint32_t>(nibble_lo) << shift_amount);
177b9739d40SPavel Labath         nibble_count += 2;
178b9739d40SPavel Labath         shift_amount += 8;
179b9c1b51eSKate Stone       } else {
180*24374aefSJonas Devlieghere         result |= (static_cast<uint32_t>(nibble_hi) << shift_amount);
181b9739d40SPavel Labath         nibble_count += 1;
182b9739d40SPavel Labath         shift_amount += 4;
18330fdc8d8SChris Lattner       }
184b9739d40SPavel Labath     }
185b9c1b51eSKate Stone   } else {
186b9c1b51eSKate Stone     while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
187b9739d40SPavel Labath       // Make sure we don't exceed the size of a uint32_t...
188b9c1b51eSKate Stone       if (nibble_count >= (sizeof(uint32_t) * 2)) {
189b9739d40SPavel Labath         m_index = UINT64_MAX;
190b9739d40SPavel Labath         return fail_value;
191b9739d40SPavel Labath       }
192b9739d40SPavel Labath 
193b9739d40SPavel Labath       uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
194b9739d40SPavel Labath       // Big Endian
195b9739d40SPavel Labath       result <<= 4;
196b9739d40SPavel Labath       result |= nibble;
197b9739d40SPavel Labath 
198b9739d40SPavel Labath       ++m_index;
199b9739d40SPavel Labath       ++nibble_count;
200b9739d40SPavel Labath     }
201b9739d40SPavel Labath   }
202b9739d40SPavel Labath   return result;
20330fdc8d8SChris Lattner }
20430fdc8d8SChris Lattner 
205b9c1b51eSKate Stone uint64_t StringExtractor::GetHexMaxU64(bool little_endian,
206b9c1b51eSKate Stone                                        uint64_t fail_value) {
207b9739d40SPavel Labath   uint64_t result = 0;
208b9739d40SPavel Labath   uint32_t nibble_count = 0;
209b9739d40SPavel Labath 
21015a2165dSFrancis Ricci   SkipSpaces();
211b9c1b51eSKate Stone   if (little_endian) {
212b9739d40SPavel Labath     uint32_t shift_amount = 0;
213b9c1b51eSKate Stone     while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
214b9739d40SPavel Labath       // Make sure we don't exceed the size of a uint64_t...
215b9c1b51eSKate Stone       if (nibble_count >= (sizeof(uint64_t) * 2)) {
216b9739d40SPavel Labath         m_index = UINT64_MAX;
217b9739d40SPavel Labath         return fail_value;
218b9739d40SPavel Labath       }
219b9739d40SPavel Labath 
220b9739d40SPavel Labath       uint8_t nibble_lo;
221b9739d40SPavel Labath       uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
222b9739d40SPavel Labath       ++m_index;
223b9c1b51eSKate Stone       if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
224b9739d40SPavel Labath         nibble_lo = xdigit_to_sint(m_packet[m_index]);
225b9739d40SPavel Labath         ++m_index;
226*24374aefSJonas Devlieghere         result |= (static_cast<uint64_t>(nibble_hi) << (shift_amount + 4));
227*24374aefSJonas Devlieghere         result |= (static_cast<uint64_t>(nibble_lo) << shift_amount);
228b9739d40SPavel Labath         nibble_count += 2;
229b9739d40SPavel Labath         shift_amount += 8;
230b9c1b51eSKate Stone       } else {
231*24374aefSJonas Devlieghere         result |= (static_cast<uint64_t>(nibble_hi) << shift_amount);
232b9739d40SPavel Labath         nibble_count += 1;
233b9739d40SPavel Labath         shift_amount += 4;
23430fdc8d8SChris Lattner       }
235b9739d40SPavel Labath     }
236b9c1b51eSKate Stone   } else {
237b9c1b51eSKate Stone     while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
238b9739d40SPavel Labath       // Make sure we don't exceed the size of a uint64_t...
239b9c1b51eSKate Stone       if (nibble_count >= (sizeof(uint64_t) * 2)) {
240b9739d40SPavel Labath         m_index = UINT64_MAX;
241b9739d40SPavel Labath         return fail_value;
242b9739d40SPavel Labath       }
243b9739d40SPavel Labath 
244b9739d40SPavel Labath       uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
245b9739d40SPavel Labath       // Big Endian
246b9739d40SPavel Labath       result <<= 4;
247b9739d40SPavel Labath       result |= nibble;
248b9739d40SPavel Labath 
249b9739d40SPavel Labath       ++m_index;
250b9739d40SPavel Labath       ++nibble_count;
251b9739d40SPavel Labath     }
252b9739d40SPavel Labath   }
253b9739d40SPavel Labath   return result;
25430fdc8d8SChris Lattner }
25530fdc8d8SChris Lattner 
256e714c4f5SRavitheja Addepally bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
257e714c4f5SRavitheja Addepally   llvm::StringRef S = GetStringRef();
258e714c4f5SRavitheja Addepally   if (!S.startswith(str))
259e714c4f5SRavitheja Addepally     return false;
260e714c4f5SRavitheja Addepally   else
261e714c4f5SRavitheja Addepally     m_index += str.size();
262e714c4f5SRavitheja Addepally   return true;
263e714c4f5SRavitheja Addepally }
264e714c4f5SRavitheja Addepally 
265b9c1b51eSKate Stone size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
266b9c1b51eSKate Stone                                     uint8_t fail_fill_value) {
26730fdc8d8SChris Lattner   size_t bytes_extracted = 0;
268b9c1b51eSKate Stone   while (!dest.empty() && GetBytesLeft() > 0) {
269d08f09c1SZachary Turner     dest[0] = GetHexU8(fail_fill_value);
270d08f09c1SZachary Turner     if (!IsGood())
27130fdc8d8SChris Lattner       break;
272d08f09c1SZachary Turner     ++bytes_extracted;
273d08f09c1SZachary Turner     dest = dest.drop_front();
27430fdc8d8SChris Lattner   }
27530fdc8d8SChris Lattner 
276d08f09c1SZachary Turner   if (!dest.empty())
277d08f09c1SZachary Turner     ::memset(dest.data(), fail_fill_value, dest.size());
27830fdc8d8SChris Lattner 
27930fdc8d8SChris Lattner   return bytes_extracted;
28030fdc8d8SChris Lattner }
28130fdc8d8SChris Lattner 
28205097246SAdrian Prantl // Decodes all valid hex encoded bytes at the head of the StringExtractor,
28305097246SAdrian Prantl // limited by dst_len.
2846eddf8dfSVince Harron //
2856eddf8dfSVince Harron // Returns the number of bytes successfully decoded
286b9c1b51eSKate Stone size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) {
2876eddf8dfSVince Harron   size_t bytes_extracted = 0;
288b9c1b51eSKate Stone   while (!dest.empty()) {
2896eddf8dfSVince Harron     int decode = DecodeHexU8();
2906eddf8dfSVince Harron     if (decode == -1)
2916eddf8dfSVince Harron       break;
292*24374aefSJonas Devlieghere     dest[0] = static_cast<uint8_t>(decode);
293d08f09c1SZachary Turner     dest = dest.drop_front();
294d08f09c1SZachary Turner     ++bytes_extracted;
2956eddf8dfSVince Harron   }
2966eddf8dfSVince Harron   return bytes_extracted;
2976eddf8dfSVince Harron }
29830fdc8d8SChris Lattner 
299b9739d40SPavel Labath // Consume ASCII hex nibble character pairs until we have decoded byte_size
300b9739d40SPavel Labath // bytes of data.
301b9739d40SPavel Labath 
302b9c1b51eSKate Stone uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size,
303b9c1b51eSKate Stone                                               bool little_endian,
304b9c1b51eSKate Stone                                               uint64_t fail_value) {
305b9c1b51eSKate Stone   if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) {
306b9739d40SPavel Labath     uint64_t result = 0;
307b9739d40SPavel Labath     uint32_t i;
308b9c1b51eSKate Stone     if (little_endian) {
309b9739d40SPavel Labath       // Little Endian
310b9739d40SPavel Labath       uint32_t shift_amount;
311b9c1b51eSKate Stone       for (i = 0, shift_amount = 0; i < byte_size && IsGood();
312b9c1b51eSKate Stone            ++i, shift_amount += 8) {
313*24374aefSJonas Devlieghere         result |= (static_cast<uint64_t>(GetHexU8()) << shift_amount);
314b9739d40SPavel Labath       }
315b9c1b51eSKate Stone     } else {
316b9739d40SPavel Labath       // Big Endian
317b9c1b51eSKate Stone       for (i = 0; i < byte_size && IsGood(); ++i) {
318b9739d40SPavel Labath         result <<= 8;
319b9739d40SPavel Labath         result |= GetHexU8();
320b9739d40SPavel Labath       }
321b9739d40SPavel Labath     }
322b9739d40SPavel Labath   }
323b9739d40SPavel Labath   m_index = UINT64_MAX;
324b9739d40SPavel Labath   return fail_value;
325b9739d40SPavel Labath }
326b9739d40SPavel Labath 
327b9c1b51eSKate Stone size_t StringExtractor::GetHexByteString(std::string &str) {
328de9d0494SGreg Clayton   str.clear();
3298c1b6bd7SPavel Labath   str.reserve(GetBytesLeft() / 2);
330de9d0494SGreg Clayton   char ch;
331de9d0494SGreg Clayton   while ((ch = GetHexU8()) != '\0')
332de9d0494SGreg Clayton     str.append(1, ch);
333de9d0494SGreg Clayton   return str.size();
334de9d0494SGreg Clayton }
335de9d0494SGreg Clayton 
336b9c1b51eSKate Stone size_t StringExtractor::GetHexByteStringFixedLength(std::string &str,
337b9c1b51eSKate Stone                                                     uint32_t nibble_length) {
338af245d11STodd Fiala   str.clear();
339b9739d40SPavel Labath 
340b9739d40SPavel Labath   uint32_t nibble_count = 0;
341b9c1b51eSKate Stone   for (const char *pch = Peek();
342b9c1b51eSKate Stone        (nibble_count < nibble_length) && (pch != nullptr);
343b9c1b51eSKate Stone        str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
344b9c1b51eSKate Stone   }
345b9739d40SPavel Labath 
346af245d11STodd Fiala   return str.size();
347af245d11STodd Fiala }
348af245d11STodd Fiala 
349b9c1b51eSKate Stone size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
350b9c1b51eSKate Stone                                                      char terminator) {
351e0f8f574SDaniel Malea   str.clear();
352e0f8f574SDaniel Malea   char ch;
353e0f8f574SDaniel Malea   while ((ch = GetHexU8(0, false)) != '\0')
354e0f8f574SDaniel Malea     str.append(1, ch);
355b9739d40SPavel Labath   if (Peek() && *Peek() == terminator)
356e0f8f574SDaniel Malea     return str.size();
357af245d11STodd Fiala 
358e0f8f574SDaniel Malea   str.clear();
359e0f8f574SDaniel Malea   return str.size();
360e0f8f574SDaniel Malea }
361e0f8f574SDaniel Malea 
362b9c1b51eSKate Stone bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
363b9c1b51eSKate Stone                                         llvm::StringRef &value) {
36405097246SAdrian Prantl   // Read something in the form of NNNN:VVVV; where NNNN is any character that
36505097246SAdrian Prantl   // is not a colon, followed by a ':' character, then a value (one or more ';'
36605097246SAdrian Prantl   // chars), followed by a ';'
36754695a33SZachary Turner   if (m_index >= m_packet.size())
36854695a33SZachary Turner     return fail();
36954695a33SZachary Turner 
37054695a33SZachary Turner   llvm::StringRef view(m_packet);
37154695a33SZachary Turner   if (view.empty())
37254695a33SZachary Turner     return fail();
37354695a33SZachary Turner 
37454695a33SZachary Turner   llvm::StringRef a, b, c, d;
37554695a33SZachary Turner   view = view.substr(m_index);
37654695a33SZachary Turner   std::tie(a, b) = view.split(':');
37754695a33SZachary Turner   if (a.empty() || b.empty())
37854695a33SZachary Turner     return fail();
37954695a33SZachary Turner   std::tie(c, d) = b.split(';');
38054695a33SZachary Turner   if (b == c && d.empty())
38154695a33SZachary Turner     return fail();
38254695a33SZachary Turner 
38354695a33SZachary Turner   name = a;
38454695a33SZachary Turner   value = c;
38554695a33SZachary Turner   if (d.empty())
38654695a33SZachary Turner     m_index = m_packet.size();
387b9c1b51eSKate Stone   else {
38854695a33SZachary Turner     size_t bytes_consumed = d.data() - view.data();
38954695a33SZachary Turner     m_index += bytes_consumed;
39054695a33SZachary Turner   }
39130fdc8d8SChris Lattner   return true;
39230fdc8d8SChris Lattner }
39398424c44SGreg Clayton 
394b9c1b51eSKate Stone void StringExtractor::SkipSpaces() {
39598424c44SGreg Clayton   const size_t n = m_packet.size();
39698424c44SGreg Clayton   while (m_index < n && isspace(m_packet[m_index]))
39798424c44SGreg Clayton     ++m_index;
39898424c44SGreg Clayton }
399