Home | History | Annotate | Download | only in Core
      1 //===-- UUID.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 "lldb/Core/UUID.h"
     11 // C Includes
     12 #include <string.h>
     13 #include <stdio.h>
     14 #include <ctype.h>
     15 
     16 // C++ Includes
     17 #include <string>
     18 
     19 // Other libraries and framework includes
     20 // Project includes
     21 #include "lldb/Core/Stream.h"
     22 
     23 namespace lldb_private {
     24 
     25 UUID::UUID() : m_num_uuid_bytes(16)
     26 {
     27     ::memset (m_uuid, 0, sizeof(m_uuid));
     28 }
     29 
     30 UUID::UUID(const UUID& rhs)
     31 {
     32     m_num_uuid_bytes = rhs.m_num_uuid_bytes;
     33     ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid));
     34 }
     35 
     36 UUID::UUID (const void *uuid_bytes, uint32_t num_uuid_bytes)
     37 {
     38     SetBytes (uuid_bytes, num_uuid_bytes);
     39 }
     40 
     41 const UUID&
     42 UUID::operator=(const UUID& rhs)
     43 {
     44     if (this != &rhs)
     45     {
     46         m_num_uuid_bytes = rhs.m_num_uuid_bytes;
     47         ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid));
     48     }
     49     return *this;
     50 }
     51 
     52 UUID::~UUID()
     53 {
     54 }
     55 
     56 void
     57 UUID::Clear()
     58 {
     59     m_num_uuid_bytes = 16;
     60     ::memset (m_uuid, 0, sizeof(m_uuid));
     61 }
     62 
     63 const void *
     64 UUID::GetBytes() const
     65 {
     66     return m_uuid;
     67 }
     68 
     69 std::string
     70 UUID::GetAsString (const char *separator) const
     71 {
     72     std::string result;
     73     char buf[256];
     74     if (!separator)
     75         separator = "-";
     76     const uint8_t *u = (const uint8_t *)GetBytes();
     77     if (sizeof (buf) > (size_t)snprintf (buf,
     78                             sizeof (buf),
     79                             "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
     80                             u[0],u[1],u[2],u[3],separator,
     81                             u[4],u[5],separator,
     82                             u[6],u[7],separator,
     83                             u[8],u[9],separator,
     84                             u[10],u[11],u[12],u[13],u[14],u[15]))
     85     {
     86         result.append (buf);
     87         if (m_num_uuid_bytes == 20)
     88         {
     89             if (sizeof (buf) > (size_t)snprintf (buf, sizeof (buf), "%s%2.2X%2.2X%2.2X%2.2X", separator,u[16],u[17],u[18],u[19]))
     90                 result.append (buf);
     91         }
     92     }
     93     return result;
     94 }
     95 
     96 void
     97 UUID::Dump (Stream *s) const
     98 {
     99     const uint8_t *u = (const uint8_t *)GetBytes();
    100     s->Printf ("%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
    101               u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]);
    102     if (m_num_uuid_bytes == 20)
    103     {
    104         s->Printf ("-%2.2X%2.2X%2.2X%2.2X", u[16],u[17],u[18],u[19]);
    105     }
    106 }
    107 
    108 bool
    109 UUID::SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes)
    110 {
    111     if (uuid_bytes)
    112     {
    113         switch (num_uuid_bytes)
    114         {
    115             case 20:
    116                 m_num_uuid_bytes = 20;
    117                 break;
    118             case 16:
    119                 m_num_uuid_bytes = 16;
    120                 m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0;
    121                 break;
    122             default:
    123                 // Unsupported UUID byte size
    124                 m_num_uuid_bytes = 0;
    125                 break;
    126         }
    127 
    128         if (m_num_uuid_bytes > 0)
    129         {
    130             ::memcpy (m_uuid, uuid_bytes, m_num_uuid_bytes);
    131             return true;
    132         }
    133     }
    134     ::memset (m_uuid, 0, sizeof(m_uuid));
    135     return false;
    136 }
    137 
    138 size_t
    139 UUID::GetByteSize()
    140 {
    141     return m_num_uuid_bytes;
    142 }
    143 
    144 bool
    145 UUID::IsValid () const
    146 {
    147     return  m_uuid[0]  ||
    148             m_uuid[1]  ||
    149             m_uuid[2]  ||
    150             m_uuid[3]  ||
    151             m_uuid[4]  ||
    152             m_uuid[5]  ||
    153             m_uuid[6]  ||
    154             m_uuid[7]  ||
    155             m_uuid[8]  ||
    156             m_uuid[9]  ||
    157             m_uuid[10] ||
    158             m_uuid[11] ||
    159             m_uuid[12] ||
    160             m_uuid[13] ||
    161             m_uuid[14] ||
    162             m_uuid[15] ||
    163             m_uuid[16] ||
    164             m_uuid[17] ||
    165             m_uuid[18] ||
    166             m_uuid[19];
    167 }
    168 
    169 static inline int
    170 xdigit_to_int (char ch)
    171 {
    172     ch = tolower(ch);
    173     if (ch >= 'a' && ch <= 'f')
    174         return 10 + ch - 'a';
    175     return ch - '0';
    176 }
    177 
    178 size_t
    179 UUID::DecodeUUIDBytesFromCString (const char *p, ValueType &uuid_bytes, const char **end, uint32_t num_uuid_bytes)
    180 {
    181     size_t uuid_byte_idx = 0;
    182     if (p)
    183     {
    184         while (*p)
    185         {
    186             if (isxdigit(p[0]) && isxdigit(p[1]))
    187             {
    188                 int hi_nibble = xdigit_to_int(p[0]);
    189                 int lo_nibble = xdigit_to_int(p[1]);
    190                 // Translate the two hex nibble characters into a byte
    191                 uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble;
    192 
    193                 // Skip both hex digits
    194                 p += 2;
    195 
    196                 // Increment the byte that we are decoding within the UUID value
    197                 // and break out if we are done
    198                 if (++uuid_byte_idx == num_uuid_bytes)
    199                     break;
    200             }
    201             else if (*p == '-')
    202             {
    203                 // Skip dashes
    204                 p++;
    205             }
    206             else
    207             {
    208                 // UUID values can only consist of hex characters and '-' chars
    209                 break;
    210             }
    211         }
    212     }
    213     if (end)
    214         *end = p;
    215     // Clear trailing bytes to 0.
    216     for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++)
    217         uuid_bytes[i] = 0;
    218     return uuid_byte_idx;
    219 }
    220 size_t
    221 UUID::SetFromCString (const char *cstr, uint32_t num_uuid_bytes)
    222 {
    223     if (cstr == NULL)
    224         return 0;
    225 
    226     const char *p = cstr;
    227 
    228     // Skip leading whitespace characters
    229     while (isspace(*p))
    230         ++p;
    231 
    232     const size_t uuid_byte_idx = UUID::DecodeUUIDBytesFromCString (p, m_uuid, &p, num_uuid_bytes);
    233 
    234     // If we successfully decoded a UUID, return the amount of characters that
    235     // were consumed
    236     if (uuid_byte_idx == num_uuid_bytes)
    237         return p - cstr;
    238 
    239     // Else return zero to indicate we were not able to parse a UUID value
    240     return 0;
    241 }
    242 
    243 }
    244 
    245 bool
    246 lldb_private::operator == (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
    247 {
    248     return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) == 0;
    249 }
    250 
    251 bool
    252 lldb_private::operator != (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
    253 {
    254     return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) != 0;
    255 }
    256 
    257 bool
    258 lldb_private::operator <  (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
    259 {
    260     return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) <  0;
    261 }
    262 
    263 bool
    264 lldb_private::operator <= (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
    265 {
    266     return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) <= 0;
    267 }
    268 
    269 bool
    270 lldb_private::operator >  (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
    271 {
    272     return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) >  0;
    273 }
    274 
    275 bool
    276 lldb_private::operator >= (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
    277 {
    278     return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) >= 0;
    279 }
    280