VirtualBox

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

Last change on this file since 197 was 129, checked in by vboxsync, 18 years ago

Generic Uuid. Corrected Gen.u16TimeMin to Gen.u16TimeMid.

  • Property svn:keywords set to Id
File size: 15.0 KB
Line 
1/* $Id: uuid-generic.cpp 129 2007-01-18 00:07:02Z vboxsync $ */
2/** @file
3 * InnoTek Portable Runtime - UUID, Generic.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#include <iprt/uuid.h>
27#include <iprt/assert.h>
28#include <iprt/err.h>
29#include <iprt/time.h>
30#include <iprt/asm.h>
31
32
33/* WARNING: This implementation ASSUMES little endian. */
34
35
36/**
37 * Generates a new UUID value.
38 *
39 * @returns iprt status code.
40 * @param pUuid Where to store generated uuid.
41 */
42RTR3DECL(int) RTUuidCreate(PRTUUID pUuid)
43{
44 /* validate input. */
45 AssertReturn(pUuid, VERR_INVALID_PARAMETER);
46
47 /*
48 * We don't have any good random sources in IPRT yet, so
49 * for the time being we'll use Nano time and the cpu TSC
50 * (which of course isn't very good at all!).
51 */
52 RTTIMESPEC Now;
53 pUuid->au64[0] = RTTimeSpecGetNano(RTTimeNow(&Now));
54 pUuid->au64[1] = ASMReadTSC();
55 pUuid->Gen.u16ClockSeq = (pUuid->Gen.u16ClockSeq & 0x3fff) | 0x8000;
56 pUuid->Gen.u16TimeHiAndVersion = (pUuid->Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000;
57
58 return VINF_SUCCESS;
59}
60
61
62/**
63 * Makes a null UUID value.
64 *
65 * @returns iprt status code.
66 * @param pUuid Where to store generated null uuid.
67 */
68RTR3DECL(int) RTUuidClear(PRTUUID pUuid)
69{
70 AssertReturn(pUuid, VERR_INVALID_PARAMETER);
71 pUuid->au64[0] = 0;
72 pUuid->au64[1] = 0;
73 return VINF_SUCCESS;
74}
75
76
77/**
78 * Checks if UUID is null.
79 *
80 * @returns true if UUID is null.
81 * @param pUuid uuid to check.
82 */
83RTR3DECL(int) RTUuidIsNull(PCRTUUID pUuid)
84{
85 AssertReturn(pUuid, VERR_INVALID_PARAMETER);
86 return !pUuid->au64[0]
87 && !pUuid->au64[1];
88}
89
90
91/**
92 * Compares two UUID values.
93 *
94 * @returns 0 if eq, < 0 or > 0.
95 * @param pUuid1 First value to compare.
96 * @param pUuid2 Second value to compare.
97 */
98RTR3DECL(int) RTUuidCompare(PCRTUUID pUuid1, PCRTUUID pUuid2)
99{
100 /*
101 * Special cases.
102 */
103 if (pUuid1 == pUuid2)
104 return 0;
105 if (!pUuid1)
106 return RTUuidIsNull(pUuid2) ? 0 : -1;
107 if (!pUuid2)
108 return RTUuidIsNull(pUuid1) ? 0 : 1;
109
110 /*
111 * Standard cases.
112 */
113 if (pUuid1->Gen.u32TimeLow != pUuid2->Gen.u32TimeLow)
114 return pUuid1->Gen.u32TimeLow < pUuid2->Gen.u32TimeLow ? -1 : 1;
115 if (pUuid1->Gen.u16TimeMid != pUuid2->Gen.u16TimeMid)
116 return pUuid1->Gen.u16TimeMid < pUuid2->Gen.u16TimeMid ? -1 : 1;
117 if (pUuid1->Gen.u16TimeHiAndVersion != pUuid2->Gen.u16TimeHiAndVersion)
118 return pUuid1->Gen.u16TimeHiAndVersion < pUuid2->Gen.u16TimeHiAndVersion ? -1 : 1;
119 if (pUuid1->Gen.u16ClockSeq != pUuid2->Gen.u16ClockSeq)
120 return pUuid1->Gen.u16ClockSeq < pUuid2->Gen.u16ClockSeq ? -1 : 1;
121 if (pUuid1->Gen.au8Node[0] != pUuid2->Gen.au8Node[0])
122 return pUuid1->Gen.au8Node[0] < pUuid2->Gen.au8Node[0] ? -1 : 1;
123 if (pUuid1->Gen.au8Node[1] != pUuid2->Gen.au8Node[1])
124 return pUuid1->Gen.au8Node[1] < pUuid2->Gen.au8Node[1] ? -1 : 1;
125 if (pUuid1->Gen.au8Node[2] != pUuid2->Gen.au8Node[2])
126 return pUuid1->Gen.au8Node[2] < pUuid2->Gen.au8Node[2] ? -1 : 1;
127 if (pUuid1->Gen.au8Node[3] != pUuid2->Gen.au8Node[3])
128 return pUuid1->Gen.au8Node[3] < pUuid2->Gen.au8Node[3] ? -1 : 1;
129 if (pUuid1->Gen.au8Node[4] != pUuid2->Gen.au8Node[4])
130 return pUuid1->Gen.au8Node[4] < pUuid2->Gen.au8Node[4] ? -1 : 1;
131 if (pUuid1->Gen.au8Node[5] != pUuid2->Gen.au8Node[5])
132 return pUuid1->Gen.au8Node[5] < pUuid2->Gen.au8Node[5] ? -1 : 1;
133 return 0;
134}
135
136
137/**
138 * Converts binary UUID to its string representation.
139 *
140 * @returns iprt status code.
141 * @param pUuid Uuid to convert.
142 * @param pszString Where to store result string.
143 * @param cchString pszString buffer length, must be >= RTUUID_STR_LENGTH.
144 */
145RTR3DECL(int) RTUuidToStr(PCRTUUID pUuid, char *pszString, unsigned cchString)
146{
147 /* validate parameters */
148 AssertReturn(pUuid, VERR_INVALID_PARAMETER);
149 AssertReturn(pszString, VERR_INVALID_PARAMETER);
150 AssertReturn(cchString >= RTUUID_STR_LENGTH, VERR_INVALID_PARAMETER);
151
152 /*
153 * RTStrPrintf(,,"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
154 * pUuid->Gen.u32TimeLow,
155 * pUuid->Gen.u16TimeMin,
156 * pUuid->Gen.u16TimeHiAndVersion,
157 * pUuid->Gen.u16ClockSeq & 0xff,
158 * pUuid->Gen.u16ClockSeq >> 8,
159 * pUuid->Gen.au8Node[0],
160 * pUuid->Gen.au8Node[1],
161 * pUuid->Gen.au8Node[2],
162 * pUuid->Gen.au8Node[3],
163 * pUuid->Gen.au8Node[4],
164 * pUuid->Gen.au8Node[5]);
165 */
166 static const char s_achDigits[17] = "0123456789abcdef";
167 uint32_t u32TimeLow = pUuid->Gen.u32TimeLow;
168 pszString[ 0] = s_achDigits[(u32TimeLow >> 28)/*& 0xf*/];
169 pszString[ 1] = s_achDigits[(u32TimeLow >> 24) & 0xf];
170 pszString[ 2] = s_achDigits[(u32TimeLow >> 20) & 0xf];
171 pszString[ 3] = s_achDigits[(u32TimeLow >> 16) & 0xf];
172 pszString[ 4] = s_achDigits[(u32TimeLow >> 12) & 0xf];
173 pszString[ 5] = s_achDigits[(u32TimeLow >> 8) & 0xf];
174 pszString[ 6] = s_achDigits[(u32TimeLow >> 4) & 0xf];
175 pszString[ 7] = s_achDigits[(u32TimeLow/*>>0*/)& 0xf];
176 pszString[ 8] = '-';
177 unsigned u = pUuid->Gen.u16TimeMid;
178 pszString[ 9] = s_achDigits[(u >> 12)/*& 0xf*/];
179 pszString[10] = s_achDigits[(u >> 8) & 0xf];
180 pszString[11] = s_achDigits[(u >> 4) & 0xf];
181 pszString[12] = s_achDigits[(u/*>>0*/)& 0xf];
182 pszString[13] = '-';
183 u = pUuid->Gen.u16TimeHiAndVersion;
184 pszString[14] = s_achDigits[(u >> 12)/*& 0xf*/];
185 pszString[15] = s_achDigits[(u >> 8) & 0xf];
186 pszString[16] = s_achDigits[(u >> 4) & 0xf];
187 pszString[17] = s_achDigits[(u/*>>0*/)& 0xf];
188 pszString[18] = '-';
189 u = pUuid->Gen.u16ClockSeq;
190 pszString[19] = s_achDigits[(u >> 4) & 0xf];
191 pszString[20] = s_achDigits[(u/*>>0*/)& 0xf];
192 pszString[21] = s_achDigits[(u >> 12)/*& 0xf*/];
193 pszString[22] = s_achDigits[(u >> 8) & 0xf];
194 pszString[23] = '-';
195 pszString[24] = s_achDigits[pUuid->Gen.au8Node[0] >> 4];
196 pszString[25] = s_achDigits[pUuid->Gen.au8Node[0] & 0xf];
197 pszString[26] = s_achDigits[pUuid->Gen.au8Node[1] >> 4];
198 pszString[27] = s_achDigits[pUuid->Gen.au8Node[1] & 0xf];
199 pszString[28] = s_achDigits[pUuid->Gen.au8Node[2] >> 4];
200 pszString[29] = s_achDigits[pUuid->Gen.au8Node[2] & 0xf];
201 pszString[30] = s_achDigits[pUuid->Gen.au8Node[3] >> 4];
202 pszString[31] = s_achDigits[pUuid->Gen.au8Node[3] & 0xf];
203 pszString[32] = s_achDigits[pUuid->Gen.au8Node[4] >> 4];
204 pszString[33] = s_achDigits[pUuid->Gen.au8Node[4] & 0xf];
205 pszString[34] = s_achDigits[pUuid->Gen.au8Node[5] >> 4];
206 pszString[35] = s_achDigits[pUuid->Gen.au8Node[5] & 0xf];
207 pszString[36] = '\0';
208
209 return VINF_SUCCESS;
210}
211
212
213/**
214 * Converts UUID from its string representation to binary format.
215 *
216 * @returns iprt status code.
217 * @param pUuid Where to store result Uuid.
218 * @param pszString String with UUID text data.
219 */
220RTR3DECL(int) RTUuidFromStr(PRTUUID pUuid, const char *pszString)
221{
222 /* 0xff if not a hex number, otherwise the value. (Assumes UTF-8 encoded strings.) */
223 static const uint8_t s_aDigits[256] =
224 {
225 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 0..0f */
226 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 10..1f */
227 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 20..2f */
228 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0xff,0xff, 0xff,0xff,0xff,0xff, /* 30..3f */
229 0xff,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 40..4f */
230 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 50..5f */
231 0xff,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 60..6f */
232 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 70..7f */
233 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 80..8f */
234 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 90..9f */
235 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* a0..af */
236 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* b0..bf */
237 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* c0..cf */
238 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* d0..df */
239 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* e0..ef */
240 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* f0..ff */
241 };
242
243 /*
244 * Validate parameters.
245 */
246 AssertReturn(pUuid, VERR_INVALID_PARAMETER);
247 AssertReturn(pszString, VERR_INVALID_PARAMETER);
248
249#define MY_ISXDIGIT(ch) (s_aDigits[(ch) & 0xff] != 0xff)
250 AssertReturn(MY_ISXDIGIT(pszString[ 0]), VERR_INVALID_UUID_FORMAT);
251 AssertReturn(MY_ISXDIGIT(pszString[ 1]), VERR_INVALID_UUID_FORMAT);
252 AssertReturn(MY_ISXDIGIT(pszString[ 2]), VERR_INVALID_UUID_FORMAT);
253 AssertReturn(MY_ISXDIGIT(pszString[ 3]), VERR_INVALID_UUID_FORMAT);
254 AssertReturn(MY_ISXDIGIT(pszString[ 4]), VERR_INVALID_UUID_FORMAT);
255 AssertReturn(MY_ISXDIGIT(pszString[ 5]), VERR_INVALID_UUID_FORMAT);
256 AssertReturn(MY_ISXDIGIT(pszString[ 6]), VERR_INVALID_UUID_FORMAT);
257 AssertReturn(MY_ISXDIGIT(pszString[ 7]), VERR_INVALID_UUID_FORMAT);
258 AssertReturn(pszString[ 8] == '-', VERR_INVALID_UUID_FORMAT);
259 AssertReturn(MY_ISXDIGIT(pszString[ 9]), VERR_INVALID_UUID_FORMAT);
260 AssertReturn(MY_ISXDIGIT(pszString[10]), VERR_INVALID_UUID_FORMAT);
261 AssertReturn(MY_ISXDIGIT(pszString[11]), VERR_INVALID_UUID_FORMAT);
262 AssertReturn(MY_ISXDIGIT(pszString[12]), VERR_INVALID_UUID_FORMAT);
263 AssertReturn(pszString[13] == '-', VERR_INVALID_UUID_FORMAT);
264 AssertReturn(MY_ISXDIGIT(pszString[14]), VERR_INVALID_UUID_FORMAT);
265 AssertReturn(MY_ISXDIGIT(pszString[15]), VERR_INVALID_UUID_FORMAT);
266 AssertReturn(MY_ISXDIGIT(pszString[16]), VERR_INVALID_UUID_FORMAT);
267 AssertReturn(MY_ISXDIGIT(pszString[17]), VERR_INVALID_UUID_FORMAT);
268 AssertReturn(pszString[18] == '-', VERR_INVALID_UUID_FORMAT);
269 AssertReturn(MY_ISXDIGIT(pszString[19]), VERR_INVALID_UUID_FORMAT);
270 AssertReturn(MY_ISXDIGIT(pszString[20]), VERR_INVALID_UUID_FORMAT);
271 AssertReturn(MY_ISXDIGIT(pszString[21]), VERR_INVALID_UUID_FORMAT);
272 AssertReturn(MY_ISXDIGIT(pszString[22]), VERR_INVALID_UUID_FORMAT);
273 AssertReturn(pszString[23] == '-', VERR_INVALID_UUID_FORMAT);
274 AssertReturn(MY_ISXDIGIT(pszString[24]), VERR_INVALID_UUID_FORMAT);
275 AssertReturn(MY_ISXDIGIT(pszString[25]), VERR_INVALID_UUID_FORMAT);
276 AssertReturn(MY_ISXDIGIT(pszString[26]), VERR_INVALID_UUID_FORMAT);
277 AssertReturn(MY_ISXDIGIT(pszString[27]), VERR_INVALID_UUID_FORMAT);
278 AssertReturn(MY_ISXDIGIT(pszString[28]), VERR_INVALID_UUID_FORMAT);
279 AssertReturn(MY_ISXDIGIT(pszString[29]), VERR_INVALID_UUID_FORMAT);
280 AssertReturn(MY_ISXDIGIT(pszString[30]), VERR_INVALID_UUID_FORMAT);
281 AssertReturn(MY_ISXDIGIT(pszString[31]), VERR_INVALID_UUID_FORMAT);
282 AssertReturn(MY_ISXDIGIT(pszString[32]), VERR_INVALID_UUID_FORMAT);
283 AssertReturn(MY_ISXDIGIT(pszString[33]), VERR_INVALID_UUID_FORMAT);
284 AssertReturn(MY_ISXDIGIT(pszString[34]), VERR_INVALID_UUID_FORMAT);
285 AssertReturn(MY_ISXDIGIT(pszString[35]), VERR_INVALID_UUID_FORMAT);
286 AssertReturn(!pszString[36], VERR_INVALID_UUID_FORMAT);
287#undef MY_ISXDIGIT
288
289 /*
290 * Inverse of RTUuidToStr (see above).
291 */
292#define MY_TONUM(ch) (s_aDigits[(ch) & 0xff])
293 pUuid->Gen.u32TimeLow = (uint32_t)MY_TONUM(pszString[ 0]) << 28
294 | (uint32_t)MY_TONUM(pszString[ 1]) << 24
295 | (uint32_t)MY_TONUM(pszString[ 2]) << 20
296 | (uint32_t)MY_TONUM(pszString[ 3]) << 16
297 | (uint32_t)MY_TONUM(pszString[ 4]) << 12
298 | (uint32_t)MY_TONUM(pszString[ 5]) << 8
299 | (uint32_t)MY_TONUM(pszString[ 6]) << 4
300 | (uint32_t)MY_TONUM(pszString[ 7]);
301 pUuid->Gen.u16TimeMid = (uint16_t)MY_TONUM(pszString[ 9]) << 12
302 | (uint16_t)MY_TONUM(pszString[10]) << 8
303 | (uint16_t)MY_TONUM(pszString[11]) << 4
304 | (uint16_t)MY_TONUM(pszString[12]);
305 pUuid->Gen.u16TimeHiAndVersion =
306 (uint16_t)MY_TONUM(pszString[14]) << 12
307 | (uint16_t)MY_TONUM(pszString[15]) << 8
308 | (uint16_t)MY_TONUM(pszString[16]) << 4
309 | (uint16_t)MY_TONUM(pszString[17]);
310 pUuid->Gen.u16ClockSeq =(uint16_t)MY_TONUM(pszString[19]) << 4
311 | (uint16_t)MY_TONUM(pszString[20])
312 | (uint16_t)MY_TONUM(pszString[21]) << 12
313 | (uint16_t)MY_TONUM(pszString[22]) << 8;
314 pUuid->Gen.au8Node[0] = (uint8_t)MY_TONUM(pszString[24]) << 4
315 | (uint8_t)MY_TONUM(pszString[25]);
316 pUuid->Gen.au8Node[1] = (uint8_t)MY_TONUM(pszString[26]) << 4
317 | (uint8_t)MY_TONUM(pszString[27]);
318 pUuid->Gen.au8Node[2] = (uint8_t)MY_TONUM(pszString[28]) << 4
319 | (uint8_t)MY_TONUM(pszString[29]);
320 pUuid->Gen.au8Node[3] = (uint8_t)MY_TONUM(pszString[30]) << 4
321 | (uint8_t)MY_TONUM(pszString[31]);
322 pUuid->Gen.au8Node[4] = (uint8_t)MY_TONUM(pszString[32]) << 4
323 | (uint8_t)MY_TONUM(pszString[33]);
324 pUuid->Gen.au8Node[5] = (uint8_t)MY_TONUM(pszString[34]) << 4
325 | (uint8_t)MY_TONUM(pszString[35]);
326#undef MY_TONUM
327 return VINF_SUCCESS;
328}
329
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