VirtualBox

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

Last change on this file since 9741 was 9741, checked in by vboxsync, 17 years ago

Split out RTUuidCreate, so we don't drag in RTRand when we don't need to create UUIDs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.0 KB
Line 
1/* $Id: uuid-generic.cpp 9741 2008-06-16 22:46:46Z 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. Needs testing on big endian! */
41
42
43RTDECL(int) RTUuidClear(PRTUUID pUuid)
44{
45 AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
46 pUuid->au64[0] = 0;
47 pUuid->au64[1] = 0;
48 return VINF_SUCCESS;
49}
50
51
52RTDECL(bool) RTUuidIsNull(PCRTUUID pUuid)
53{
54 AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
55 return !pUuid->au64[0]
56 && !pUuid->au64[1];
57}
58
59
60RTDECL(int) RTUuidCompare(PCRTUUID pUuid1, PCRTUUID pUuid2)
61{
62 /*
63 * Special cases.
64 */
65 /** @todo This differs in the windows implementation... check out which behavior we really want. */
66 if (pUuid1 == pUuid2)
67 return 0;
68 if (!pUuid1)
69 return RTUuidIsNull(pUuid2) ? 0 : -1;
70 if (!pUuid2)
71 return RTUuidIsNull(pUuid1) ? 0 : 1;
72 AssertPtr(pUuid1);
73 AssertPtr(pUuid2);
74
75 /*
76 * Standard cases.
77 */
78 if (pUuid1->Gen.u32TimeLow != pUuid2->Gen.u32TimeLow)
79 return pUuid1->Gen.u32TimeLow < pUuid2->Gen.u32TimeLow ? -1 : 1;
80 if (pUuid1->Gen.u16TimeMid != pUuid2->Gen.u16TimeMid)
81 return pUuid1->Gen.u16TimeMid < pUuid2->Gen.u16TimeMid ? -1 : 1;
82 if (pUuid1->Gen.u16TimeHiAndVersion != pUuid2->Gen.u16TimeHiAndVersion)
83 return pUuid1->Gen.u16TimeHiAndVersion < pUuid2->Gen.u16TimeHiAndVersion ? -1 : 1;
84 if (pUuid1->Gen.u16ClockSeq != pUuid2->Gen.u16ClockSeq)
85 return pUuid1->Gen.u16ClockSeq < pUuid2->Gen.u16ClockSeq ? -1 : 1;
86 if (pUuid1->Gen.au8Node[0] != pUuid2->Gen.au8Node[0])
87 return pUuid1->Gen.au8Node[0] < pUuid2->Gen.au8Node[0] ? -1 : 1;
88 if (pUuid1->Gen.au8Node[1] != pUuid2->Gen.au8Node[1])
89 return pUuid1->Gen.au8Node[1] < pUuid2->Gen.au8Node[1] ? -1 : 1;
90 if (pUuid1->Gen.au8Node[2] != pUuid2->Gen.au8Node[2])
91 return pUuid1->Gen.au8Node[2] < pUuid2->Gen.au8Node[2] ? -1 : 1;
92 if (pUuid1->Gen.au8Node[3] != pUuid2->Gen.au8Node[3])
93 return pUuid1->Gen.au8Node[3] < pUuid2->Gen.au8Node[3] ? -1 : 1;
94 if (pUuid1->Gen.au8Node[4] != pUuid2->Gen.au8Node[4])
95 return pUuid1->Gen.au8Node[4] < pUuid2->Gen.au8Node[4] ? -1 : 1;
96 if (pUuid1->Gen.au8Node[5] != pUuid2->Gen.au8Node[5])
97 return pUuid1->Gen.au8Node[5] < pUuid2->Gen.au8Node[5] ? -1 : 1;
98 return 0;
99}
100
101
102RTDECL(int) RTUuidCompareStr(PCRTUUID pUuid1, const char *pszString)
103{
104 /* check params */
105 AssertPtrReturn(pUuid1, -1);
106 AssertPtrReturn(pszString, 1);
107
108 /*
109 * Try convert the string to a UUID and then compare the two.
110 */
111 RTUUID Uuid2;
112 int rc = RTUuidFromStr(&Uuid2, pszString);
113 AssertRCReturn(rc, 1);
114
115 return RTUuidCompare(pUuid1, &Uuid2);
116}
117
118
119RTDECL(int) RTUuidToStr(PCRTUUID pUuid, char *pszString, size_t cchString)
120{
121 /* validate parameters */
122 AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
123 AssertPtrReturn(pszString, VERR_INVALID_PARAMETER);
124 AssertReturn(cchString >= RTUUID_STR_LENGTH, VERR_INVALID_PARAMETER);
125
126 /*
127 * RTStrPrintf(,,"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
128 * pUuid->Gen.u32TimeLow,
129 * pUuid->Gen.u16TimeMin,
130 * pUuid->Gen.u16TimeHiAndVersion,
131 * pUuid->Gen.u16ClockSeq & 0xff,
132 * pUuid->Gen.u16ClockSeq >> 8,
133 * pUuid->Gen.au8Node[0],
134 * pUuid->Gen.au8Node[1],
135 * pUuid->Gen.au8Node[2],
136 * pUuid->Gen.au8Node[3],
137 * pUuid->Gen.au8Node[4],
138 * pUuid->Gen.au8Node[5]);
139 */
140 static const char s_achDigits[17] = "0123456789abcdef";
141 uint32_t u32TimeLow = pUuid->Gen.u32TimeLow;
142 pszString[ 0] = s_achDigits[(u32TimeLow >> 28)/*& 0xf*/];
143 pszString[ 1] = s_achDigits[(u32TimeLow >> 24) & 0xf];
144 pszString[ 2] = s_achDigits[(u32TimeLow >> 20) & 0xf];
145 pszString[ 3] = s_achDigits[(u32TimeLow >> 16) & 0xf];
146 pszString[ 4] = s_achDigits[(u32TimeLow >> 12) & 0xf];
147 pszString[ 5] = s_achDigits[(u32TimeLow >> 8) & 0xf];
148 pszString[ 6] = s_achDigits[(u32TimeLow >> 4) & 0xf];
149 pszString[ 7] = s_achDigits[(u32TimeLow/*>>0*/)& 0xf];
150 pszString[ 8] = '-';
151 unsigned u = pUuid->Gen.u16TimeMid;
152 pszString[ 9] = s_achDigits[(u >> 12)/*& 0xf*/];
153 pszString[10] = s_achDigits[(u >> 8) & 0xf];
154 pszString[11] = s_achDigits[(u >> 4) & 0xf];
155 pszString[12] = s_achDigits[(u/*>>0*/)& 0xf];
156 pszString[13] = '-';
157 u = pUuid->Gen.u16TimeHiAndVersion;
158 pszString[14] = s_achDigits[(u >> 12)/*& 0xf*/];
159 pszString[15] = s_achDigits[(u >> 8) & 0xf];
160 pszString[16] = s_achDigits[(u >> 4) & 0xf];
161 pszString[17] = s_achDigits[(u/*>>0*/)& 0xf];
162 pszString[18] = '-';
163 u = pUuid->Gen.u16ClockSeq;
164 pszString[19] = s_achDigits[(u >> 4) & 0xf];
165 pszString[20] = s_achDigits[(u/*>>0*/)& 0xf];
166 pszString[21] = s_achDigits[(u >> 12)/*& 0xf*/];
167 pszString[22] = s_achDigits[(u >> 8) & 0xf];
168 pszString[23] = '-';
169 pszString[24] = s_achDigits[pUuid->Gen.au8Node[0] >> 4];
170 pszString[25] = s_achDigits[pUuid->Gen.au8Node[0] & 0xf];
171 pszString[26] = s_achDigits[pUuid->Gen.au8Node[1] >> 4];
172 pszString[27] = s_achDigits[pUuid->Gen.au8Node[1] & 0xf];
173 pszString[28] = s_achDigits[pUuid->Gen.au8Node[2] >> 4];
174 pszString[29] = s_achDigits[pUuid->Gen.au8Node[2] & 0xf];
175 pszString[30] = s_achDigits[pUuid->Gen.au8Node[3] >> 4];
176 pszString[31] = s_achDigits[pUuid->Gen.au8Node[3] & 0xf];
177 pszString[32] = s_achDigits[pUuid->Gen.au8Node[4] >> 4];
178 pszString[33] = s_achDigits[pUuid->Gen.au8Node[4] & 0xf];
179 pszString[34] = s_achDigits[pUuid->Gen.au8Node[5] >> 4];
180 pszString[35] = s_achDigits[pUuid->Gen.au8Node[5] & 0xf];
181 pszString[36] = '\0';
182
183 return VINF_SUCCESS;
184}
185
186
187RTDECL(int) RTUuidFromStr(PRTUUID pUuid, const char *pszString)
188{
189 /* 0xff if not a hex number, otherwise the value. (Assumes UTF-8 encoded strings.) */
190 static const uint8_t s_aDigits[256] =
191 {
192 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 0..0f */
193 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 10..1f */
194 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 20..2f */
195 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0xff,0xff, 0xff,0xff,0xff,0xff, /* 30..3f */
196 0xff,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 40..4f */
197 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 50..5f */
198 0xff,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 60..6f */
199 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 70..7f */
200 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 80..8f */
201 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 90..9f */
202 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* a0..af */
203 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* b0..bf */
204 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* c0..cf */
205 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* d0..df */
206 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* e0..ef */
207 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* f0..ff */
208 };
209
210 /*
211 * Validate parameters.
212 */
213 AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
214 AssertPtrReturn(pszString, VERR_INVALID_PARAMETER);
215
216#define MY_CHECK(expr) do { if (RT_UNLIKELY(!(expr))) return VERR_INVALID_UUID_FORMAT; } while (0)
217#define MY_ISXDIGIT(ch) (s_aDigits[(ch) & 0xff] != 0xff)
218 MY_CHECK(MY_ISXDIGIT(pszString[ 0]));
219 MY_CHECK(MY_ISXDIGIT(pszString[ 1]));
220 MY_CHECK(MY_ISXDIGIT(pszString[ 2]));
221 MY_CHECK(MY_ISXDIGIT(pszString[ 3]));
222 MY_CHECK(MY_ISXDIGIT(pszString[ 4]));
223 MY_CHECK(MY_ISXDIGIT(pszString[ 5]));
224 MY_CHECK(MY_ISXDIGIT(pszString[ 6]));
225 MY_CHECK(MY_ISXDIGIT(pszString[ 7]));
226 MY_CHECK(pszString[ 8] == '-');
227 MY_CHECK(MY_ISXDIGIT(pszString[ 9]));
228 MY_CHECK(MY_ISXDIGIT(pszString[10]));
229 MY_CHECK(MY_ISXDIGIT(pszString[11]));
230 MY_CHECK(MY_ISXDIGIT(pszString[12]));
231 MY_CHECK(pszString[13] == '-');
232 MY_CHECK(MY_ISXDIGIT(pszString[14]));
233 MY_CHECK(MY_ISXDIGIT(pszString[15]));
234 MY_CHECK(MY_ISXDIGIT(pszString[16]));
235 MY_CHECK(MY_ISXDIGIT(pszString[17]));
236 MY_CHECK(pszString[18] == '-');
237 MY_CHECK(MY_ISXDIGIT(pszString[19]));
238 MY_CHECK(MY_ISXDIGIT(pszString[20]));
239 MY_CHECK(MY_ISXDIGIT(pszString[21]));
240 MY_CHECK(MY_ISXDIGIT(pszString[22]));
241 MY_CHECK(pszString[23] == '-');
242 MY_CHECK(MY_ISXDIGIT(pszString[24]));
243 MY_CHECK(MY_ISXDIGIT(pszString[25]));
244 MY_CHECK(MY_ISXDIGIT(pszString[26]));
245 MY_CHECK(MY_ISXDIGIT(pszString[27]));
246 MY_CHECK(MY_ISXDIGIT(pszString[28]));
247 MY_CHECK(MY_ISXDIGIT(pszString[29]));
248 MY_CHECK(MY_ISXDIGIT(pszString[30]));
249 MY_CHECK(MY_ISXDIGIT(pszString[31]));
250 MY_CHECK(MY_ISXDIGIT(pszString[32]));
251 MY_CHECK(MY_ISXDIGIT(pszString[33]));
252 MY_CHECK(MY_ISXDIGIT(pszString[34]));
253 MY_CHECK(MY_ISXDIGIT(pszString[35]));
254 MY_CHECK(!pszString[36]);
255#undef MY_ISXDIGIT
256#undef MY_CHECK
257
258 /*
259 * Inverse of RTUuidToStr (see above).
260 */
261#define MY_TONUM(ch) (s_aDigits[(ch) & 0xff])
262 pUuid->Gen.u32TimeLow = (uint32_t)MY_TONUM(pszString[ 0]) << 28
263 | (uint32_t)MY_TONUM(pszString[ 1]) << 24
264 | (uint32_t)MY_TONUM(pszString[ 2]) << 20
265 | (uint32_t)MY_TONUM(pszString[ 3]) << 16
266 | (uint32_t)MY_TONUM(pszString[ 4]) << 12
267 | (uint32_t)MY_TONUM(pszString[ 5]) << 8
268 | (uint32_t)MY_TONUM(pszString[ 6]) << 4
269 | (uint32_t)MY_TONUM(pszString[ 7]);
270 pUuid->Gen.u16TimeMid = (uint16_t)MY_TONUM(pszString[ 9]) << 12
271 | (uint16_t)MY_TONUM(pszString[10]) << 8
272 | (uint16_t)MY_TONUM(pszString[11]) << 4
273 | (uint16_t)MY_TONUM(pszString[12]);
274 pUuid->Gen.u16TimeHiAndVersion =
275 (uint16_t)MY_TONUM(pszString[14]) << 12
276 | (uint16_t)MY_TONUM(pszString[15]) << 8
277 | (uint16_t)MY_TONUM(pszString[16]) << 4
278 | (uint16_t)MY_TONUM(pszString[17]);
279 pUuid->Gen.u16ClockSeq =(uint16_t)MY_TONUM(pszString[19]) << 4
280 | (uint16_t)MY_TONUM(pszString[20])
281 | (uint16_t)MY_TONUM(pszString[21]) << 12
282 | (uint16_t)MY_TONUM(pszString[22]) << 8;
283 pUuid->Gen.au8Node[0] = (uint8_t)MY_TONUM(pszString[24]) << 4
284 | (uint8_t)MY_TONUM(pszString[25]);
285 pUuid->Gen.au8Node[1] = (uint8_t)MY_TONUM(pszString[26]) << 4
286 | (uint8_t)MY_TONUM(pszString[27]);
287 pUuid->Gen.au8Node[2] = (uint8_t)MY_TONUM(pszString[28]) << 4
288 | (uint8_t)MY_TONUM(pszString[29]);
289 pUuid->Gen.au8Node[3] = (uint8_t)MY_TONUM(pszString[30]) << 4
290 | (uint8_t)MY_TONUM(pszString[31]);
291 pUuid->Gen.au8Node[4] = (uint8_t)MY_TONUM(pszString[32]) << 4
292 | (uint8_t)MY_TONUM(pszString[33]);
293 pUuid->Gen.au8Node[5] = (uint8_t)MY_TONUM(pszString[34]) << 4
294 | (uint8_t)MY_TONUM(pszString[35]);
295#undef MY_TONUM
296 return VINF_SUCCESS;
297}
298
Note: See TracBrowser for help on using the repository browser.

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