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