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