]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Utility/UUID.cpp
MFV r324714:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Utility / UUID.cpp
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 namespace lldb_private {
23
24 UUID::UUID() { Clear(); }
25
26 UUID::UUID(const UUID &rhs) {
27   SetBytes(rhs.m_uuid, rhs.m_num_uuid_bytes);
28 }
29
30 UUID::UUID(const void *uuid_bytes, uint32_t num_uuid_bytes) {
31   SetBytes(uuid_bytes, num_uuid_bytes);
32 }
33
34 const UUID &UUID::operator=(const UUID &rhs) {
35   if (this != &rhs) {
36     m_num_uuid_bytes = rhs.m_num_uuid_bytes;
37     ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid));
38   }
39   return *this;
40 }
41
42 UUID::~UUID() {}
43
44 void UUID::Clear() {
45   m_num_uuid_bytes = 16;
46   ::memset(m_uuid, 0, sizeof(m_uuid));
47 }
48
49 const void *UUID::GetBytes() const { return m_uuid; }
50
51 std::string UUID::GetAsString(const char *separator) const {
52   std::string result;
53   char buf[256];
54   if (!separator)
55     separator = "-";
56   const uint8_t *u = (const uint8_t *)GetBytes();
57   if (sizeof(buf) >
58       (size_t)snprintf(buf, sizeof(buf), "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2."
59                                          "2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%"
60                                          "2.2X%2.2X%2.2X",
61                        u[0], u[1], u[2], u[3], separator, u[4], u[5], separator,
62                        u[6], u[7], separator, u[8], u[9], separator, u[10],
63                        u[11], u[12], u[13], u[14], u[15])) {
64     result.append(buf);
65     if (m_num_uuid_bytes == 20) {
66       if (sizeof(buf) > (size_t)snprintf(buf, sizeof(buf),
67                                          "%s%2.2X%2.2X%2.2X%2.2X", separator,
68                                          u[16], u[17], u[18], u[19]))
69         result.append(buf);
70     }
71   }
72   return result;
73 }
74
75 void UUID::Dump(Stream *s) const {
76   s->PutCString(GetAsString().c_str());
77 }
78
79 bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) {
80   if (uuid_bytes) {
81     switch (num_uuid_bytes) {
82     case 20:
83       m_num_uuid_bytes = 20;
84       break;
85     case 16:
86       m_num_uuid_bytes = 16;
87       m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0;
88       break;
89     default:
90       // Unsupported UUID byte size
91       m_num_uuid_bytes = 0;
92       break;
93     }
94
95     if (m_num_uuid_bytes > 0) {
96       ::memcpy(m_uuid, uuid_bytes, m_num_uuid_bytes);
97       return true;
98     }
99   }
100   ::memset(m_uuid, 0, sizeof(m_uuid));
101   return false;
102 }
103
104 size_t UUID::GetByteSize() const { return m_num_uuid_bytes; }
105
106 bool UUID::IsValid() const {
107   return m_uuid[0] || m_uuid[1] || m_uuid[2] || m_uuid[3] || m_uuid[4] ||
108          m_uuid[5] || m_uuid[6] || m_uuid[7] || m_uuid[8] || m_uuid[9] ||
109          m_uuid[10] || m_uuid[11] || m_uuid[12] || m_uuid[13] || m_uuid[14] ||
110          m_uuid[15] || m_uuid[16] || m_uuid[17] || m_uuid[18] || m_uuid[19];
111 }
112
113 static inline int xdigit_to_int(char ch) {
114   ch = tolower(ch);
115   if (ch >= 'a' && ch <= 'f')
116     return 10 + ch - 'a';
117   return ch - '0';
118 }
119
120 llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p,
121                                                 ValueType &uuid_bytes,
122                                                 uint32_t &bytes_decoded,
123                                                 uint32_t num_uuid_bytes) {
124   ::memset(uuid_bytes, 0, sizeof(uuid_bytes));
125   size_t uuid_byte_idx = 0;
126   while (!p.empty()) {
127     if (isxdigit(p[0]) && isxdigit(p[1])) {
128       int hi_nibble = xdigit_to_int(p[0]);
129       int lo_nibble = xdigit_to_int(p[1]);
130       // Translate the two hex nibble characters into a byte
131       uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble;
132
133       // Skip both hex digits
134       p = p.drop_front(2);
135
136       // Increment the byte that we are decoding within the UUID value
137       // and break out if we are done
138       if (++uuid_byte_idx == num_uuid_bytes)
139         break;
140     } else if (p.front() == '-') {
141       // Skip dashes
142       p = p.drop_front();
143     } else {
144       // UUID values can only consist of hex characters and '-' chars
145       break;
146     }
147   }
148
149   // Clear trailing bytes to 0.
150   for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++)
151     uuid_bytes[i] = 0;
152   bytes_decoded = uuid_byte_idx;
153   return p;
154 }
155
156 size_t UUID::SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes) {
157   llvm::StringRef p = str;
158
159   // Skip leading whitespace characters
160   p = p.ltrim();
161
162   uint32_t bytes_decoded = 0;
163   llvm::StringRef rest =
164       UUID::DecodeUUIDBytesFromString(p, m_uuid, bytes_decoded, num_uuid_bytes);
165
166   // If we successfully decoded a UUID, return the amount of characters that
167   // were consumed
168   if (bytes_decoded == num_uuid_bytes) {
169     m_num_uuid_bytes = num_uuid_bytes;
170     return str.size() - rest.size();
171   }
172
173   // Else return zero to indicate we were not able to parse a UUID value
174   return 0;
175 }
176
177 size_t UUID::SetFromCString(const char *cstr, uint32_t num_uuid_bytes) {
178   if (cstr == NULL)
179     return 0;
180
181   return SetFromStringRef(cstr, num_uuid_bytes);
182 }
183 }
184
185 bool lldb_private::operator==(const lldb_private::UUID &lhs,
186                               const lldb_private::UUID &rhs) {
187   return ::memcmp(lhs.GetBytes(), rhs.GetBytes(),
188                   sizeof(lldb_private::UUID::ValueType)) == 0;
189 }
190
191 bool lldb_private::operator!=(const lldb_private::UUID &lhs,
192                               const lldb_private::UUID &rhs) {
193   return !(lhs == rhs);
194 }
195
196 bool lldb_private::operator<(const lldb_private::UUID &lhs,
197                              const lldb_private::UUID &rhs) {
198   return ::memcmp(lhs.GetBytes(), rhs.GetBytes(),
199                   sizeof(lldb_private::UUID::ValueType)) < 0;
200 }
201
202 bool lldb_private::operator<=(const lldb_private::UUID &lhs,
203                               const lldb_private::UUID &rhs) {
204   return !(lhs > rhs);
205 }
206
207 bool lldb_private::operator>(const lldb_private::UUID &lhs,
208                              const lldb_private::UUID &rhs) {
209   return rhs < lhs;
210 }
211
212 bool lldb_private::operator>=(const lldb_private::UUID &lhs,
213                               const lldb_private::UUID &rhs) {
214   return !(lhs < rhs);
215 }