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/Core/UUID.h"
11 // C Includes
12 #include <string.h>
13 #include <stdio.h>
14 #include <ctype.h>
15
16 // C++ Includes
17 #include <string>
18
19 // Other libraries and framework includes
20 // Project includes
21 #include "lldb/Core/Stream.h"
22
23 namespace lldb_private {
24
UUID()25 UUID::UUID() : m_num_uuid_bytes(16)
26 {
27 ::memset (m_uuid, 0, sizeof(m_uuid));
28 }
29
UUID(const UUID & rhs)30 UUID::UUID(const UUID& rhs)
31 {
32 m_num_uuid_bytes = rhs.m_num_uuid_bytes;
33 ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid));
34 }
35
UUID(const void * uuid_bytes,uint32_t num_uuid_bytes)36 UUID::UUID (const void *uuid_bytes, uint32_t num_uuid_bytes)
37 {
38 SetBytes (uuid_bytes, num_uuid_bytes);
39 }
40
41 const UUID&
operator =(const UUID & rhs)42 UUID::operator=(const UUID& rhs)
43 {
44 if (this != &rhs)
45 {
46 m_num_uuid_bytes = rhs.m_num_uuid_bytes;
47 ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid));
48 }
49 return *this;
50 }
51
~UUID()52 UUID::~UUID()
53 {
54 }
55
56 void
Clear()57 UUID::Clear()
58 {
59 m_num_uuid_bytes = 16;
60 ::memset (m_uuid, 0, sizeof(m_uuid));
61 }
62
63 const void *
GetBytes() const64 UUID::GetBytes() const
65 {
66 return m_uuid;
67 }
68
69 std::string
GetAsString(const char * separator) const70 UUID::GetAsString (const char *separator) const
71 {
72 std::string result;
73 char buf[256];
74 if (!separator)
75 separator = "-";
76 const uint8_t *u = (const uint8_t *)GetBytes();
77 if (sizeof (buf) > (size_t)snprintf (buf,
78 sizeof (buf),
79 "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
80 u[0],u[1],u[2],u[3],separator,
81 u[4],u[5],separator,
82 u[6],u[7],separator,
83 u[8],u[9],separator,
84 u[10],u[11],u[12],u[13],u[14],u[15]))
85 {
86 result.append (buf);
87 if (m_num_uuid_bytes == 20)
88 {
89 if (sizeof (buf) > (size_t)snprintf (buf, sizeof (buf), "%s%2.2X%2.2X%2.2X%2.2X", separator,u[16],u[17],u[18],u[19]))
90 result.append (buf);
91 }
92 }
93 return result;
94 }
95
96 void
Dump(Stream * s) const97 UUID::Dump (Stream *s) const
98 {
99 const uint8_t *u = (const uint8_t *)GetBytes();
100 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%2.2X%2.2X%2.2X%2.2X",
101 u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]);
102 if (m_num_uuid_bytes == 20)
103 {
104 s->Printf ("-%2.2X%2.2X%2.2X%2.2X", u[16],u[17],u[18],u[19]);
105 }
106 }
107
108 bool
SetBytes(const void * uuid_bytes,uint32_t num_uuid_bytes)109 UUID::SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes)
110 {
111 if (uuid_bytes)
112 {
113 switch (num_uuid_bytes)
114 {
115 case 20:
116 m_num_uuid_bytes = 20;
117 break;
118 case 16:
119 m_num_uuid_bytes = 16;
120 m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0;
121 break;
122 default:
123 // Unsupported UUID byte size
124 m_num_uuid_bytes = 0;
125 break;
126 }
127
128 if (m_num_uuid_bytes > 0)
129 {
130 ::memcpy (m_uuid, uuid_bytes, m_num_uuid_bytes);
131 return true;
132 }
133 }
134 ::memset (m_uuid, 0, sizeof(m_uuid));
135 return false;
136 }
137
138 size_t
GetByteSize()139 UUID::GetByteSize()
140 {
141 return m_num_uuid_bytes;
142 }
143
144 bool
IsValid() const145 UUID::IsValid () const
146 {
147 return m_uuid[0] ||
148 m_uuid[1] ||
149 m_uuid[2] ||
150 m_uuid[3] ||
151 m_uuid[4] ||
152 m_uuid[5] ||
153 m_uuid[6] ||
154 m_uuid[7] ||
155 m_uuid[8] ||
156 m_uuid[9] ||
157 m_uuid[10] ||
158 m_uuid[11] ||
159 m_uuid[12] ||
160 m_uuid[13] ||
161 m_uuid[14] ||
162 m_uuid[15] ||
163 m_uuid[16] ||
164 m_uuid[17] ||
165 m_uuid[18] ||
166 m_uuid[19];
167 }
168
169 static inline int
xdigit_to_int(char ch)170 xdigit_to_int (char ch)
171 {
172 ch = tolower(ch);
173 if (ch >= 'a' && ch <= 'f')
174 return 10 + ch - 'a';
175 return ch - '0';
176 }
177
178 size_t
DecodeUUIDBytesFromCString(const char * p,ValueType & uuid_bytes,const char ** end,uint32_t num_uuid_bytes)179 UUID::DecodeUUIDBytesFromCString (const char *p, ValueType &uuid_bytes, const char **end, uint32_t num_uuid_bytes)
180 {
181 size_t uuid_byte_idx = 0;
182 if (p)
183 {
184 while (*p)
185 {
186 if (isxdigit(p[0]) && isxdigit(p[1]))
187 {
188 int hi_nibble = xdigit_to_int(p[0]);
189 int lo_nibble = xdigit_to_int(p[1]);
190 // Translate the two hex nibble characters into a byte
191 uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble;
192
193 // Skip both hex digits
194 p += 2;
195
196 // Increment the byte that we are decoding within the UUID value
197 // and break out if we are done
198 if (++uuid_byte_idx == num_uuid_bytes)
199 break;
200 }
201 else if (*p == '-')
202 {
203 // Skip dashes
204 p++;
205 }
206 else
207 {
208 // UUID values can only consist of hex characters and '-' chars
209 break;
210 }
211 }
212 }
213 if (end)
214 *end = p;
215 // Clear trailing bytes to 0.
216 for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++)
217 uuid_bytes[i] = 0;
218 return uuid_byte_idx;
219 }
220 size_t
SetFromCString(const char * cstr,uint32_t num_uuid_bytes)221 UUID::SetFromCString (const char *cstr, uint32_t num_uuid_bytes)
222 {
223 if (cstr == NULL)
224 return 0;
225
226 const char *p = cstr;
227
228 // Skip leading whitespace characters
229 while (isspace(*p))
230 ++p;
231
232 const size_t uuid_byte_idx = UUID::DecodeUUIDBytesFromCString (p, m_uuid, &p, num_uuid_bytes);
233
234 // If we successfully decoded a UUID, return the amount of characters that
235 // were consumed
236 if (uuid_byte_idx == num_uuid_bytes)
237 return p - cstr;
238
239 // Else return zero to indicate we were not able to parse a UUID value
240 return 0;
241 }
242
243 }
244
245 bool
operator ==(const lldb_private::UUID & lhs,const lldb_private::UUID & rhs)246 lldb_private::operator == (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
247 {
248 return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) == 0;
249 }
250
251 bool
operator !=(const lldb_private::UUID & lhs,const lldb_private::UUID & rhs)252 lldb_private::operator != (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
253 {
254 return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) != 0;
255 }
256
257 bool
operator <(const lldb_private::UUID & lhs,const lldb_private::UUID & rhs)258 lldb_private::operator < (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
259 {
260 return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) < 0;
261 }
262
263 bool
operator <=(const lldb_private::UUID & lhs,const lldb_private::UUID & rhs)264 lldb_private::operator <= (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
265 {
266 return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) <= 0;
267 }
268
269 bool
operator >(const lldb_private::UUID & lhs,const lldb_private::UUID & rhs)270 lldb_private::operator > (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
271 {
272 return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) > 0;
273 }
274
275 bool
operator >=(const lldb_private::UUID & lhs,const lldb_private::UUID & rhs)276 lldb_private::operator >= (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
277 {
278 return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) >= 0;
279 }
280