10e1d52aeSZachary Turner //===-- UUID.cpp ------------------------------------------------*- C++ -*-===// 20e1d52aeSZachary Turner // 30e1d52aeSZachary Turner // The LLVM Compiler Infrastructure 40e1d52aeSZachary Turner // 50e1d52aeSZachary Turner // This file is distributed under the University of Illinois Open Source 60e1d52aeSZachary Turner // License. See LICENSE.TXT for details. 70e1d52aeSZachary Turner // 80e1d52aeSZachary Turner //===----------------------------------------------------------------------===// 90e1d52aeSZachary Turner 100e1d52aeSZachary Turner #include "lldb/Utility/UUID.h" 110e1d52aeSZachary Turner 12*666cc0b2SZachary Turner // Other libraries and framework includes 13*666cc0b2SZachary Turner // Project includes 14*666cc0b2SZachary Turner #include "lldb/Utility/Stream.h" 15*666cc0b2SZachary Turner 16*666cc0b2SZachary Turner #include "llvm/ADT/StringRef.h" 17*666cc0b2SZachary Turner 180e1d52aeSZachary Turner // C Includes 190e1d52aeSZachary Turner #include <ctype.h> 200e1d52aeSZachary Turner #include <stdio.h> 210e1d52aeSZachary Turner #include <string.h> 220e1d52aeSZachary Turner 230e1d52aeSZachary Turner // C++ Includes 240e1d52aeSZachary Turner #include <string> 250e1d52aeSZachary Turner 260e1d52aeSZachary Turner namespace lldb_private { 270e1d52aeSZachary Turner 280e1d52aeSZachary Turner UUID::UUID() : m_num_uuid_bytes(16) { ::memset(m_uuid, 0, sizeof(m_uuid)); } 290e1d52aeSZachary Turner 300e1d52aeSZachary Turner UUID::UUID(const UUID &rhs) { 310e1d52aeSZachary Turner m_num_uuid_bytes = rhs.m_num_uuid_bytes; 320e1d52aeSZachary Turner ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid)); 330e1d52aeSZachary Turner } 340e1d52aeSZachary Turner 350e1d52aeSZachary Turner UUID::UUID(const void *uuid_bytes, uint32_t num_uuid_bytes) { 360e1d52aeSZachary Turner SetBytes(uuid_bytes, num_uuid_bytes); 370e1d52aeSZachary Turner } 380e1d52aeSZachary Turner 390e1d52aeSZachary Turner const UUID &UUID::operator=(const UUID &rhs) { 400e1d52aeSZachary Turner if (this != &rhs) { 410e1d52aeSZachary Turner m_num_uuid_bytes = rhs.m_num_uuid_bytes; 420e1d52aeSZachary Turner ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid)); 430e1d52aeSZachary Turner } 440e1d52aeSZachary Turner return *this; 450e1d52aeSZachary Turner } 460e1d52aeSZachary Turner 470e1d52aeSZachary Turner UUID::~UUID() {} 480e1d52aeSZachary Turner 490e1d52aeSZachary Turner void UUID::Clear() { 500e1d52aeSZachary Turner m_num_uuid_bytes = 16; 510e1d52aeSZachary Turner ::memset(m_uuid, 0, sizeof(m_uuid)); 520e1d52aeSZachary Turner } 530e1d52aeSZachary Turner 540e1d52aeSZachary Turner const void *UUID::GetBytes() const { return m_uuid; } 550e1d52aeSZachary Turner 560e1d52aeSZachary Turner std::string UUID::GetAsString(const char *separator) const { 570e1d52aeSZachary Turner std::string result; 580e1d52aeSZachary Turner char buf[256]; 590e1d52aeSZachary Turner if (!separator) 600e1d52aeSZachary Turner separator = "-"; 610e1d52aeSZachary Turner const uint8_t *u = (const uint8_t *)GetBytes(); 620e1d52aeSZachary Turner if (sizeof(buf) > 630e1d52aeSZachary Turner (size_t)snprintf(buf, sizeof(buf), "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2." 640e1d52aeSZachary Turner "2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%" 650e1d52aeSZachary Turner "2.2X%2.2X%2.2X", 660e1d52aeSZachary Turner u[0], u[1], u[2], u[3], separator, u[4], u[5], separator, 670e1d52aeSZachary Turner u[6], u[7], separator, u[8], u[9], separator, u[10], 680e1d52aeSZachary Turner u[11], u[12], u[13], u[14], u[15])) { 690e1d52aeSZachary Turner result.append(buf); 700e1d52aeSZachary Turner if (m_num_uuid_bytes == 20) { 710e1d52aeSZachary Turner if (sizeof(buf) > (size_t)snprintf(buf, sizeof(buf), 720e1d52aeSZachary Turner "%s%2.2X%2.2X%2.2X%2.2X", separator, 730e1d52aeSZachary Turner u[16], u[17], u[18], u[19])) 740e1d52aeSZachary Turner result.append(buf); 750e1d52aeSZachary Turner } 760e1d52aeSZachary Turner } 770e1d52aeSZachary Turner return result; 780e1d52aeSZachary Turner } 790e1d52aeSZachary Turner 800e1d52aeSZachary Turner void UUID::Dump(Stream *s) const { 810e1d52aeSZachary Turner const uint8_t *u = (const uint8_t *)GetBytes(); 820e1d52aeSZachary 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%" 830e1d52aeSZachary Turner "2.2X%2.2X%2.2X%2.2X", 840e1d52aeSZachary Turner u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7], u[8], u[9], u[10], 850e1d52aeSZachary Turner u[11], u[12], u[13], u[14], u[15]); 860e1d52aeSZachary Turner if (m_num_uuid_bytes == 20) { 870e1d52aeSZachary Turner s->Printf("-%2.2X%2.2X%2.2X%2.2X", u[16], u[17], u[18], u[19]); 880e1d52aeSZachary Turner } 890e1d52aeSZachary Turner } 900e1d52aeSZachary Turner 910e1d52aeSZachary Turner bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) { 920e1d52aeSZachary Turner if (uuid_bytes) { 930e1d52aeSZachary Turner switch (num_uuid_bytes) { 940e1d52aeSZachary Turner case 20: 950e1d52aeSZachary Turner m_num_uuid_bytes = 20; 960e1d52aeSZachary Turner break; 970e1d52aeSZachary Turner case 16: 980e1d52aeSZachary Turner m_num_uuid_bytes = 16; 990e1d52aeSZachary Turner m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0; 1000e1d52aeSZachary Turner break; 1010e1d52aeSZachary Turner default: 1020e1d52aeSZachary Turner // Unsupported UUID byte size 1030e1d52aeSZachary Turner m_num_uuid_bytes = 0; 1040e1d52aeSZachary Turner break; 1050e1d52aeSZachary Turner } 1060e1d52aeSZachary Turner 1070e1d52aeSZachary Turner if (m_num_uuid_bytes > 0) { 1080e1d52aeSZachary Turner ::memcpy(m_uuid, uuid_bytes, m_num_uuid_bytes); 1090e1d52aeSZachary Turner return true; 1100e1d52aeSZachary Turner } 1110e1d52aeSZachary Turner } 1120e1d52aeSZachary Turner ::memset(m_uuid, 0, sizeof(m_uuid)); 1130e1d52aeSZachary Turner return false; 1140e1d52aeSZachary Turner } 1150e1d52aeSZachary Turner 1160e1d52aeSZachary Turner size_t UUID::GetByteSize() { return m_num_uuid_bytes; } 1170e1d52aeSZachary Turner 1180e1d52aeSZachary Turner bool UUID::IsValid() const { 1190e1d52aeSZachary Turner return m_uuid[0] || m_uuid[1] || m_uuid[2] || m_uuid[3] || m_uuid[4] || 1200e1d52aeSZachary Turner m_uuid[5] || m_uuid[6] || m_uuid[7] || m_uuid[8] || m_uuid[9] || 1210e1d52aeSZachary Turner m_uuid[10] || m_uuid[11] || m_uuid[12] || m_uuid[13] || m_uuid[14] || 1220e1d52aeSZachary Turner m_uuid[15] || m_uuid[16] || m_uuid[17] || m_uuid[18] || m_uuid[19]; 1230e1d52aeSZachary Turner } 1240e1d52aeSZachary Turner 1250e1d52aeSZachary Turner static inline int xdigit_to_int(char ch) { 1260e1d52aeSZachary Turner ch = tolower(ch); 1270e1d52aeSZachary Turner if (ch >= 'a' && ch <= 'f') 1280e1d52aeSZachary Turner return 10 + ch - 'a'; 1290e1d52aeSZachary Turner return ch - '0'; 1300e1d52aeSZachary Turner } 1310e1d52aeSZachary Turner 1320e1d52aeSZachary Turner llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p, 1330e1d52aeSZachary Turner ValueType &uuid_bytes, 1340e1d52aeSZachary Turner uint32_t &bytes_decoded, 1350e1d52aeSZachary Turner uint32_t num_uuid_bytes) { 1360e1d52aeSZachary Turner ::memset(uuid_bytes, 0, sizeof(uuid_bytes)); 1370e1d52aeSZachary Turner size_t uuid_byte_idx = 0; 1380e1d52aeSZachary Turner while (!p.empty()) { 1390e1d52aeSZachary Turner if (isxdigit(p[0]) && isxdigit(p[1])) { 1400e1d52aeSZachary Turner int hi_nibble = xdigit_to_int(p[0]); 1410e1d52aeSZachary Turner int lo_nibble = xdigit_to_int(p[1]); 1420e1d52aeSZachary Turner // Translate the two hex nibble characters into a byte 1430e1d52aeSZachary Turner uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble; 1440e1d52aeSZachary Turner 1450e1d52aeSZachary Turner // Skip both hex digits 1460e1d52aeSZachary Turner p = p.drop_front(2); 1470e1d52aeSZachary Turner 1480e1d52aeSZachary Turner // Increment the byte that we are decoding within the UUID value 1490e1d52aeSZachary Turner // and break out if we are done 1500e1d52aeSZachary Turner if (++uuid_byte_idx == num_uuid_bytes) 1510e1d52aeSZachary Turner break; 1520e1d52aeSZachary Turner } else if (p.front() == '-') { 1530e1d52aeSZachary Turner // Skip dashes 1540e1d52aeSZachary Turner p = p.drop_front(); 1550e1d52aeSZachary Turner } else { 1560e1d52aeSZachary Turner // UUID values can only consist of hex characters and '-' chars 1570e1d52aeSZachary Turner break; 1580e1d52aeSZachary Turner } 1590e1d52aeSZachary Turner } 1600e1d52aeSZachary Turner 1610e1d52aeSZachary Turner // Clear trailing bytes to 0. 1620e1d52aeSZachary Turner for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++) 1630e1d52aeSZachary Turner uuid_bytes[i] = 0; 1640e1d52aeSZachary Turner bytes_decoded = uuid_byte_idx; 1650e1d52aeSZachary Turner return p; 1660e1d52aeSZachary Turner } 1670e1d52aeSZachary Turner size_t UUID::SetFromCString(const char *cstr, uint32_t num_uuid_bytes) { 1680e1d52aeSZachary Turner if (cstr == NULL) 1690e1d52aeSZachary Turner return 0; 1700e1d52aeSZachary Turner 1710e1d52aeSZachary Turner llvm::StringRef orig(cstr); 1720e1d52aeSZachary Turner llvm::StringRef p = orig; 1730e1d52aeSZachary Turner 1740e1d52aeSZachary Turner // Skip leading whitespace characters 1750e1d52aeSZachary Turner p = p.ltrim(); 1760e1d52aeSZachary Turner 1770e1d52aeSZachary Turner uint32_t bytes_decoded = 0; 1780e1d52aeSZachary Turner llvm::StringRef rest = 1790e1d52aeSZachary Turner UUID::DecodeUUIDBytesFromString(p, m_uuid, bytes_decoded, num_uuid_bytes); 1800e1d52aeSZachary Turner 1810e1d52aeSZachary Turner // If we successfully decoded a UUID, return the amount of characters that 1820e1d52aeSZachary Turner // were consumed 1830e1d52aeSZachary Turner if (bytes_decoded == num_uuid_bytes) { 1840e1d52aeSZachary Turner m_num_uuid_bytes = num_uuid_bytes; 1850e1d52aeSZachary Turner return orig.size() - rest.size(); 1860e1d52aeSZachary Turner } 1870e1d52aeSZachary Turner 1880e1d52aeSZachary Turner // Else return zero to indicate we were not able to parse a UUID value 1890e1d52aeSZachary Turner return 0; 1900e1d52aeSZachary Turner } 1910e1d52aeSZachary Turner } 1920e1d52aeSZachary Turner 1930e1d52aeSZachary Turner bool lldb_private::operator==(const lldb_private::UUID &lhs, 1940e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 1950e1d52aeSZachary Turner return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), 1960e1d52aeSZachary Turner sizeof(lldb_private::UUID::ValueType)) == 0; 1970e1d52aeSZachary Turner } 1980e1d52aeSZachary Turner 1990e1d52aeSZachary Turner bool lldb_private::operator!=(const lldb_private::UUID &lhs, 2000e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 2010e1d52aeSZachary Turner return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), 2020e1d52aeSZachary Turner sizeof(lldb_private::UUID::ValueType)) != 0; 2030e1d52aeSZachary Turner } 2040e1d52aeSZachary Turner 2050e1d52aeSZachary Turner bool lldb_private::operator<(const lldb_private::UUID &lhs, 2060e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 2070e1d52aeSZachary Turner return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), 2080e1d52aeSZachary Turner sizeof(lldb_private::UUID::ValueType)) < 0; 2090e1d52aeSZachary Turner } 2100e1d52aeSZachary Turner 2110e1d52aeSZachary Turner bool lldb_private::operator<=(const lldb_private::UUID &lhs, 2120e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 2130e1d52aeSZachary Turner return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), 2140e1d52aeSZachary Turner sizeof(lldb_private::UUID::ValueType)) <= 0; 2150e1d52aeSZachary Turner } 2160e1d52aeSZachary Turner 2170e1d52aeSZachary Turner bool lldb_private::operator>(const lldb_private::UUID &lhs, 2180e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 2190e1d52aeSZachary Turner return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), 2200e1d52aeSZachary Turner sizeof(lldb_private::UUID::ValueType)) > 0; 2210e1d52aeSZachary Turner } 2220e1d52aeSZachary Turner 2230e1d52aeSZachary Turner bool lldb_private::operator>=(const lldb_private::UUID &lhs, 2240e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 2250e1d52aeSZachary Turner return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), 2260e1d52aeSZachary Turner sizeof(lldb_private::UUID::ValueType)) >= 0; 2270e1d52aeSZachary Turner } 228