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