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 12666cc0b2SZachary Turner // Other libraries and framework includes 13666cc0b2SZachary Turner // Project includes 14666cc0b2SZachary Turner #include "lldb/Utility/Stream.h" 15666cc0b2SZachary Turner #include "llvm/ADT/StringRef.h" 16666cc0b2SZachary Turner 170e1d52aeSZachary Turner // C Includes 180e1d52aeSZachary Turner #include <ctype.h> 190e1d52aeSZachary Turner #include <stdio.h> 200e1d52aeSZachary Turner #include <string.h> 210e1d52aeSZachary Turner 22*a174bcbfSPavel Labath using namespace lldb_private; 230e1d52aeSZachary Turner 2450112989SStephane Sezer UUID::UUID() { Clear(); } 250e1d52aeSZachary Turner 260e1d52aeSZachary Turner UUID::UUID(const UUID &rhs) { 2750112989SStephane Sezer SetBytes(rhs.m_uuid, rhs.m_num_uuid_bytes); 280e1d52aeSZachary Turner } 290e1d52aeSZachary Turner 300e1d52aeSZachary Turner UUID::UUID(const void *uuid_bytes, uint32_t num_uuid_bytes) { 310e1d52aeSZachary Turner SetBytes(uuid_bytes, num_uuid_bytes); 320e1d52aeSZachary Turner } 330e1d52aeSZachary Turner 340e1d52aeSZachary Turner const UUID &UUID::operator=(const UUID &rhs) { 350e1d52aeSZachary Turner if (this != &rhs) { 360e1d52aeSZachary Turner m_num_uuid_bytes = rhs.m_num_uuid_bytes; 370e1d52aeSZachary Turner ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid)); 380e1d52aeSZachary Turner } 390e1d52aeSZachary Turner return *this; 400e1d52aeSZachary Turner } 410e1d52aeSZachary Turner 420e1d52aeSZachary Turner UUID::~UUID() {} 430e1d52aeSZachary Turner 440e1d52aeSZachary Turner void UUID::Clear() { 450e1d52aeSZachary Turner m_num_uuid_bytes = 16; 460e1d52aeSZachary Turner ::memset(m_uuid, 0, sizeof(m_uuid)); 470e1d52aeSZachary Turner } 480e1d52aeSZachary Turner 490e1d52aeSZachary Turner std::string UUID::GetAsString(const char *separator) const { 500e1d52aeSZachary Turner std::string result; 510e1d52aeSZachary Turner char buf[256]; 520e1d52aeSZachary Turner if (!separator) 530e1d52aeSZachary Turner separator = "-"; 54470b286eSPavel Labath const uint8_t *u = GetBytes().data(); 550e1d52aeSZachary Turner if (sizeof(buf) > 560e1d52aeSZachary Turner (size_t)snprintf(buf, sizeof(buf), "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2." 570e1d52aeSZachary Turner "2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%" 580e1d52aeSZachary Turner "2.2X%2.2X%2.2X", 590e1d52aeSZachary Turner u[0], u[1], u[2], u[3], separator, u[4], u[5], separator, 600e1d52aeSZachary Turner u[6], u[7], separator, u[8], u[9], separator, u[10], 610e1d52aeSZachary Turner u[11], u[12], u[13], u[14], u[15])) { 620e1d52aeSZachary Turner result.append(buf); 630e1d52aeSZachary Turner if (m_num_uuid_bytes == 20) { 640e1d52aeSZachary Turner if (sizeof(buf) > (size_t)snprintf(buf, sizeof(buf), 650e1d52aeSZachary Turner "%s%2.2X%2.2X%2.2X%2.2X", separator, 660e1d52aeSZachary Turner u[16], u[17], u[18], u[19])) 670e1d52aeSZachary Turner result.append(buf); 680e1d52aeSZachary Turner } 690e1d52aeSZachary Turner } 700e1d52aeSZachary Turner return result; 710e1d52aeSZachary Turner } 720e1d52aeSZachary Turner 730e1d52aeSZachary Turner void UUID::Dump(Stream *s) const { 74b108dbccSStephane Sezer s->PutCString(GetAsString().c_str()); 750e1d52aeSZachary Turner } 760e1d52aeSZachary Turner 770e1d52aeSZachary Turner bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) { 780e1d52aeSZachary Turner if (uuid_bytes) { 790e1d52aeSZachary Turner switch (num_uuid_bytes) { 800e1d52aeSZachary Turner case 20: 810e1d52aeSZachary Turner m_num_uuid_bytes = 20; 820e1d52aeSZachary Turner break; 830e1d52aeSZachary Turner case 16: 840e1d52aeSZachary Turner m_num_uuid_bytes = 16; 850e1d52aeSZachary Turner m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0; 860e1d52aeSZachary Turner break; 870e1d52aeSZachary Turner default: 880e1d52aeSZachary Turner // Unsupported UUID byte size 890e1d52aeSZachary Turner m_num_uuid_bytes = 0; 900e1d52aeSZachary Turner break; 910e1d52aeSZachary Turner } 920e1d52aeSZachary Turner 930e1d52aeSZachary Turner if (m_num_uuid_bytes > 0) { 940e1d52aeSZachary Turner ::memcpy(m_uuid, uuid_bytes, m_num_uuid_bytes); 950e1d52aeSZachary Turner return true; 960e1d52aeSZachary Turner } 970e1d52aeSZachary Turner } 980e1d52aeSZachary Turner ::memset(m_uuid, 0, sizeof(m_uuid)); 990e1d52aeSZachary Turner return false; 1000e1d52aeSZachary Turner } 1010e1d52aeSZachary Turner 1020e1d52aeSZachary Turner bool UUID::IsValid() const { 1030e1d52aeSZachary Turner return m_uuid[0] || m_uuid[1] || m_uuid[2] || m_uuid[3] || m_uuid[4] || 1040e1d52aeSZachary Turner m_uuid[5] || m_uuid[6] || m_uuid[7] || m_uuid[8] || m_uuid[9] || 1050e1d52aeSZachary Turner m_uuid[10] || m_uuid[11] || m_uuid[12] || m_uuid[13] || m_uuid[14] || 1060e1d52aeSZachary Turner m_uuid[15] || m_uuid[16] || m_uuid[17] || m_uuid[18] || m_uuid[19]; 1070e1d52aeSZachary Turner } 1080e1d52aeSZachary Turner 1090e1d52aeSZachary Turner static inline int xdigit_to_int(char ch) { 1100e1d52aeSZachary Turner ch = tolower(ch); 1110e1d52aeSZachary Turner if (ch >= 'a' && ch <= 'f') 1120e1d52aeSZachary Turner return 10 + ch - 'a'; 1130e1d52aeSZachary Turner return ch - '0'; 1140e1d52aeSZachary Turner } 1150e1d52aeSZachary Turner 1160e1d52aeSZachary Turner llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p, 1170e1d52aeSZachary Turner ValueType &uuid_bytes, 1180e1d52aeSZachary Turner uint32_t &bytes_decoded, 1190e1d52aeSZachary Turner uint32_t num_uuid_bytes) { 1200e1d52aeSZachary Turner ::memset(uuid_bytes, 0, sizeof(uuid_bytes)); 1210e1d52aeSZachary Turner size_t uuid_byte_idx = 0; 1220e1d52aeSZachary Turner while (!p.empty()) { 1230e1d52aeSZachary Turner if (isxdigit(p[0]) && isxdigit(p[1])) { 1240e1d52aeSZachary Turner int hi_nibble = xdigit_to_int(p[0]); 1250e1d52aeSZachary Turner int lo_nibble = xdigit_to_int(p[1]); 1260e1d52aeSZachary Turner // Translate the two hex nibble characters into a byte 1270e1d52aeSZachary Turner uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble; 1280e1d52aeSZachary Turner 1290e1d52aeSZachary Turner // Skip both hex digits 1300e1d52aeSZachary Turner p = p.drop_front(2); 1310e1d52aeSZachary Turner 13205097246SAdrian Prantl // Increment the byte that we are decoding within the UUID value and 13305097246SAdrian Prantl // break out if we are done 1340e1d52aeSZachary Turner if (++uuid_byte_idx == num_uuid_bytes) 1350e1d52aeSZachary Turner break; 1360e1d52aeSZachary Turner } else if (p.front() == '-') { 1370e1d52aeSZachary Turner // Skip dashes 1380e1d52aeSZachary Turner p = p.drop_front(); 1390e1d52aeSZachary Turner } else { 1400e1d52aeSZachary Turner // UUID values can only consist of hex characters and '-' chars 1410e1d52aeSZachary Turner break; 1420e1d52aeSZachary Turner } 1430e1d52aeSZachary Turner } 1440e1d52aeSZachary Turner 1450e1d52aeSZachary Turner // Clear trailing bytes to 0. 1460e1d52aeSZachary Turner for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++) 1470e1d52aeSZachary Turner uuid_bytes[i] = 0; 1480e1d52aeSZachary Turner bytes_decoded = uuid_byte_idx; 1490e1d52aeSZachary Turner return p; 1500e1d52aeSZachary Turner } 1510e1d52aeSZachary Turner 1522833321fSZachary Turner size_t UUID::SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes) { 1532833321fSZachary Turner llvm::StringRef p = str; 1540e1d52aeSZachary Turner 1550e1d52aeSZachary Turner // Skip leading whitespace characters 1560e1d52aeSZachary Turner p = p.ltrim(); 1570e1d52aeSZachary Turner 1580e1d52aeSZachary Turner uint32_t bytes_decoded = 0; 1590e1d52aeSZachary Turner llvm::StringRef rest = 1600e1d52aeSZachary Turner UUID::DecodeUUIDBytesFromString(p, m_uuid, bytes_decoded, num_uuid_bytes); 1610e1d52aeSZachary Turner 1620e1d52aeSZachary Turner // If we successfully decoded a UUID, return the amount of characters that 1630e1d52aeSZachary Turner // were consumed 1640e1d52aeSZachary Turner if (bytes_decoded == num_uuid_bytes) { 1650e1d52aeSZachary Turner m_num_uuid_bytes = num_uuid_bytes; 1662833321fSZachary Turner return str.size() - rest.size(); 1670e1d52aeSZachary Turner } 1680e1d52aeSZachary Turner 1690e1d52aeSZachary Turner // Else return zero to indicate we were not able to parse a UUID value 1700e1d52aeSZachary Turner return 0; 1710e1d52aeSZachary Turner } 1722833321fSZachary Turner 1730e1d52aeSZachary Turner bool lldb_private::operator==(const lldb_private::UUID &lhs, 1740e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 175470b286eSPavel Labath return lhs.GetBytes() == rhs.GetBytes(); 1760e1d52aeSZachary Turner } 1770e1d52aeSZachary Turner 1780e1d52aeSZachary Turner bool lldb_private::operator!=(const lldb_private::UUID &lhs, 1790e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 180d8f06753SDavide Italiano return !(lhs == rhs); 1810e1d52aeSZachary Turner } 1820e1d52aeSZachary Turner 1830e1d52aeSZachary Turner bool lldb_private::operator<(const lldb_private::UUID &lhs, 1840e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 185470b286eSPavel Labath if (lhs.GetBytes().size() != rhs.GetBytes().size()) 186470b286eSPavel Labath return lhs.GetBytes().size() < rhs.GetBytes().size(); 187470b286eSPavel Labath 188470b286eSPavel Labath return std::memcmp(lhs.GetBytes().data(), rhs.GetBytes().data(), 189470b286eSPavel Labath lhs.GetBytes().size()); 1900e1d52aeSZachary Turner } 1910e1d52aeSZachary Turner 1920e1d52aeSZachary Turner bool lldb_private::operator<=(const lldb_private::UUID &lhs, 1930e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 194d8f06753SDavide Italiano return !(lhs > rhs); 1950e1d52aeSZachary Turner } 1960e1d52aeSZachary Turner 1970e1d52aeSZachary Turner bool lldb_private::operator>(const lldb_private::UUID &lhs, 1980e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 199d8f06753SDavide Italiano return rhs < lhs; 2000e1d52aeSZachary Turner } 2010e1d52aeSZachary Turner 2020e1d52aeSZachary Turner bool lldb_private::operator>=(const lldb_private::UUID &lhs, 2030e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 204d8f06753SDavide Italiano return !(lhs < rhs); 2050e1d52aeSZachary Turner } 206