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