VirtualBox

source: vbox/trunk/src/VBox/Runtime/generic/uuid-generic.cpp@ 13476

Last change on this file since 13476 was 11413, checked in by vboxsync, 16 years ago

Runtime: small fix to the UUID code, splitting the ClockSeq field and put the UUID variant in the right place. Rest is cleanup and documenting that the IPRT UUIDs are little endian.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.3 KB
Line 
1/* $Id: uuid-generic.cpp 11413 2008-08-14 08:03:03Z vboxsync $ */
2/** @file
3 * IPRT - UUID, Generic.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/uuid.h>
36#include <iprt/assert.h>
37#include <iprt/err.h>
38
39
40/* WARNING: This implementation ASSUMES little endian. Does not work on big endian! */
41
42/* Remember, the time fields in the UUID must be little endian. */
43
44
45RTDECL(int) RTUuidClear(PRTUUID pUuid)
46{
47 AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
48 pUuid->au64[0] = 0;
49 pUuid->au64[1] = 0;
50 return VINF_SUCCESS;
51}
52
53
54RTDECL(bool) RTUuidIsNull(PCRTUUID pUuid)
55{
56 AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
57 return !pUuid->au64[0]
58 && !pUuid->au64[1];
59}
60
61
62RTDECL(int) RTUuidCompare(PCRTUUID pUuid1, PCRTUUID pUuid2)
63{
64 /*
65 * Special cases.
66 */
67 if (pUuid1 == pUuid2)
68 return 0;
69 if (!pUuid1)
70 return RTUuidIsNull(pUuid2) ? 0 : -1;
71 if (!pUuid2)
72 return RTUuidIsNull(pUuid1) ? 0 : 1;
73 AssertPtrReturn(pUuid1, -1);
74 AssertPtrReturn(pUuid2, 1);
75
76 /*
77 * Standard cases.
78 */
79 if (pUuid1->Gen.u32TimeLow != pUuid2->Gen.u32TimeLow)
80 return pUuid1->Gen.u32TimeLow < pUuid2->Gen.u32TimeLow ? -1 : 1;
81 if (pUuid1->Gen.u16TimeMid != pUuid2->Gen.u16TimeMid)
82 return pUuid1->Gen.u16TimeMid < pUuid2->Gen.u16TimeMid ? -1 : 1;
83 if (pUuid1->Gen.u16TimeHiAndVersion != pUuid2->Gen.u16TimeHiAndVersion)
84 return pUuid1->Gen.u16TimeHiAndVersion < pUuid2->Gen.u16TimeHiAndVersion ? -1 : 1;
85 if (pUuid1->Gen.u8ClockSeqHiAndReserved != pUuid2->Gen.u8ClockSeqHiAndReserved)
86 return pUuid1->Gen.u8ClockSeqHiAndReserved < pUuid2->Gen.u8ClockSeqHiAndReserved ? -1 : 1;
87 if (pUuid1->Gen.u8ClockSeqLow != pUuid2->Gen.u8ClockSeqLow)
88 return pUuid1->Gen.u8ClockSeqLow < pUuid2->Gen.u8ClockSeqLow ? -1 : 1;
89 if (pUuid1->Gen.au8Node[0] != pUuid2->Gen.au8Node[0])
90 return pUuid1->Gen.au8Node[0] < pUuid2->Gen.au8Node[0] ? -1 : 1;
91 if (pUuid1->Gen.au8Node[1] != pUuid2->Gen.au8Node[1])
92 return pUuid1->Gen.au8Node[1] < pUuid2->Gen.au8Node[1] ? -1 : 1;
93 if (pUuid1->Gen.au8Node[2] != pUuid2->Gen.au8Node[2])
94 return pUuid1->Gen.au8Node[2] < pUuid2->Gen.au8Node[2] ? -1 : 1;
95 if (pUuid1->Gen.au8Node[3] != pUuid2->Gen.au8Node[3])
96 return pUuid1->Gen.au8Node[3] < pUuid2->Gen.au8Node[3] ? -1 : 1;
97 if (pUuid1->Gen.au8Node[4] != pUuid2->Gen.au8Node[4])
98 return pUuid1->Gen.au8Node[4] < pUuid2->Gen.au8Node[4] ? -1 : 1;
99 if (pUuid1->Gen.au8Node[5] != pUuid2->Gen.au8Node[5])
100 return pUuid1->Gen.au8Node[5] < pUuid2->Gen.au8Node[5] ? -1 : 1;
101 return 0;
102}
103
104
105RTDECL(int) RTUuidCompareStr(PCRTUUID pUuid1, const char *pszString)
106{
107 /* check params */
108 AssertPtrReturn(pUuid1, -1);
109 AssertPtrReturn(pszString, 1);
110
111 /*
112 * Try convert the string to a UUID and then compare the two.
113 */
114 RTUUID Uuid2;
115 int rc = RTUuidFromStr(&Uuid2, pszString);
116 AssertRCReturn(rc, 1);
117
118 return RTUuidCompare(pUuid1, &Uuid2);
119}
120
121
122RTDECL(int) RTUuidToStr(PCRTUUID pUuid, char *pszString, size_t cchString)
123{
124 /* validate parameters */
125 AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
126 AssertPtrReturn(pszString, VERR_INVALID_PARAMETER);
127 AssertReturn(cchString >= RTUUID_STR_LENGTH, VERR_INVALID_PARAMETER);
128
129 /*
130 * RTStrPrintf(,,"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
131 * pUuid->Gen.u32TimeLow,
132 * pUuid->Gen.u16TimeMin,
133 * pUuid->Gen.u16TimeHiAndVersion,
134 * pUuid->Gen.u16ClockSeq & 0xff,
135 * pUuid->Gen.u16ClockSeq >> 8,
136 * pUuid->Gen.au8Node[0],
137 * pUuid->Gen.au8Node[1],
138 * pUuid->Gen.au8Node[2],
139 * pUuid->Gen.au8Node[3],
140 * pUuid->Gen.au8Node[4],
141 * pUuid->Gen.au8Node[5]);
142 */
143 static const char s_achDigits[17] = "0123456789abcdef";
144 uint32_t u32TimeLow = pUuid->Gen.u32TimeLow;
145 pszString[ 0] = s_achDigits[(u32TimeLow >> 28)/*& 0xf*/];
146 pszString[ 1] = s_achDigits[(u32TimeLow >> 24) & 0xf];
147 pszString[ 2] = s_achDigits[(u32TimeLow >> 20) & 0xf];
148 pszString[ 3] = s_achDigits[(u32TimeLow >> 16) & 0xf];
149 pszString[ 4] = s_achDigits[(u32TimeLow >> 12) & 0xf];
150 pszString[ 5] = s_achDigits[(u32TimeLow >> 8) & 0xf];
151 pszString[ 6] = s_achDigits[(u32TimeLow >> 4) & 0xf];
152 pszString[ 7] = s_achDigits[(u32TimeLow/*>>0*/)& 0xf];
153 pszString[ 8] = '-';
154 unsigned u = pUuid->Gen.u16TimeMid;
155 pszString[ 9] = s_achDigits[(u >> 12)/*& 0xf*/];
156 pszString[10] = s_achDigits[(u >> 8) & 0xf];
157 pszString[11] = s_achDigits[(u >> 4) & 0xf];
158 pszString[12] = s_achDigits[(u/*>>0*/)& 0xf];
159 pszString[13] = '-';
160 u = pUuid->Gen.u16TimeHiAndVersion;
161 pszString[14] = s_achDigits[(u >> 12)/*& 0xf*/];
162 pszString[15] = s_achDigits[(u >> 8) & 0xf];
163 pszString[16] = s_achDigits[(u >> 4) & 0xf];
164 pszString[17] = s_achDigits[(u/*>>0*/)& 0xf];
165 pszString[18] = '-';
166 pszString[19] = s_achDigits[pUuid->Gen.u8ClockSeqHiAndReserved >> 4];
167 pszString[20] = s_achDigits[pUuid->Gen.u8ClockSeqHiAndReserved & 0xf];
168 pszString[21] = s_achDigits[pUuid->Gen.u8ClockSeqLow >> 4];
169 pszString[22] = s_achDigits[pUuid->Gen.u8ClockSeqLow & 0xf];
170 pszString[23] = '-';
171 pszString[24] = s_achDigits[pUuid->Gen.au8Node[0] >> 4];
172 pszString[25] = s_achDigits[pUuid->Gen.au8Node[0] & 0xf];
173 pszString[26] = s_achDigits[pUuid->Gen.au8Node[1] >> 4];
174 pszString[27] = s_achDigits[pUuid->Gen.au8Node[1] & 0xf];
175 pszString[28] = s_achDigits[pUuid->Gen.au8Node[2] >> 4];
176 pszString[29] = s_achDigits[pUuid->Gen.au8Node[2] & 0xf];
177 pszString[30] = s_achDigits[pUuid->Gen.au8Node[3] >> 4];
178 pszString[31] = s_achDigits[pUuid->Gen.au8Node[3] & 0xf];
179 pszString[32] = s_achDigits[pUuid->Gen.au8Node[4] >> 4];
180 pszString[33] = s_achDigits[pUuid->Gen.au8Node[4] & 0xf];
181 pszString[34] = s_achDigits[pUuid->Gen.au8Node[5] >> 4];
182 pszString[35] = s_achDigits[pUuid->Gen.au8Node[5] & 0xf];
183 pszString[36] = '\0';
184
185 return VINF_SUCCESS;
186}
187
188
189RTDECL(int) RTUuidFromStr(PRTUUID pUuid, const char *pszString)
190{
191 /* 0xff if not a hex number, otherwise the value. (Assumes UTF-8 encoded strings.) */
192 static const uint8_t s_aDigits[256] =
193 {
194 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 0..0f */
195 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 10..1f */
196 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 20..2f */
197 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0xff,0xff, 0xff,0xff,0xff,0xff, /* 30..3f */
198 0xff,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 40..4f */
199 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 50..5f */
200 0xff,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 60..6f */
201 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 70..7f */
202 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 80..8f */
203 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 90..9f */
204 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* a0..af */
205 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* b0..bf */
206 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* c0..cf */
207 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* d0..df */
208 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* e0..ef */
209 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* f0..ff */
210 };
211
212 /*
213 * Validate parameters.
214 */
215 AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
216 AssertPtrReturn(pszString, VERR_INVALID_PARAMETER);
217
218#define MY_CHECK(expr) do { if (RT_UNLIKELY(!(expr))) return VERR_INVALID_UUID_FORMAT; } while (0)
219#define MY_ISXDIGIT(ch) (s_aDigits[(ch) & 0xff] != 0xff)
220 MY_CHECK(MY_ISXDIGIT(pszString[ 0]));
221 MY_CHECK(MY_ISXDIGIT(pszString[ 1]));
222 MY_CHECK(MY_ISXDIGIT(pszString[ 2]));
223 MY_CHECK(MY_ISXDIGIT(pszString[ 3]));
224 MY_CHECK(MY_ISXDIGIT(pszString[ 4]));
225 MY_CHECK(MY_ISXDIGIT(pszString[ 5]));
226 MY_CHECK(MY_ISXDIGIT(pszString[ 6]));
227 MY_CHECK(MY_ISXDIGIT(pszString[ 7]));
228 MY_CHECK(pszString[ 8] == '-');
229 MY_CHECK(MY_ISXDIGIT(pszString[ 9]));
230 MY_CHECK(MY_ISXDIGIT(pszString[10]));
231 MY_CHECK(MY_ISXDIGIT(pszString[11]));
232 MY_CHECK(MY_ISXDIGIT(pszString[12]));
233 MY_CHECK(pszString[13] == '-');
234 MY_CHECK(MY_ISXDIGIT(pszString[14]));
235 MY_CHECK(MY_ISXDIGIT(pszString[15]));
236 MY_CHECK(MY_ISXDIGIT(pszString[16]));
237 MY_CHECK(MY_ISXDIGIT(pszString[17]));
238 MY_CHECK(pszString[18] == '-');
239 MY_CHECK(MY_ISXDIGIT(pszString[19]));
240 MY_CHECK(MY_ISXDIGIT(pszString[20]));
241 MY_CHECK(MY_ISXDIGIT(pszString[21]));
242 MY_CHECK(MY_ISXDIGIT(pszString[22]));
243 MY_CHECK(pszString[23] == '-');
244 MY_CHECK(MY_ISXDIGIT(pszString[24]));
245 MY_CHECK(MY_ISXDIGIT(pszString[25]));
246 MY_CHECK(MY_ISXDIGIT(pszString[26]));
247 MY_CHECK(MY_ISXDIGIT(pszString[27]));
248 MY_CHECK(MY_ISXDIGIT(pszString[28]));
249 MY_CHECK(MY_ISXDIGIT(pszString[29]));
250 MY_CHECK(MY_ISXDIGIT(pszString[30]));
251 MY_CHECK(MY_ISXDIGIT(pszString[31]));
252 MY_CHECK(MY_ISXDIGIT(pszString[32]));
253 MY_CHECK(MY_ISXDIGIT(pszString[33]));
254 MY_CHECK(MY_ISXDIGIT(pszString[34]));
255 MY_CHECK(MY_ISXDIGIT(pszString[35]));
256 MY_CHECK(!pszString[36]);
257#undef MY_ISXDIGIT
258#undef MY_CHECK
259
260 /*
261 * Inverse of RTUuidToStr (see above).
262 */
263#define MY_TONUM(ch) (s_aDigits[(ch) & 0xff])
264 pUuid->Gen.u32TimeLow = (uint32_t)MY_TONUM(pszString[ 0]) << 28
265 | (uint32_t)MY_TONUM(pszString[ 1]) << 24
266 | (uint32_t)MY_TONUM(pszString[ 2]) << 20
267 | (uint32_t)MY_TONUM(pszString[ 3]) << 16
268 | (uint32_t)MY_TONUM(pszString[ 4]) << 12
269 | (uint32_t)MY_TONUM(pszString[ 5]) << 8
270 | (uint32_t)MY_TONUM(pszString[ 6]) << 4
271 | (uint32_t)MY_TONUM(pszString[ 7]);
272 pUuid->Gen.u16TimeMid = (uint16_t)MY_TONUM(pszString[ 9]) << 12
273 | (uint16_t)MY_TONUM(pszString[10]) << 8
274 | (uint16_t)MY_TONUM(pszString[11]) << 4
275 | (uint16_t)MY_TONUM(pszString[12]);
276 pUuid->Gen.u16TimeHiAndVersion =
277 (uint16_t)MY_TONUM(pszString[14]) << 12
278 | (uint16_t)MY_TONUM(pszString[15]) << 8
279 | (uint16_t)MY_TONUM(pszString[16]) << 4
280 | (uint16_t)MY_TONUM(pszString[17]);
281 pUuid->Gen.u8ClockSeqHiAndReserved =
282 (uint16_t)MY_TONUM(pszString[19]) << 4
283 | (uint16_t)MY_TONUM(pszString[20]);
284 pUuid->Gen.u8ClockSeqLow =
285 (uint16_t)MY_TONUM(pszString[21]) << 4
286 | (uint16_t)MY_TONUM(pszString[22]);
287 pUuid->Gen.au8Node[0] = (uint8_t)MY_TONUM(pszString[24]) << 4
288 | (uint8_t)MY_TONUM(pszString[25]);
289 pUuid->Gen.au8Node[1] = (uint8_t)MY_TONUM(pszString[26]) << 4
290 | (uint8_t)MY_TONUM(pszString[27]);
291 pUuid->Gen.au8Node[2] = (uint8_t)MY_TONUM(pszString[28]) << 4
292 | (uint8_t)MY_TONUM(pszString[29]);
293 pUuid->Gen.au8Node[3] = (uint8_t)MY_TONUM(pszString[30]) << 4
294 | (uint8_t)MY_TONUM(pszString[31]);
295 pUuid->Gen.au8Node[4] = (uint8_t)MY_TONUM(pszString[32]) << 4
296 | (uint8_t)MY_TONUM(pszString[33]);
297 pUuid->Gen.au8Node[5] = (uint8_t)MY_TONUM(pszString[34]) << 4
298 | (uint8_t)MY_TONUM(pszString[35]);
299#undef MY_TONUM
300 return VINF_SUCCESS;
301}
302
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette