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 23namespace lldb_private { 24 25UUID::UUID() : m_num_uuid_bytes(16) 26{ 27 ::memset (m_uuid, 0, sizeof(m_uuid)); 28} 29 30UUID::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 36UUID::UUID (const void *uuid_bytes, uint32_t num_uuid_bytes) 37{ 38 SetBytes (uuid_bytes, num_uuid_bytes); 39} 40 41const UUID& 42UUID::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 52UUID::~UUID() 53{ 54} 55 56void 57UUID::Clear() 58{ 59 m_num_uuid_bytes = 16; 60 ::memset (m_uuid, 0, sizeof(m_uuid)); 61} 62 63const void * 64UUID::GetBytes() const 65{ 66 return m_uuid; 67} 68 69std::string 70UUID::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 96void 97UUID::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 108bool 109UUID::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 138size_t 139UUID::GetByteSize() 140{ 141 return m_num_uuid_bytes; 142} 143 144bool 145UUID::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 169static inline int 170xdigit_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 178size_t 179UUID::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} 220size_t 221UUID::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 245bool 246lldb_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 251bool 252lldb_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 257bool 258lldb_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 263bool 264lldb_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 269bool 270lldb_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 275bool 276lldb_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