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