1*30fdc8d8SChris Lattner //===-- StringExtractor.cpp -------------------------------------*- C++ -*-===//
2*30fdc8d8SChris Lattner //
3*30fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
4*30fdc8d8SChris Lattner //
5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
7*30fdc8d8SChris Lattner //
8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
9*30fdc8d8SChris Lattner 
10*30fdc8d8SChris Lattner #include "StringExtractor.h"
11*30fdc8d8SChris Lattner 
12*30fdc8d8SChris Lattner // C Includes
13*30fdc8d8SChris Lattner // C++ Includes
14*30fdc8d8SChris Lattner // Other libraries and framework includes
15*30fdc8d8SChris Lattner // Project includes
16*30fdc8d8SChris Lattner 
17*30fdc8d8SChris Lattner static inline int
18*30fdc8d8SChris Lattner xdigit_to_sint (char ch)
19*30fdc8d8SChris Lattner {
20*30fdc8d8SChris Lattner     ch = tolower(ch);
21*30fdc8d8SChris Lattner     if (ch >= 'a' && ch <= 'f')
22*30fdc8d8SChris Lattner         return 10 + ch - 'a';
23*30fdc8d8SChris Lattner     return ch - '0';
24*30fdc8d8SChris Lattner }
25*30fdc8d8SChris Lattner 
26*30fdc8d8SChris Lattner static inline unsigned int
27*30fdc8d8SChris Lattner xdigit_to_uint (uint8_t ch)
28*30fdc8d8SChris Lattner {
29*30fdc8d8SChris Lattner     ch = tolower(ch);
30*30fdc8d8SChris Lattner     if (ch >= 'a' && ch <= 'f')
31*30fdc8d8SChris Lattner         return 10u + ch - 'a';
32*30fdc8d8SChris Lattner     return ch - '0';
33*30fdc8d8SChris Lattner }
34*30fdc8d8SChris Lattner 
35*30fdc8d8SChris Lattner //----------------------------------------------------------------------
36*30fdc8d8SChris Lattner // StringExtractor constructor
37*30fdc8d8SChris Lattner //----------------------------------------------------------------------
38*30fdc8d8SChris Lattner StringExtractor::StringExtractor() :
39*30fdc8d8SChris Lattner     m_packet(),
40*30fdc8d8SChris Lattner     m_index (0)
41*30fdc8d8SChris Lattner {
42*30fdc8d8SChris Lattner }
43*30fdc8d8SChris Lattner 
44*30fdc8d8SChris Lattner 
45*30fdc8d8SChris Lattner StringExtractor::StringExtractor(const char *packet_cstr) :
46*30fdc8d8SChris Lattner     m_packet(),
47*30fdc8d8SChris Lattner     m_index (0)
48*30fdc8d8SChris Lattner {
49*30fdc8d8SChris Lattner     if (packet_cstr)
50*30fdc8d8SChris Lattner         m_packet.assign (packet_cstr);
51*30fdc8d8SChris Lattner }
52*30fdc8d8SChris Lattner 
53*30fdc8d8SChris Lattner 
54*30fdc8d8SChris Lattner //----------------------------------------------------------------------
55*30fdc8d8SChris Lattner // StringExtractor copy constructor
56*30fdc8d8SChris Lattner //----------------------------------------------------------------------
57*30fdc8d8SChris Lattner StringExtractor::StringExtractor(const StringExtractor& rhs) :
58*30fdc8d8SChris Lattner     m_packet (rhs.m_packet),
59*30fdc8d8SChris Lattner     m_index (rhs.m_index)
60*30fdc8d8SChris Lattner {
61*30fdc8d8SChris Lattner 
62*30fdc8d8SChris Lattner }
63*30fdc8d8SChris Lattner 
64*30fdc8d8SChris Lattner //----------------------------------------------------------------------
65*30fdc8d8SChris Lattner // StringExtractor assignment operator
66*30fdc8d8SChris Lattner //----------------------------------------------------------------------
67*30fdc8d8SChris Lattner const StringExtractor&
68*30fdc8d8SChris Lattner StringExtractor::operator=(const StringExtractor& rhs)
69*30fdc8d8SChris Lattner {
70*30fdc8d8SChris Lattner     if (this != &rhs)
71*30fdc8d8SChris Lattner     {
72*30fdc8d8SChris Lattner         m_packet = rhs.m_packet;
73*30fdc8d8SChris Lattner         m_index = rhs.m_index;
74*30fdc8d8SChris Lattner 
75*30fdc8d8SChris Lattner     }
76*30fdc8d8SChris Lattner     return *this;
77*30fdc8d8SChris Lattner }
78*30fdc8d8SChris Lattner 
79*30fdc8d8SChris Lattner //----------------------------------------------------------------------
80*30fdc8d8SChris Lattner // Destructor
81*30fdc8d8SChris Lattner //----------------------------------------------------------------------
82*30fdc8d8SChris Lattner StringExtractor::~StringExtractor()
83*30fdc8d8SChris Lattner {
84*30fdc8d8SChris Lattner }
85*30fdc8d8SChris Lattner 
86*30fdc8d8SChris Lattner 
87*30fdc8d8SChris Lattner char
88*30fdc8d8SChris Lattner StringExtractor::GetChar (char fail_value)
89*30fdc8d8SChris Lattner {
90*30fdc8d8SChris Lattner     if (m_index < m_packet.size())
91*30fdc8d8SChris Lattner     {
92*30fdc8d8SChris Lattner         char ch = m_packet[m_index];
93*30fdc8d8SChris Lattner         ++m_index;
94*30fdc8d8SChris Lattner         return ch;
95*30fdc8d8SChris Lattner     }
96*30fdc8d8SChris Lattner     m_index = UINT32_MAX;
97*30fdc8d8SChris Lattner     return fail_value;
98*30fdc8d8SChris Lattner }
99*30fdc8d8SChris Lattner 
100*30fdc8d8SChris Lattner uint32_t
101*30fdc8d8SChris Lattner StringExtractor::GetNumHexASCIICharsAtFilePos (uint32_t max) const
102*30fdc8d8SChris Lattner {
103*30fdc8d8SChris Lattner     uint32_t idx = m_index;
104*30fdc8d8SChris Lattner     const size_t size = m_packet.size();
105*30fdc8d8SChris Lattner     while (idx < size && idx - m_index < max && isxdigit(m_packet[idx]))
106*30fdc8d8SChris Lattner         ++idx;
107*30fdc8d8SChris Lattner     return idx - m_index;
108*30fdc8d8SChris Lattner }
109*30fdc8d8SChris Lattner //----------------------------------------------------------------------
110*30fdc8d8SChris Lattner // Extract a signed character from two hex ASCII chars in the packet
111*30fdc8d8SChris Lattner // string
112*30fdc8d8SChris Lattner //----------------------------------------------------------------------
113*30fdc8d8SChris Lattner int8_t
114*30fdc8d8SChris Lattner StringExtractor::GetHexS8 (int8_t fail_value)
115*30fdc8d8SChris Lattner {
116*30fdc8d8SChris Lattner     if (GetNumHexASCIICharsAtFilePos(2))
117*30fdc8d8SChris Lattner     {
118*30fdc8d8SChris Lattner         char hi_nibble_char = m_packet[m_index];
119*30fdc8d8SChris Lattner         char lo_nibble_char = m_packet[m_index+1];
120*30fdc8d8SChris Lattner 
121*30fdc8d8SChris Lattner         if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
122*30fdc8d8SChris Lattner         {
123*30fdc8d8SChris Lattner             char hi_nibble = xdigit_to_sint (hi_nibble_char);
124*30fdc8d8SChris Lattner             char lo_nibble = xdigit_to_sint (lo_nibble_char);
125*30fdc8d8SChris Lattner             m_index += 2;
126*30fdc8d8SChris Lattner             return (hi_nibble << 4) + lo_nibble;
127*30fdc8d8SChris Lattner         }
128*30fdc8d8SChris Lattner     }
129*30fdc8d8SChris Lattner     m_index = UINT32_MAX;
130*30fdc8d8SChris Lattner     return fail_value;
131*30fdc8d8SChris Lattner }
132*30fdc8d8SChris Lattner 
133*30fdc8d8SChris Lattner //----------------------------------------------------------------------
134*30fdc8d8SChris Lattner // Extract an unsigned character from two hex ASCII chars in the packet
135*30fdc8d8SChris Lattner // string
136*30fdc8d8SChris Lattner //----------------------------------------------------------------------
137*30fdc8d8SChris Lattner uint8_t
138*30fdc8d8SChris Lattner StringExtractor::GetHexU8 (uint8_t fail_value)
139*30fdc8d8SChris Lattner {
140*30fdc8d8SChris Lattner     if (GetNumHexASCIICharsAtFilePos(2))
141*30fdc8d8SChris Lattner     {
142*30fdc8d8SChris Lattner         uint8_t hi_nibble_char = m_packet[m_index];
143*30fdc8d8SChris Lattner         uint8_t lo_nibble_char = m_packet[m_index+1];
144*30fdc8d8SChris Lattner 
145*30fdc8d8SChris Lattner         if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
146*30fdc8d8SChris Lattner         {
147*30fdc8d8SChris Lattner             uint8_t hi_nibble = xdigit_to_sint (hi_nibble_char);
148*30fdc8d8SChris Lattner             uint8_t lo_nibble = xdigit_to_sint (lo_nibble_char);
149*30fdc8d8SChris Lattner             m_index += 2;
150*30fdc8d8SChris Lattner             return (hi_nibble << 4) + lo_nibble;
151*30fdc8d8SChris Lattner         }
152*30fdc8d8SChris Lattner     }
153*30fdc8d8SChris Lattner     m_index = UINT32_MAX;
154*30fdc8d8SChris Lattner     return fail_value;
155*30fdc8d8SChris Lattner }
156*30fdc8d8SChris Lattner 
157*30fdc8d8SChris Lattner uint32_t
158*30fdc8d8SChris Lattner StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
159*30fdc8d8SChris Lattner {
160*30fdc8d8SChris Lattner     uint32_t result = 0;
161*30fdc8d8SChris Lattner     uint32_t nibble_count = 0;
162*30fdc8d8SChris Lattner 
163*30fdc8d8SChris Lattner     if (little_endian)
164*30fdc8d8SChris Lattner     {
165*30fdc8d8SChris Lattner         uint32_t shift_amount = 0;
166*30fdc8d8SChris Lattner         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
167*30fdc8d8SChris Lattner         {
168*30fdc8d8SChris Lattner             // Make sure we don't exceed the size of a uint32_t...
169*30fdc8d8SChris Lattner             if (nibble_count >= (sizeof(uint32_t) * 2))
170*30fdc8d8SChris Lattner             {
171*30fdc8d8SChris Lattner                 m_index = UINT32_MAX;
172*30fdc8d8SChris Lattner                 return fail_value;
173*30fdc8d8SChris Lattner             }
174*30fdc8d8SChris Lattner 
175*30fdc8d8SChris Lattner             uint8_t nibble_lo;
176*30fdc8d8SChris Lattner             uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
177*30fdc8d8SChris Lattner             ++m_index;
178*30fdc8d8SChris Lattner             if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
179*30fdc8d8SChris Lattner             {
180*30fdc8d8SChris Lattner                 nibble_lo = xdigit_to_sint (m_packet[m_index]);
181*30fdc8d8SChris Lattner                 ++m_index;
182*30fdc8d8SChris Lattner                 result |= ((uint32_t)nibble_hi << (shift_amount + 4));
183*30fdc8d8SChris Lattner                 result |= ((uint32_t)nibble_lo << shift_amount);
184*30fdc8d8SChris Lattner                 nibble_count += 2;
185*30fdc8d8SChris Lattner                 shift_amount += 8;
186*30fdc8d8SChris Lattner             }
187*30fdc8d8SChris Lattner             else
188*30fdc8d8SChris Lattner             {
189*30fdc8d8SChris Lattner                 result |= ((uint32_t)nibble_hi << shift_amount);
190*30fdc8d8SChris Lattner                 nibble_count += 1;
191*30fdc8d8SChris Lattner                 shift_amount += 4;
192*30fdc8d8SChris Lattner             }
193*30fdc8d8SChris Lattner 
194*30fdc8d8SChris Lattner         }
195*30fdc8d8SChris Lattner     }
196*30fdc8d8SChris Lattner     else
197*30fdc8d8SChris Lattner     {
198*30fdc8d8SChris Lattner         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
199*30fdc8d8SChris Lattner         {
200*30fdc8d8SChris Lattner             // Make sure we don't exceed the size of a uint32_t...
201*30fdc8d8SChris Lattner             if (nibble_count >= (sizeof(uint32_t) * 2))
202*30fdc8d8SChris Lattner             {
203*30fdc8d8SChris Lattner                 m_index = UINT32_MAX;
204*30fdc8d8SChris Lattner                 return fail_value;
205*30fdc8d8SChris Lattner             }
206*30fdc8d8SChris Lattner 
207*30fdc8d8SChris Lattner             uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
208*30fdc8d8SChris Lattner             // Big Endian
209*30fdc8d8SChris Lattner             result <<= 4;
210*30fdc8d8SChris Lattner             result |= nibble;
211*30fdc8d8SChris Lattner 
212*30fdc8d8SChris Lattner             ++m_index;
213*30fdc8d8SChris Lattner             ++nibble_count;
214*30fdc8d8SChris Lattner         }
215*30fdc8d8SChris Lattner     }
216*30fdc8d8SChris Lattner     return result;
217*30fdc8d8SChris Lattner }
218*30fdc8d8SChris Lattner 
219*30fdc8d8SChris Lattner uint64_t
220*30fdc8d8SChris Lattner StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
221*30fdc8d8SChris Lattner {
222*30fdc8d8SChris Lattner     uint64_t result = 0;
223*30fdc8d8SChris Lattner     uint32_t nibble_count = 0;
224*30fdc8d8SChris Lattner 
225*30fdc8d8SChris Lattner     if (little_endian)
226*30fdc8d8SChris Lattner     {
227*30fdc8d8SChris Lattner         uint32_t shift_amount = 0;
228*30fdc8d8SChris Lattner         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
229*30fdc8d8SChris Lattner         {
230*30fdc8d8SChris Lattner             // Make sure we don't exceed the size of a uint64_t...
231*30fdc8d8SChris Lattner             if (nibble_count >= (sizeof(uint64_t) * 2))
232*30fdc8d8SChris Lattner             {
233*30fdc8d8SChris Lattner                 m_index = UINT32_MAX;
234*30fdc8d8SChris Lattner                 return fail_value;
235*30fdc8d8SChris Lattner             }
236*30fdc8d8SChris Lattner 
237*30fdc8d8SChris Lattner             uint8_t nibble_lo;
238*30fdc8d8SChris Lattner             uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
239*30fdc8d8SChris Lattner             ++m_index;
240*30fdc8d8SChris Lattner             if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
241*30fdc8d8SChris Lattner             {
242*30fdc8d8SChris Lattner                 nibble_lo = xdigit_to_sint (m_packet[m_index]);
243*30fdc8d8SChris Lattner                 ++m_index;
244*30fdc8d8SChris Lattner                 result |= ((uint64_t)nibble_hi << (shift_amount + 4));
245*30fdc8d8SChris Lattner                 result |= ((uint64_t)nibble_lo << shift_amount);
246*30fdc8d8SChris Lattner                 nibble_count += 2;
247*30fdc8d8SChris Lattner                 shift_amount += 8;
248*30fdc8d8SChris Lattner             }
249*30fdc8d8SChris Lattner             else
250*30fdc8d8SChris Lattner             {
251*30fdc8d8SChris Lattner                 result |= ((uint64_t)nibble_hi << shift_amount);
252*30fdc8d8SChris Lattner                 nibble_count += 1;
253*30fdc8d8SChris Lattner                 shift_amount += 4;
254*30fdc8d8SChris Lattner             }
255*30fdc8d8SChris Lattner 
256*30fdc8d8SChris Lattner         }
257*30fdc8d8SChris Lattner     }
258*30fdc8d8SChris Lattner     else
259*30fdc8d8SChris Lattner     {
260*30fdc8d8SChris Lattner         while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
261*30fdc8d8SChris Lattner         {
262*30fdc8d8SChris Lattner             // Make sure we don't exceed the size of a uint64_t...
263*30fdc8d8SChris Lattner             if (nibble_count >= (sizeof(uint64_t) * 2))
264*30fdc8d8SChris Lattner             {
265*30fdc8d8SChris Lattner                 m_index = UINT32_MAX;
266*30fdc8d8SChris Lattner                 return fail_value;
267*30fdc8d8SChris Lattner             }
268*30fdc8d8SChris Lattner 
269*30fdc8d8SChris Lattner             uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
270*30fdc8d8SChris Lattner             // Big Endian
271*30fdc8d8SChris Lattner             result <<= 4;
272*30fdc8d8SChris Lattner             result |= nibble;
273*30fdc8d8SChris Lattner 
274*30fdc8d8SChris Lattner             ++m_index;
275*30fdc8d8SChris Lattner             ++nibble_count;
276*30fdc8d8SChris Lattner         }
277*30fdc8d8SChris Lattner     }
278*30fdc8d8SChris Lattner     return result;
279*30fdc8d8SChris Lattner }
280*30fdc8d8SChris Lattner 
281*30fdc8d8SChris Lattner size_t
282*30fdc8d8SChris Lattner StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
283*30fdc8d8SChris Lattner {
284*30fdc8d8SChris Lattner     uint8_t *dst = (uint8_t*)dst_void;
285*30fdc8d8SChris Lattner     size_t bytes_extracted = 0;
286*30fdc8d8SChris Lattner     while (bytes_extracted < dst_len && GetBytesLeft ())
287*30fdc8d8SChris Lattner     {
288*30fdc8d8SChris Lattner         dst[bytes_extracted] = GetHexU8 (fail_fill_value);
289*30fdc8d8SChris Lattner         if (IsGood())
290*30fdc8d8SChris Lattner             ++bytes_extracted;
291*30fdc8d8SChris Lattner         else
292*30fdc8d8SChris Lattner             break;
293*30fdc8d8SChris Lattner     }
294*30fdc8d8SChris Lattner 
295*30fdc8d8SChris Lattner     for (size_t i = bytes_extracted; i < dst_len; ++i)
296*30fdc8d8SChris Lattner         dst[i] = fail_fill_value;
297*30fdc8d8SChris Lattner 
298*30fdc8d8SChris Lattner     return bytes_extracted;
299*30fdc8d8SChris Lattner }
300*30fdc8d8SChris Lattner 
301*30fdc8d8SChris Lattner 
302*30fdc8d8SChris Lattner // Consume ASCII hex nibble character pairs until we have decoded byte_size
303*30fdc8d8SChris Lattner // bytes of data.
304*30fdc8d8SChris Lattner 
305*30fdc8d8SChris Lattner uint64_t
306*30fdc8d8SChris Lattner StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
307*30fdc8d8SChris Lattner {
308*30fdc8d8SChris Lattner     if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
309*30fdc8d8SChris Lattner     {
310*30fdc8d8SChris Lattner         uint64_t result = 0;
311*30fdc8d8SChris Lattner         uint32_t i;
312*30fdc8d8SChris Lattner         if (little_endian)
313*30fdc8d8SChris Lattner         {
314*30fdc8d8SChris Lattner             // Little Endian
315*30fdc8d8SChris Lattner             uint32_t shift_amount;
316*30fdc8d8SChris Lattner             for (i = 0, shift_amount = 0;
317*30fdc8d8SChris Lattner                  i < byte_size && m_index != UINT32_MAX;
318*30fdc8d8SChris Lattner                  ++i, shift_amount += 8)
319*30fdc8d8SChris Lattner             {
320*30fdc8d8SChris Lattner                 result |= ((uint64_t)GetHexU8() << shift_amount);
321*30fdc8d8SChris Lattner             }
322*30fdc8d8SChris Lattner         }
323*30fdc8d8SChris Lattner         else
324*30fdc8d8SChris Lattner         {
325*30fdc8d8SChris Lattner             // Big Endian
326*30fdc8d8SChris Lattner             for (i = 0; i < byte_size && m_index != UINT32_MAX; ++i)
327*30fdc8d8SChris Lattner             {
328*30fdc8d8SChris Lattner                 result <<= 8;
329*30fdc8d8SChris Lattner                 result |= GetHexU8();
330*30fdc8d8SChris Lattner             }
331*30fdc8d8SChris Lattner         }
332*30fdc8d8SChris Lattner     }
333*30fdc8d8SChris Lattner     m_index = UINT32_MAX;
334*30fdc8d8SChris Lattner     return fail_value;
335*30fdc8d8SChris Lattner }
336*30fdc8d8SChris Lattner 
337*30fdc8d8SChris Lattner bool
338*30fdc8d8SChris Lattner StringExtractor::GetNameColonValue (std::string &name, std::string &value)
339*30fdc8d8SChris Lattner {
340*30fdc8d8SChris Lattner     // Read something in the form of NNNN:VVVV; where NNNN is any character
341*30fdc8d8SChris Lattner     // that is not a colon, followed by a ':' character, then a value (one or
342*30fdc8d8SChris Lattner     // more ';' chars), followed by a ';'
343*30fdc8d8SChris Lattner     if (m_index < m_packet.size())
344*30fdc8d8SChris Lattner     {
345*30fdc8d8SChris Lattner         const size_t colon_idx = m_packet.find (':', m_index);
346*30fdc8d8SChris Lattner         if (colon_idx != std::string::npos)
347*30fdc8d8SChris Lattner         {
348*30fdc8d8SChris Lattner             const size_t semicolon_idx = m_packet.find (';', colon_idx);
349*30fdc8d8SChris Lattner             if (semicolon_idx != std::string::npos)
350*30fdc8d8SChris Lattner             {
351*30fdc8d8SChris Lattner                 name.assign (m_packet, m_index, colon_idx - m_index);
352*30fdc8d8SChris Lattner                 value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
353*30fdc8d8SChris Lattner                 m_index = semicolon_idx + 1;
354*30fdc8d8SChris Lattner                 return true;
355*30fdc8d8SChris Lattner             }
356*30fdc8d8SChris Lattner         }
357*30fdc8d8SChris Lattner     }
358*30fdc8d8SChris Lattner     m_index = UINT32_MAX;
359*30fdc8d8SChris Lattner     return false;
360*30fdc8d8SChris Lattner }
361