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