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