[4750] | 1 | /* $Id: uuid-generic.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
[8245] | 3 | * IPRT - UUID, Generic.
|
---|
[4750] | 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
---|
[4071] | 8 | *
|
---|
[96407] | 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
[5999] | 11 | *
|
---|
[96407] | 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
[5999] | 25 | * The contents of this file may alternatively be used under the terms
|
---|
| 26 | * of the Common Development and Distribution License Version 1.0
|
---|
[96407] | 27 | * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
|
---|
| 28 | * in the VirtualBox distribution, in which case the provisions of the
|
---|
[5999] | 29 | * CDDL are applicable instead of those of the GPL.
|
---|
| 30 | *
|
---|
| 31 | * You may elect to license modified versions of this file under the
|
---|
| 32 | * terms and conditions of either the GPL or the CDDL or both.
|
---|
[96407] | 33 | *
|
---|
| 34 | * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
|
---|
[4750] | 35 | */
|
---|
| 36 |
|
---|
| 37 |
|
---|
[57358] | 38 | /*********************************************************************************************************************************
|
---|
| 39 | * Header Files *
|
---|
| 40 | *********************************************************************************************************************************/
|
---|
[4750] | 41 | #include <iprt/uuid.h>
|
---|
[21337] | 42 | #include "internal/iprt.h"
|
---|
| 43 |
|
---|
[4750] | 44 | #include <iprt/assert.h>
|
---|
| 45 | #include <iprt/err.h>
|
---|
[40988] | 46 | #include <iprt/asm.h>
|
---|
[4750] | 47 |
|
---|
| 48 |
|
---|
[57358] | 49 | /*********************************************************************************************************************************
|
---|
| 50 | * Global Variables *
|
---|
| 51 | *********************************************************************************************************************************/
|
---|
[19198] | 52 | /** Conversion table used by the conversion functions.
|
---|
| 53 | * 0xff if not a hex number, otherwise the value. */
|
---|
| 54 | static const uint8_t g_au8Digits[256] =
|
---|
| 55 | {
|
---|
| 56 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 0..0f */
|
---|
| 57 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 10..1f */
|
---|
| 58 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 20..2f */
|
---|
| 59 | 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0xff,0xff, 0xff,0xff,0xff,0xff, /* 30..3f */
|
---|
| 60 | 0xff,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 40..4f */
|
---|
| 61 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 50..5f */
|
---|
| 62 | 0xff,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 60..6f */
|
---|
| 63 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 70..7f */
|
---|
| 64 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 80..8f */
|
---|
| 65 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* 90..9f */
|
---|
| 66 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* a0..af */
|
---|
| 67 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* b0..bf */
|
---|
| 68 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* c0..cf */
|
---|
| 69 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* d0..df */
|
---|
| 70 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* e0..ef */
|
---|
| 71 | 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, /* f0..ff */
|
---|
| 72 | };
|
---|
| 73 | /** Conversion to string. */
|
---|
| 74 | static const char g_achDigits[17] = "0123456789abcdef";
|
---|
| 75 |
|
---|
| 76 |
|
---|
| 77 |
|
---|
[11413] | 78 | /* WARNING: This implementation ASSUMES little endian. Does not work on big endian! */
|
---|
[4750] | 79 |
|
---|
[11413] | 80 | /* Remember, the time fields in the UUID must be little endian. */
|
---|
[4750] | 81 |
|
---|
[11413] | 82 |
|
---|
[4750] | 83 | RTDECL(int) RTUuidClear(PRTUUID pUuid)
|
---|
| 84 | {
|
---|
[9738] | 85 | AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
|
---|
[4750] | 86 | pUuid->au64[0] = 0;
|
---|
| 87 | pUuid->au64[1] = 0;
|
---|
| 88 | return VINF_SUCCESS;
|
---|
| 89 | }
|
---|
[21337] | 90 | RT_EXPORT_SYMBOL(RTUuidClear);
|
---|
[4750] | 91 |
|
---|
| 92 |
|
---|
[9738] | 93 | RTDECL(bool) RTUuidIsNull(PCRTUUID pUuid)
|
---|
[4750] | 94 | {
|
---|
[14067] | 95 | AssertPtrReturn(pUuid, true);
|
---|
[4750] | 96 | return !pUuid->au64[0]
|
---|
| 97 | && !pUuid->au64[1];
|
---|
| 98 | }
|
---|
[21337] | 99 | RT_EXPORT_SYMBOL(RTUuidIsNull);
|
---|
[4750] | 100 |
|
---|
| 101 |
|
---|
| 102 | RTDECL(int) RTUuidCompare(PCRTUUID pUuid1, PCRTUUID pUuid2)
|
---|
| 103 | {
|
---|
| 104 | /*
|
---|
| 105 | * Special cases.
|
---|
| 106 | */
|
---|
| 107 | if (pUuid1 == pUuid2)
|
---|
| 108 | return 0;
|
---|
| 109 | if (!pUuid1)
|
---|
| 110 | return RTUuidIsNull(pUuid2) ? 0 : -1;
|
---|
| 111 | if (!pUuid2)
|
---|
| 112 | return RTUuidIsNull(pUuid1) ? 0 : 1;
|
---|
[9743] | 113 | AssertPtrReturn(pUuid1, -1);
|
---|
| 114 | AssertPtrReturn(pUuid2, 1);
|
---|
[4750] | 115 |
|
---|
| 116 | /*
|
---|
| 117 | * Standard cases.
|
---|
| 118 | */
|
---|
| 119 | if (pUuid1->Gen.u32TimeLow != pUuid2->Gen.u32TimeLow)
|
---|
| 120 | return pUuid1->Gen.u32TimeLow < pUuid2->Gen.u32TimeLow ? -1 : 1;
|
---|
| 121 | if (pUuid1->Gen.u16TimeMid != pUuid2->Gen.u16TimeMid)
|
---|
| 122 | return pUuid1->Gen.u16TimeMid < pUuid2->Gen.u16TimeMid ? -1 : 1;
|
---|
| 123 | if (pUuid1->Gen.u16TimeHiAndVersion != pUuid2->Gen.u16TimeHiAndVersion)
|
---|
| 124 | return pUuid1->Gen.u16TimeHiAndVersion < pUuid2->Gen.u16TimeHiAndVersion ? -1 : 1;
|
---|
[11413] | 125 | if (pUuid1->Gen.u8ClockSeqHiAndReserved != pUuid2->Gen.u8ClockSeqHiAndReserved)
|
---|
| 126 | return pUuid1->Gen.u8ClockSeqHiAndReserved < pUuid2->Gen.u8ClockSeqHiAndReserved ? -1 : 1;
|
---|
| 127 | if (pUuid1->Gen.u8ClockSeqLow != pUuid2->Gen.u8ClockSeqLow)
|
---|
| 128 | return pUuid1->Gen.u8ClockSeqLow < pUuid2->Gen.u8ClockSeqLow ? -1 : 1;
|
---|
[4750] | 129 | if (pUuid1->Gen.au8Node[0] != pUuid2->Gen.au8Node[0])
|
---|
| 130 | return pUuid1->Gen.au8Node[0] < pUuid2->Gen.au8Node[0] ? -1 : 1;
|
---|
| 131 | if (pUuid1->Gen.au8Node[1] != pUuid2->Gen.au8Node[1])
|
---|
| 132 | return pUuid1->Gen.au8Node[1] < pUuid2->Gen.au8Node[1] ? -1 : 1;
|
---|
| 133 | if (pUuid1->Gen.au8Node[2] != pUuid2->Gen.au8Node[2])
|
---|
| 134 | return pUuid1->Gen.au8Node[2] < pUuid2->Gen.au8Node[2] ? -1 : 1;
|
---|
| 135 | if (pUuid1->Gen.au8Node[3] != pUuid2->Gen.au8Node[3])
|
---|
| 136 | return pUuid1->Gen.au8Node[3] < pUuid2->Gen.au8Node[3] ? -1 : 1;
|
---|
| 137 | if (pUuid1->Gen.au8Node[4] != pUuid2->Gen.au8Node[4])
|
---|
| 138 | return pUuid1->Gen.au8Node[4] < pUuid2->Gen.au8Node[4] ? -1 : 1;
|
---|
| 139 | if (pUuid1->Gen.au8Node[5] != pUuid2->Gen.au8Node[5])
|
---|
| 140 | return pUuid1->Gen.au8Node[5] < pUuid2->Gen.au8Node[5] ? -1 : 1;
|
---|
| 141 | return 0;
|
---|
| 142 | }
|
---|
[21337] | 143 | RT_EXPORT_SYMBOL(RTUuidCompare);
|
---|
[4750] | 144 |
|
---|
| 145 |
|
---|
[25961] | 146 | RTDECL(int) RTUuidCompareStr(PCRTUUID pUuid1, const char *pszString2)
|
---|
[4750] | 147 | {
|
---|
[13977] | 148 | RTUUID Uuid2;
|
---|
| 149 | int rc;
|
---|
| 150 |
|
---|
[9738] | 151 | /* check params */
|
---|
| 152 | AssertPtrReturn(pUuid1, -1);
|
---|
[25961] | 153 | AssertPtrReturn(pszString2, 1);
|
---|
[9738] | 154 |
|
---|
| 155 | /*
|
---|
| 156 | * Try convert the string to a UUID and then compare the two.
|
---|
| 157 | */
|
---|
[25961] | 158 | rc = RTUuidFromStr(&Uuid2, pszString2);
|
---|
[9738] | 159 | AssertRCReturn(rc, 1);
|
---|
| 160 |
|
---|
| 161 | return RTUuidCompare(pUuid1, &Uuid2);
|
---|
| 162 | }
|
---|
[21337] | 163 | RT_EXPORT_SYMBOL(RTUuidCompareStr);
|
---|
[9738] | 164 |
|
---|
| 165 |
|
---|
[25961] | 166 | RTDECL(int) RTUuidCompare2Strs(const char *pszString1, const char *pszString2)
|
---|
| 167 | {
|
---|
| 168 | RTUUID Uuid1;
|
---|
| 169 | RTUUID Uuid2;
|
---|
| 170 | int rc;
|
---|
| 171 |
|
---|
| 172 | /* check params */
|
---|
| 173 | AssertPtrReturn(pszString1, -1);
|
---|
| 174 | AssertPtrReturn(pszString2, 1);
|
---|
| 175 |
|
---|
| 176 | /*
|
---|
| 177 | * Try convert the strings to UUIDs and then compare them.
|
---|
| 178 | */
|
---|
| 179 | rc = RTUuidFromStr(&Uuid1, pszString1);
|
---|
| 180 | AssertRCReturn(rc, -1);
|
---|
| 181 |
|
---|
| 182 | rc = RTUuidFromStr(&Uuid2, pszString2);
|
---|
| 183 | AssertRCReturn(rc, 1);
|
---|
| 184 |
|
---|
| 185 | return RTUuidCompare(&Uuid1, &Uuid2);
|
---|
| 186 | }
|
---|
| 187 | RT_EXPORT_SYMBOL(RTUuidCompare2Strs);
|
---|
| 188 |
|
---|
| 189 |
|
---|
[9738] | 190 | RTDECL(int) RTUuidToStr(PCRTUUID pUuid, char *pszString, size_t cchString)
|
---|
| 191 | {
|
---|
[13977] | 192 | uint32_t u32TimeLow;
|
---|
| 193 | unsigned u;
|
---|
| 194 |
|
---|
[4750] | 195 | /* validate parameters */
|
---|
[9738] | 196 | AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
|
---|
| 197 | AssertPtrReturn(pszString, VERR_INVALID_PARAMETER);
|
---|
[4750] | 198 | AssertReturn(cchString >= RTUUID_STR_LENGTH, VERR_INVALID_PARAMETER);
|
---|
| 199 |
|
---|
| 200 | /*
|
---|
| 201 | * RTStrPrintf(,,"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
---|
| 202 | * pUuid->Gen.u32TimeLow,
|
---|
| 203 | * pUuid->Gen.u16TimeMin,
|
---|
| 204 | * pUuid->Gen.u16TimeHiAndVersion,
|
---|
| 205 | * pUuid->Gen.u16ClockSeq & 0xff,
|
---|
| 206 | * pUuid->Gen.u16ClockSeq >> 8,
|
---|
| 207 | * pUuid->Gen.au8Node[0],
|
---|
| 208 | * pUuid->Gen.au8Node[1],
|
---|
| 209 | * pUuid->Gen.au8Node[2],
|
---|
| 210 | * pUuid->Gen.au8Node[3],
|
---|
| 211 | * pUuid->Gen.au8Node[4],
|
---|
| 212 | * pUuid->Gen.au8Node[5]);
|
---|
| 213 | */
|
---|
[40988] | 214 | u32TimeLow = RT_H2LE_U32(pUuid->Gen.u32TimeLow);
|
---|
[19198] | 215 | pszString[ 0] = g_achDigits[(u32TimeLow >> 28)/*& 0xf*/];
|
---|
| 216 | pszString[ 1] = g_achDigits[(u32TimeLow >> 24) & 0xf];
|
---|
| 217 | pszString[ 2] = g_achDigits[(u32TimeLow >> 20) & 0xf];
|
---|
| 218 | pszString[ 3] = g_achDigits[(u32TimeLow >> 16) & 0xf];
|
---|
| 219 | pszString[ 4] = g_achDigits[(u32TimeLow >> 12) & 0xf];
|
---|
| 220 | pszString[ 5] = g_achDigits[(u32TimeLow >> 8) & 0xf];
|
---|
| 221 | pszString[ 6] = g_achDigits[(u32TimeLow >> 4) & 0xf];
|
---|
| 222 | pszString[ 7] = g_achDigits[(u32TimeLow/*>>0*/)& 0xf];
|
---|
[4750] | 223 | pszString[ 8] = '-';
|
---|
[40988] | 224 | u = RT_H2LE_U16(pUuid->Gen.u16TimeMid);
|
---|
[19198] | 225 | pszString[ 9] = g_achDigits[(u >> 12)/*& 0xf*/];
|
---|
| 226 | pszString[10] = g_achDigits[(u >> 8) & 0xf];
|
---|
| 227 | pszString[11] = g_achDigits[(u >> 4) & 0xf];
|
---|
| 228 | pszString[12] = g_achDigits[(u/*>>0*/)& 0xf];
|
---|
[4750] | 229 | pszString[13] = '-';
|
---|
[40988] | 230 | u = RT_H2LE_U16(pUuid->Gen.u16TimeHiAndVersion);
|
---|
[19198] | 231 | pszString[14] = g_achDigits[(u >> 12)/*& 0xf*/];
|
---|
| 232 | pszString[15] = g_achDigits[(u >> 8) & 0xf];
|
---|
| 233 | pszString[16] = g_achDigits[(u >> 4) & 0xf];
|
---|
| 234 | pszString[17] = g_achDigits[(u/*>>0*/)& 0xf];
|
---|
[4750] | 235 | pszString[18] = '-';
|
---|
[19198] | 236 | pszString[19] = g_achDigits[pUuid->Gen.u8ClockSeqHiAndReserved >> 4];
|
---|
| 237 | pszString[20] = g_achDigits[pUuid->Gen.u8ClockSeqHiAndReserved & 0xf];
|
---|
| 238 | pszString[21] = g_achDigits[pUuid->Gen.u8ClockSeqLow >> 4];
|
---|
| 239 | pszString[22] = g_achDigits[pUuid->Gen.u8ClockSeqLow & 0xf];
|
---|
[4750] | 240 | pszString[23] = '-';
|
---|
[19198] | 241 | pszString[24] = g_achDigits[pUuid->Gen.au8Node[0] >> 4];
|
---|
| 242 | pszString[25] = g_achDigits[pUuid->Gen.au8Node[0] & 0xf];
|
---|
| 243 | pszString[26] = g_achDigits[pUuid->Gen.au8Node[1] >> 4];
|
---|
| 244 | pszString[27] = g_achDigits[pUuid->Gen.au8Node[1] & 0xf];
|
---|
| 245 | pszString[28] = g_achDigits[pUuid->Gen.au8Node[2] >> 4];
|
---|
| 246 | pszString[29] = g_achDigits[pUuid->Gen.au8Node[2] & 0xf];
|
---|
| 247 | pszString[30] = g_achDigits[pUuid->Gen.au8Node[3] >> 4];
|
---|
| 248 | pszString[31] = g_achDigits[pUuid->Gen.au8Node[3] & 0xf];
|
---|
| 249 | pszString[32] = g_achDigits[pUuid->Gen.au8Node[4] >> 4];
|
---|
| 250 | pszString[33] = g_achDigits[pUuid->Gen.au8Node[4] & 0xf];
|
---|
| 251 | pszString[34] = g_achDigits[pUuid->Gen.au8Node[5] >> 4];
|
---|
| 252 | pszString[35] = g_achDigits[pUuid->Gen.au8Node[5] & 0xf];
|
---|
[4750] | 253 | pszString[36] = '\0';
|
---|
| 254 |
|
---|
| 255 | return VINF_SUCCESS;
|
---|
| 256 | }
|
---|
[21337] | 257 | RT_EXPORT_SYMBOL(RTUuidToStr);
|
---|
[4750] | 258 |
|
---|
| 259 |
|
---|
| 260 | RTDECL(int) RTUuidFromStr(PRTUUID pUuid, const char *pszString)
|
---|
| 261 | {
|
---|
[32988] | 262 | bool fHaveBraces;
|
---|
| 263 |
|
---|
[4750] | 264 | /*
|
---|
| 265 | * Validate parameters.
|
---|
| 266 | */
|
---|
[9738] | 267 | AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
|
---|
| 268 | AssertPtrReturn(pszString, VERR_INVALID_PARAMETER);
|
---|
[4750] | 269 |
|
---|
[32994] | 270 | fHaveBraces = pszString[0] == '{';
|
---|
| 271 | pszString += fHaveBraces;
|
---|
[32979] | 272 |
|
---|
[4750] | 273 | #define MY_CHECK(expr) do { if (RT_UNLIKELY(!(expr))) return VERR_INVALID_UUID_FORMAT; } while (0)
|
---|
[19198] | 274 | #define MY_ISXDIGIT(ch) (g_au8Digits[(ch) & 0xff] != 0xff)
|
---|
[4750] | 275 | MY_CHECK(MY_ISXDIGIT(pszString[ 0]));
|
---|
| 276 | MY_CHECK(MY_ISXDIGIT(pszString[ 1]));
|
---|
| 277 | MY_CHECK(MY_ISXDIGIT(pszString[ 2]));
|
---|
| 278 | MY_CHECK(MY_ISXDIGIT(pszString[ 3]));
|
---|
| 279 | MY_CHECK(MY_ISXDIGIT(pszString[ 4]));
|
---|
| 280 | MY_CHECK(MY_ISXDIGIT(pszString[ 5]));
|
---|
| 281 | MY_CHECK(MY_ISXDIGIT(pszString[ 6]));
|
---|
| 282 | MY_CHECK(MY_ISXDIGIT(pszString[ 7]));
|
---|
| 283 | MY_CHECK(pszString[ 8] == '-');
|
---|
| 284 | MY_CHECK(MY_ISXDIGIT(pszString[ 9]));
|
---|
| 285 | MY_CHECK(MY_ISXDIGIT(pszString[10]));
|
---|
| 286 | MY_CHECK(MY_ISXDIGIT(pszString[11]));
|
---|
| 287 | MY_CHECK(MY_ISXDIGIT(pszString[12]));
|
---|
| 288 | MY_CHECK(pszString[13] == '-');
|
---|
| 289 | MY_CHECK(MY_ISXDIGIT(pszString[14]));
|
---|
| 290 | MY_CHECK(MY_ISXDIGIT(pszString[15]));
|
---|
| 291 | MY_CHECK(MY_ISXDIGIT(pszString[16]));
|
---|
| 292 | MY_CHECK(MY_ISXDIGIT(pszString[17]));
|
---|
| 293 | MY_CHECK(pszString[18] == '-');
|
---|
| 294 | MY_CHECK(MY_ISXDIGIT(pszString[19]));
|
---|
| 295 | MY_CHECK(MY_ISXDIGIT(pszString[20]));
|
---|
| 296 | MY_CHECK(MY_ISXDIGIT(pszString[21]));
|
---|
| 297 | MY_CHECK(MY_ISXDIGIT(pszString[22]));
|
---|
| 298 | MY_CHECK(pszString[23] == '-');
|
---|
| 299 | MY_CHECK(MY_ISXDIGIT(pszString[24]));
|
---|
| 300 | MY_CHECK(MY_ISXDIGIT(pszString[25]));
|
---|
| 301 | MY_CHECK(MY_ISXDIGIT(pszString[26]));
|
---|
| 302 | MY_CHECK(MY_ISXDIGIT(pszString[27]));
|
---|
| 303 | MY_CHECK(MY_ISXDIGIT(pszString[28]));
|
---|
| 304 | MY_CHECK(MY_ISXDIGIT(pszString[29]));
|
---|
| 305 | MY_CHECK(MY_ISXDIGIT(pszString[30]));
|
---|
| 306 | MY_CHECK(MY_ISXDIGIT(pszString[31]));
|
---|
| 307 | MY_CHECK(MY_ISXDIGIT(pszString[32]));
|
---|
| 308 | MY_CHECK(MY_ISXDIGIT(pszString[33]));
|
---|
| 309 | MY_CHECK(MY_ISXDIGIT(pszString[34]));
|
---|
| 310 | MY_CHECK(MY_ISXDIGIT(pszString[35]));
|
---|
[32994] | 311 | if (fHaveBraces)
|
---|
| 312 | MY_CHECK(pszString[36] == '}');
|
---|
| 313 | MY_CHECK(!pszString[36 + fHaveBraces]);
|
---|
[4750] | 314 | #undef MY_ISXDIGIT
|
---|
| 315 | #undef MY_CHECK
|
---|
| 316 |
|
---|
| 317 | /*
|
---|
| 318 | * Inverse of RTUuidToStr (see above).
|
---|
| 319 | */
|
---|
[19198] | 320 | #define MY_TONUM(ch) (g_au8Digits[(ch) & 0xff])
|
---|
[40988] | 321 | pUuid->Gen.u32TimeLow = RT_LE2H_U32((uint32_t)MY_TONUM(pszString[ 0]) << 28
|
---|
[4750] | 322 | | (uint32_t)MY_TONUM(pszString[ 1]) << 24
|
---|
| 323 | | (uint32_t)MY_TONUM(pszString[ 2]) << 20
|
---|
| 324 | | (uint32_t)MY_TONUM(pszString[ 3]) << 16
|
---|
| 325 | | (uint32_t)MY_TONUM(pszString[ 4]) << 12
|
---|
| 326 | | (uint32_t)MY_TONUM(pszString[ 5]) << 8
|
---|
| 327 | | (uint32_t)MY_TONUM(pszString[ 6]) << 4
|
---|
[40988] | 328 | | (uint32_t)MY_TONUM(pszString[ 7]));
|
---|
| 329 | pUuid->Gen.u16TimeMid = RT_LE2H_U16((uint16_t)MY_TONUM(pszString[ 9]) << 12
|
---|
[4750] | 330 | | (uint16_t)MY_TONUM(pszString[10]) << 8
|
---|
| 331 | | (uint16_t)MY_TONUM(pszString[11]) << 4
|
---|
[40988] | 332 | | (uint16_t)MY_TONUM(pszString[12]));
|
---|
| 333 | pUuid->Gen.u16TimeHiAndVersion = RT_LE2H_U16(
|
---|
[4750] | 334 | (uint16_t)MY_TONUM(pszString[14]) << 12
|
---|
| 335 | | (uint16_t)MY_TONUM(pszString[15]) << 8
|
---|
| 336 | | (uint16_t)MY_TONUM(pszString[16]) << 4
|
---|
[40988] | 337 | | (uint16_t)MY_TONUM(pszString[17]));
|
---|
[11413] | 338 | pUuid->Gen.u8ClockSeqHiAndReserved =
|
---|
| 339 | (uint16_t)MY_TONUM(pszString[19]) << 4
|
---|
| 340 | | (uint16_t)MY_TONUM(pszString[20]);
|
---|
| 341 | pUuid->Gen.u8ClockSeqLow =
|
---|
| 342 | (uint16_t)MY_TONUM(pszString[21]) << 4
|
---|
| 343 | | (uint16_t)MY_TONUM(pszString[22]);
|
---|
[4750] | 344 | pUuid->Gen.au8Node[0] = (uint8_t)MY_TONUM(pszString[24]) << 4
|
---|
| 345 | | (uint8_t)MY_TONUM(pszString[25]);
|
---|
| 346 | pUuid->Gen.au8Node[1] = (uint8_t)MY_TONUM(pszString[26]) << 4
|
---|
| 347 | | (uint8_t)MY_TONUM(pszString[27]);
|
---|
| 348 | pUuid->Gen.au8Node[2] = (uint8_t)MY_TONUM(pszString[28]) << 4
|
---|
| 349 | | (uint8_t)MY_TONUM(pszString[29]);
|
---|
| 350 | pUuid->Gen.au8Node[3] = (uint8_t)MY_TONUM(pszString[30]) << 4
|
---|
| 351 | | (uint8_t)MY_TONUM(pszString[31]);
|
---|
| 352 | pUuid->Gen.au8Node[4] = (uint8_t)MY_TONUM(pszString[32]) << 4
|
---|
| 353 | | (uint8_t)MY_TONUM(pszString[33]);
|
---|
| 354 | pUuid->Gen.au8Node[5] = (uint8_t)MY_TONUM(pszString[34]) << 4
|
---|
| 355 | | (uint8_t)MY_TONUM(pszString[35]);
|
---|
| 356 | #undef MY_TONUM
|
---|
| 357 | return VINF_SUCCESS;
|
---|
| 358 | }
|
---|
[21337] | 359 | RT_EXPORT_SYMBOL(RTUuidFromStr);
|
---|
[4750] | 360 |
|
---|
[19198] | 361 |
|
---|
| 362 | RTDECL(int) RTUuidToUtf16(PCRTUUID pUuid, PRTUTF16 pwszString, size_t cwcString)
|
---|
| 363 | {
|
---|
| 364 | uint32_t u32TimeLow;
|
---|
| 365 | unsigned u;
|
---|
| 366 |
|
---|
| 367 | /* validate parameters */
|
---|
| 368 | AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
|
---|
| 369 | AssertPtrReturn(pwszString, VERR_INVALID_PARAMETER);
|
---|
| 370 | AssertReturn(cwcString >= RTUUID_STR_LENGTH, VERR_INVALID_PARAMETER);
|
---|
| 371 |
|
---|
| 372 | /*
|
---|
| 373 | * RTStrPrintf(,,"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
---|
| 374 | * pUuid->Gen.u32TimeLow,
|
---|
| 375 | * pUuid->Gen.u16TimeMin,
|
---|
| 376 | * pUuid->Gen.u16TimeHiAndVersion,
|
---|
| 377 | * pUuid->Gen.u16ClockSeq & 0xff,
|
---|
| 378 | * pUuid->Gen.u16ClockSeq >> 8,
|
---|
| 379 | * pUuid->Gen.au8Node[0],
|
---|
| 380 | * pUuid->Gen.au8Node[1],
|
---|
| 381 | * pUuid->Gen.au8Node[2],
|
---|
| 382 | * pUuid->Gen.au8Node[3],
|
---|
| 383 | * pUuid->Gen.au8Node[4],
|
---|
| 384 | * pUuid->Gen.au8Node[5]);
|
---|
| 385 | */
|
---|
[40988] | 386 | u32TimeLow = RT_H2LE_U32(pUuid->Gen.u32TimeLow);
|
---|
[19198] | 387 | pwszString[ 0] = g_achDigits[(u32TimeLow >> 28)/*& 0xf*/];
|
---|
| 388 | pwszString[ 1] = g_achDigits[(u32TimeLow >> 24) & 0xf];
|
---|
| 389 | pwszString[ 2] = g_achDigits[(u32TimeLow >> 20) & 0xf];
|
---|
| 390 | pwszString[ 3] = g_achDigits[(u32TimeLow >> 16) & 0xf];
|
---|
| 391 | pwszString[ 4] = g_achDigits[(u32TimeLow >> 12) & 0xf];
|
---|
| 392 | pwszString[ 5] = g_achDigits[(u32TimeLow >> 8) & 0xf];
|
---|
| 393 | pwszString[ 6] = g_achDigits[(u32TimeLow >> 4) & 0xf];
|
---|
| 394 | pwszString[ 7] = g_achDigits[(u32TimeLow/*>>0*/)& 0xf];
|
---|
| 395 | pwszString[ 8] = '-';
|
---|
[40988] | 396 | u = RT_H2LE_U16(pUuid->Gen.u16TimeMid);
|
---|
[19198] | 397 | pwszString[ 9] = g_achDigits[(u >> 12)/*& 0xf*/];
|
---|
| 398 | pwszString[10] = g_achDigits[(u >> 8) & 0xf];
|
---|
| 399 | pwszString[11] = g_achDigits[(u >> 4) & 0xf];
|
---|
| 400 | pwszString[12] = g_achDigits[(u/*>>0*/)& 0xf];
|
---|
| 401 | pwszString[13] = '-';
|
---|
[40988] | 402 | u = RT_H2LE_U16(pUuid->Gen.u16TimeHiAndVersion);
|
---|
[19198] | 403 | pwszString[14] = g_achDigits[(u >> 12)/*& 0xf*/];
|
---|
| 404 | pwszString[15] = g_achDigits[(u >> 8) & 0xf];
|
---|
| 405 | pwszString[16] = g_achDigits[(u >> 4) & 0xf];
|
---|
| 406 | pwszString[17] = g_achDigits[(u/*>>0*/)& 0xf];
|
---|
| 407 | pwszString[18] = '-';
|
---|
| 408 | pwszString[19] = g_achDigits[pUuid->Gen.u8ClockSeqHiAndReserved >> 4];
|
---|
| 409 | pwszString[20] = g_achDigits[pUuid->Gen.u8ClockSeqHiAndReserved & 0xf];
|
---|
| 410 | pwszString[21] = g_achDigits[pUuid->Gen.u8ClockSeqLow >> 4];
|
---|
| 411 | pwszString[22] = g_achDigits[pUuid->Gen.u8ClockSeqLow & 0xf];
|
---|
| 412 | pwszString[23] = '-';
|
---|
| 413 | pwszString[24] = g_achDigits[pUuid->Gen.au8Node[0] >> 4];
|
---|
| 414 | pwszString[25] = g_achDigits[pUuid->Gen.au8Node[0] & 0xf];
|
---|
| 415 | pwszString[26] = g_achDigits[pUuid->Gen.au8Node[1] >> 4];
|
---|
| 416 | pwszString[27] = g_achDigits[pUuid->Gen.au8Node[1] & 0xf];
|
---|
| 417 | pwszString[28] = g_achDigits[pUuid->Gen.au8Node[2] >> 4];
|
---|
| 418 | pwszString[29] = g_achDigits[pUuid->Gen.au8Node[2] & 0xf];
|
---|
| 419 | pwszString[30] = g_achDigits[pUuid->Gen.au8Node[3] >> 4];
|
---|
| 420 | pwszString[31] = g_achDigits[pUuid->Gen.au8Node[3] & 0xf];
|
---|
| 421 | pwszString[32] = g_achDigits[pUuid->Gen.au8Node[4] >> 4];
|
---|
| 422 | pwszString[33] = g_achDigits[pUuid->Gen.au8Node[4] & 0xf];
|
---|
| 423 | pwszString[34] = g_achDigits[pUuid->Gen.au8Node[5] >> 4];
|
---|
| 424 | pwszString[35] = g_achDigits[pUuid->Gen.au8Node[5] & 0xf];
|
---|
| 425 | pwszString[36] = '\0';
|
---|
| 426 |
|
---|
| 427 | return VINF_SUCCESS;
|
---|
| 428 | }
|
---|
[21337] | 429 | RT_EXPORT_SYMBOL(RTUuidToUtf16);
|
---|
[19198] | 430 |
|
---|
| 431 |
|
---|
| 432 | RTDECL(int) RTUuidFromUtf16(PRTUUID pUuid, PCRTUTF16 pwszString)
|
---|
| 433 | {
|
---|
[32988] | 434 | bool fHaveBraces;
|
---|
[19198] | 435 |
|
---|
| 436 | /*
|
---|
| 437 | * Validate parameters.
|
---|
| 438 | */
|
---|
| 439 | AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER);
|
---|
| 440 | AssertPtrReturn(pwszString, VERR_INVALID_PARAMETER);
|
---|
| 441 |
|
---|
[32995] | 442 | fHaveBraces = pwszString[0] == '{';
|
---|
| 443 | pwszString += fHaveBraces;
|
---|
[32979] | 444 |
|
---|
[19198] | 445 | #define MY_CHECK(expr) do { if (RT_UNLIKELY(!(expr))) return VERR_INVALID_UUID_FORMAT; } while (0)
|
---|
| 446 | #define MY_ISXDIGIT(ch) (!((ch) & 0xff00) && g_au8Digits[(ch) & 0xff] != 0xff)
|
---|
| 447 | MY_CHECK(MY_ISXDIGIT(pwszString[ 0]));
|
---|
| 448 | MY_CHECK(MY_ISXDIGIT(pwszString[ 1]));
|
---|
| 449 | MY_CHECK(MY_ISXDIGIT(pwszString[ 2]));
|
---|
| 450 | MY_CHECK(MY_ISXDIGIT(pwszString[ 3]));
|
---|
| 451 | MY_CHECK(MY_ISXDIGIT(pwszString[ 4]));
|
---|
| 452 | MY_CHECK(MY_ISXDIGIT(pwszString[ 5]));
|
---|
| 453 | MY_CHECK(MY_ISXDIGIT(pwszString[ 6]));
|
---|
| 454 | MY_CHECK(MY_ISXDIGIT(pwszString[ 7]));
|
---|
| 455 | MY_CHECK(pwszString[ 8] == '-');
|
---|
| 456 | MY_CHECK(MY_ISXDIGIT(pwszString[ 9]));
|
---|
| 457 | MY_CHECK(MY_ISXDIGIT(pwszString[10]));
|
---|
| 458 | MY_CHECK(MY_ISXDIGIT(pwszString[11]));
|
---|
| 459 | MY_CHECK(MY_ISXDIGIT(pwszString[12]));
|
---|
| 460 | MY_CHECK(pwszString[13] == '-');
|
---|
| 461 | MY_CHECK(MY_ISXDIGIT(pwszString[14]));
|
---|
| 462 | MY_CHECK(MY_ISXDIGIT(pwszString[15]));
|
---|
| 463 | MY_CHECK(MY_ISXDIGIT(pwszString[16]));
|
---|
| 464 | MY_CHECK(MY_ISXDIGIT(pwszString[17]));
|
---|
| 465 | MY_CHECK(pwszString[18] == '-');
|
---|
| 466 | MY_CHECK(MY_ISXDIGIT(pwszString[19]));
|
---|
| 467 | MY_CHECK(MY_ISXDIGIT(pwszString[20]));
|
---|
| 468 | MY_CHECK(MY_ISXDIGIT(pwszString[21]));
|
---|
| 469 | MY_CHECK(MY_ISXDIGIT(pwszString[22]));
|
---|
| 470 | MY_CHECK(pwszString[23] == '-');
|
---|
| 471 | MY_CHECK(MY_ISXDIGIT(pwszString[24]));
|
---|
| 472 | MY_CHECK(MY_ISXDIGIT(pwszString[25]));
|
---|
| 473 | MY_CHECK(MY_ISXDIGIT(pwszString[26]));
|
---|
| 474 | MY_CHECK(MY_ISXDIGIT(pwszString[27]));
|
---|
| 475 | MY_CHECK(MY_ISXDIGIT(pwszString[28]));
|
---|
| 476 | MY_CHECK(MY_ISXDIGIT(pwszString[29]));
|
---|
| 477 | MY_CHECK(MY_ISXDIGIT(pwszString[30]));
|
---|
| 478 | MY_CHECK(MY_ISXDIGIT(pwszString[31]));
|
---|
| 479 | MY_CHECK(MY_ISXDIGIT(pwszString[32]));
|
---|
| 480 | MY_CHECK(MY_ISXDIGIT(pwszString[33]));
|
---|
| 481 | MY_CHECK(MY_ISXDIGIT(pwszString[34]));
|
---|
| 482 | MY_CHECK(MY_ISXDIGIT(pwszString[35]));
|
---|
[32995] | 483 | if (fHaveBraces)
|
---|
| 484 | MY_CHECK(pwszString[36] == '}');
|
---|
| 485 | MY_CHECK(!pwszString[36 + fHaveBraces]);
|
---|
[19198] | 486 | #undef MY_ISXDIGIT
|
---|
| 487 | #undef MY_CHECK
|
---|
| 488 |
|
---|
| 489 | /*
|
---|
| 490 | * Inverse of RTUuidToUtf8 (see above).
|
---|
| 491 | */
|
---|
| 492 | #define MY_TONUM(ch) (g_au8Digits[(ch) & 0xff])
|
---|
[40988] | 493 | pUuid->Gen.u32TimeLow = RT_LE2H_U32((uint32_t)MY_TONUM(pwszString[ 0]) << 28
|
---|
[19198] | 494 | | (uint32_t)MY_TONUM(pwszString[ 1]) << 24
|
---|
| 495 | | (uint32_t)MY_TONUM(pwszString[ 2]) << 20
|
---|
| 496 | | (uint32_t)MY_TONUM(pwszString[ 3]) << 16
|
---|
| 497 | | (uint32_t)MY_TONUM(pwszString[ 4]) << 12
|
---|
| 498 | | (uint32_t)MY_TONUM(pwszString[ 5]) << 8
|
---|
| 499 | | (uint32_t)MY_TONUM(pwszString[ 6]) << 4
|
---|
[40988] | 500 | | (uint32_t)MY_TONUM(pwszString[ 7]));
|
---|
| 501 | pUuid->Gen.u16TimeMid = RT_LE2H_U16((uint16_t)MY_TONUM(pwszString[ 9]) << 12
|
---|
[19198] | 502 | | (uint16_t)MY_TONUM(pwszString[10]) << 8
|
---|
| 503 | | (uint16_t)MY_TONUM(pwszString[11]) << 4
|
---|
[40988] | 504 | | (uint16_t)MY_TONUM(pwszString[12]));
|
---|
| 505 | pUuid->Gen.u16TimeHiAndVersion = RT_LE2H_U16(
|
---|
[19198] | 506 | (uint16_t)MY_TONUM(pwszString[14]) << 12
|
---|
| 507 | | (uint16_t)MY_TONUM(pwszString[15]) << 8
|
---|
| 508 | | (uint16_t)MY_TONUM(pwszString[16]) << 4
|
---|
[40988] | 509 | | (uint16_t)MY_TONUM(pwszString[17]));
|
---|
[19198] | 510 | pUuid->Gen.u8ClockSeqHiAndReserved =
|
---|
| 511 | (uint16_t)MY_TONUM(pwszString[19]) << 4
|
---|
| 512 | | (uint16_t)MY_TONUM(pwszString[20]);
|
---|
| 513 | pUuid->Gen.u8ClockSeqLow =
|
---|
| 514 | (uint16_t)MY_TONUM(pwszString[21]) << 4
|
---|
| 515 | | (uint16_t)MY_TONUM(pwszString[22]);
|
---|
| 516 | pUuid->Gen.au8Node[0] = (uint8_t)MY_TONUM(pwszString[24]) << 4
|
---|
| 517 | | (uint8_t)MY_TONUM(pwszString[25]);
|
---|
| 518 | pUuid->Gen.au8Node[1] = (uint8_t)MY_TONUM(pwszString[26]) << 4
|
---|
| 519 | | (uint8_t)MY_TONUM(pwszString[27]);
|
---|
| 520 | pUuid->Gen.au8Node[2] = (uint8_t)MY_TONUM(pwszString[28]) << 4
|
---|
| 521 | | (uint8_t)MY_TONUM(pwszString[29]);
|
---|
| 522 | pUuid->Gen.au8Node[3] = (uint8_t)MY_TONUM(pwszString[30]) << 4
|
---|
| 523 | | (uint8_t)MY_TONUM(pwszString[31]);
|
---|
| 524 | pUuid->Gen.au8Node[4] = (uint8_t)MY_TONUM(pwszString[32]) << 4
|
---|
| 525 | | (uint8_t)MY_TONUM(pwszString[33]);
|
---|
| 526 | pUuid->Gen.au8Node[5] = (uint8_t)MY_TONUM(pwszString[34]) << 4
|
---|
| 527 | | (uint8_t)MY_TONUM(pwszString[35]);
|
---|
| 528 | #undef MY_TONUM
|
---|
| 529 | return VINF_SUCCESS;
|
---|
| 530 | }
|
---|
[21337] | 531 | RT_EXPORT_SYMBOL(RTUuidFromUtf16);
|
---|
[19198] | 532 |
|
---|