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