VirtualBox

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

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

Made RTUuidCompare grok NULL pointers and behave the same way in both the generic and Windows implementation.

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