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 220e1d52aeSZachary Turner namespace lldb_private { 230e1d52aeSZachary Turner 240e1d52aeSZachary Turner UUID::UUID() : m_num_uuid_bytes(16) { ::memset(m_uuid, 0, sizeof(m_uuid)); } 250e1d52aeSZachary Turner 260e1d52aeSZachary Turner UUID::UUID(const UUID &rhs) { 270e1d52aeSZachary Turner m_num_uuid_bytes = rhs.m_num_uuid_bytes; 280e1d52aeSZachary Turner ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid)); 290e1d52aeSZachary Turner } 300e1d52aeSZachary Turner 310e1d52aeSZachary Turner UUID::UUID(const void *uuid_bytes, uint32_t num_uuid_bytes) { 320e1d52aeSZachary Turner SetBytes(uuid_bytes, num_uuid_bytes); 330e1d52aeSZachary Turner } 340e1d52aeSZachary Turner 350e1d52aeSZachary Turner const UUID &UUID::operator=(const UUID &rhs) { 360e1d52aeSZachary Turner if (this != &rhs) { 370e1d52aeSZachary Turner m_num_uuid_bytes = rhs.m_num_uuid_bytes; 380e1d52aeSZachary Turner ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid)); 390e1d52aeSZachary Turner } 400e1d52aeSZachary Turner return *this; 410e1d52aeSZachary Turner } 420e1d52aeSZachary Turner 430e1d52aeSZachary Turner UUID::~UUID() {} 440e1d52aeSZachary Turner 450e1d52aeSZachary Turner void UUID::Clear() { 460e1d52aeSZachary Turner m_num_uuid_bytes = 16; 470e1d52aeSZachary Turner ::memset(m_uuid, 0, sizeof(m_uuid)); 480e1d52aeSZachary Turner } 490e1d52aeSZachary Turner 500e1d52aeSZachary Turner const void *UUID::GetBytes() const { return m_uuid; } 510e1d52aeSZachary Turner 520e1d52aeSZachary Turner std::string UUID::GetAsString(const char *separator) const { 530e1d52aeSZachary Turner std::string result; 540e1d52aeSZachary Turner char buf[256]; 550e1d52aeSZachary Turner if (!separator) 560e1d52aeSZachary Turner separator = "-"; 570e1d52aeSZachary Turner const uint8_t *u = (const uint8_t *)GetBytes(); 580e1d52aeSZachary Turner if (sizeof(buf) > 590e1d52aeSZachary Turner (size_t)snprintf(buf, sizeof(buf), "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2." 600e1d52aeSZachary Turner "2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%" 610e1d52aeSZachary Turner "2.2X%2.2X%2.2X", 620e1d52aeSZachary Turner u[0], u[1], u[2], u[3], separator, u[4], u[5], separator, 630e1d52aeSZachary Turner u[6], u[7], separator, u[8], u[9], separator, u[10], 640e1d52aeSZachary Turner u[11], u[12], u[13], u[14], u[15])) { 650e1d52aeSZachary Turner result.append(buf); 660e1d52aeSZachary Turner if (m_num_uuid_bytes == 20) { 670e1d52aeSZachary Turner if (sizeof(buf) > (size_t)snprintf(buf, sizeof(buf), 680e1d52aeSZachary Turner "%s%2.2X%2.2X%2.2X%2.2X", separator, 690e1d52aeSZachary Turner u[16], u[17], u[18], u[19])) 700e1d52aeSZachary Turner result.append(buf); 710e1d52aeSZachary Turner } 720e1d52aeSZachary Turner } 730e1d52aeSZachary Turner return result; 740e1d52aeSZachary Turner } 750e1d52aeSZachary Turner 760e1d52aeSZachary Turner void UUID::Dump(Stream *s) const { 77*b108dbccSStephane Sezer s->PutCString(GetAsString().c_str()); 780e1d52aeSZachary Turner } 790e1d52aeSZachary Turner 800e1d52aeSZachary Turner bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) { 810e1d52aeSZachary Turner if (uuid_bytes) { 820e1d52aeSZachary Turner switch (num_uuid_bytes) { 830e1d52aeSZachary Turner case 20: 840e1d52aeSZachary Turner m_num_uuid_bytes = 20; 850e1d52aeSZachary Turner break; 860e1d52aeSZachary Turner case 16: 870e1d52aeSZachary Turner m_num_uuid_bytes = 16; 880e1d52aeSZachary Turner m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0; 890e1d52aeSZachary Turner break; 900e1d52aeSZachary Turner default: 910e1d52aeSZachary Turner // Unsupported UUID byte size 920e1d52aeSZachary Turner m_num_uuid_bytes = 0; 930e1d52aeSZachary Turner break; 940e1d52aeSZachary Turner } 950e1d52aeSZachary Turner 960e1d52aeSZachary Turner if (m_num_uuid_bytes > 0) { 970e1d52aeSZachary Turner ::memcpy(m_uuid, uuid_bytes, m_num_uuid_bytes); 980e1d52aeSZachary Turner return true; 990e1d52aeSZachary Turner } 1000e1d52aeSZachary Turner } 1010e1d52aeSZachary Turner ::memset(m_uuid, 0, sizeof(m_uuid)); 1020e1d52aeSZachary Turner return false; 1030e1d52aeSZachary Turner } 1040e1d52aeSZachary Turner 10520725523SStephane Sezer size_t UUID::GetByteSize() const { return m_num_uuid_bytes; } 1060e1d52aeSZachary Turner 1070e1d52aeSZachary Turner bool UUID::IsValid() const { 1080e1d52aeSZachary Turner return m_uuid[0] || m_uuid[1] || m_uuid[2] || m_uuid[3] || m_uuid[4] || 1090e1d52aeSZachary Turner m_uuid[5] || m_uuid[6] || m_uuid[7] || m_uuid[8] || m_uuid[9] || 1100e1d52aeSZachary Turner m_uuid[10] || m_uuid[11] || m_uuid[12] || m_uuid[13] || m_uuid[14] || 1110e1d52aeSZachary Turner m_uuid[15] || m_uuid[16] || m_uuid[17] || m_uuid[18] || m_uuid[19]; 1120e1d52aeSZachary Turner } 1130e1d52aeSZachary Turner 1140e1d52aeSZachary Turner static inline int xdigit_to_int(char ch) { 1150e1d52aeSZachary Turner ch = tolower(ch); 1160e1d52aeSZachary Turner if (ch >= 'a' && ch <= 'f') 1170e1d52aeSZachary Turner return 10 + ch - 'a'; 1180e1d52aeSZachary Turner return ch - '0'; 1190e1d52aeSZachary Turner } 1200e1d52aeSZachary Turner 1210e1d52aeSZachary Turner llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p, 1220e1d52aeSZachary Turner ValueType &uuid_bytes, 1230e1d52aeSZachary Turner uint32_t &bytes_decoded, 1240e1d52aeSZachary Turner uint32_t num_uuid_bytes) { 1250e1d52aeSZachary Turner ::memset(uuid_bytes, 0, sizeof(uuid_bytes)); 1260e1d52aeSZachary Turner size_t uuid_byte_idx = 0; 1270e1d52aeSZachary Turner while (!p.empty()) { 1280e1d52aeSZachary Turner if (isxdigit(p[0]) && isxdigit(p[1])) { 1290e1d52aeSZachary Turner int hi_nibble = xdigit_to_int(p[0]); 1300e1d52aeSZachary Turner int lo_nibble = xdigit_to_int(p[1]); 1310e1d52aeSZachary Turner // Translate the two hex nibble characters into a byte 1320e1d52aeSZachary Turner uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble; 1330e1d52aeSZachary Turner 1340e1d52aeSZachary Turner // Skip both hex digits 1350e1d52aeSZachary Turner p = p.drop_front(2); 1360e1d52aeSZachary Turner 1370e1d52aeSZachary Turner // Increment the byte that we are decoding within the UUID value 1380e1d52aeSZachary Turner // and break out if we are done 1390e1d52aeSZachary Turner if (++uuid_byte_idx == num_uuid_bytes) 1400e1d52aeSZachary Turner break; 1410e1d52aeSZachary Turner } else if (p.front() == '-') { 1420e1d52aeSZachary Turner // Skip dashes 1430e1d52aeSZachary Turner p = p.drop_front(); 1440e1d52aeSZachary Turner } else { 1450e1d52aeSZachary Turner // UUID values can only consist of hex characters and '-' chars 1460e1d52aeSZachary Turner break; 1470e1d52aeSZachary Turner } 1480e1d52aeSZachary Turner } 1490e1d52aeSZachary Turner 1500e1d52aeSZachary Turner // Clear trailing bytes to 0. 1510e1d52aeSZachary Turner for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++) 1520e1d52aeSZachary Turner uuid_bytes[i] = 0; 1530e1d52aeSZachary Turner bytes_decoded = uuid_byte_idx; 1540e1d52aeSZachary Turner return p; 1550e1d52aeSZachary Turner } 1560e1d52aeSZachary Turner 1572833321fSZachary Turner size_t UUID::SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes) { 1582833321fSZachary Turner llvm::StringRef p = str; 1590e1d52aeSZachary Turner 1600e1d52aeSZachary Turner // Skip leading whitespace characters 1610e1d52aeSZachary Turner p = p.ltrim(); 1620e1d52aeSZachary Turner 1630e1d52aeSZachary Turner uint32_t bytes_decoded = 0; 1640e1d52aeSZachary Turner llvm::StringRef rest = 1650e1d52aeSZachary Turner UUID::DecodeUUIDBytesFromString(p, m_uuid, bytes_decoded, num_uuid_bytes); 1660e1d52aeSZachary Turner 1670e1d52aeSZachary Turner // If we successfully decoded a UUID, return the amount of characters that 1680e1d52aeSZachary Turner // were consumed 1690e1d52aeSZachary Turner if (bytes_decoded == num_uuid_bytes) { 1700e1d52aeSZachary Turner m_num_uuid_bytes = num_uuid_bytes; 1712833321fSZachary Turner return str.size() - rest.size(); 1720e1d52aeSZachary Turner } 1730e1d52aeSZachary Turner 1740e1d52aeSZachary Turner // Else return zero to indicate we were not able to parse a UUID value 1750e1d52aeSZachary Turner return 0; 1760e1d52aeSZachary Turner } 1772833321fSZachary Turner 1782833321fSZachary Turner size_t UUID::SetFromCString(const char *cstr, uint32_t num_uuid_bytes) { 1792833321fSZachary Turner if (cstr == NULL) 1802833321fSZachary Turner return 0; 1812833321fSZachary Turner 1822833321fSZachary Turner return SetFromStringRef(cstr, num_uuid_bytes); 1832833321fSZachary Turner } 1840e1d52aeSZachary Turner } 1850e1d52aeSZachary Turner 1860e1d52aeSZachary Turner bool lldb_private::operator==(const lldb_private::UUID &lhs, 1870e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 1880e1d52aeSZachary Turner return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), 1890e1d52aeSZachary Turner sizeof(lldb_private::UUID::ValueType)) == 0; 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) { 1990e1d52aeSZachary Turner return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), 2000e1d52aeSZachary Turner sizeof(lldb_private::UUID::ValueType)) < 0; 2010e1d52aeSZachary Turner } 2020e1d52aeSZachary Turner 2030e1d52aeSZachary Turner bool lldb_private::operator<=(const lldb_private::UUID &lhs, 2040e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 205d8f06753SDavide Italiano return !(lhs > rhs); 2060e1d52aeSZachary Turner } 2070e1d52aeSZachary Turner 2080e1d52aeSZachary Turner bool lldb_private::operator>(const lldb_private::UUID &lhs, 2090e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 210d8f06753SDavide Italiano return rhs < lhs; 2110e1d52aeSZachary Turner } 2120e1d52aeSZachary Turner 2130e1d52aeSZachary Turner bool lldb_private::operator>=(const lldb_private::UUID &lhs, 2140e1d52aeSZachary Turner const lldb_private::UUID &rhs) { 215d8f06753SDavide Italiano return !(lhs < rhs); 2160e1d52aeSZachary Turner } 217