stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
uuid.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2016-2024 Amebis
4*/
5
6#pragma once
7
8#include "assert.hpp"
9#include "compat.hpp"
10#include "string.hpp"
11#include <stdint.h>
12#include <stdio.h>
13#if defined(_WIN32)
14#include "windows.h"
15#include <rpc.h>
16#else
17#include <uuid/uuid.h>
18#include <wchar.h>
19#endif
20
21namespace stdex
22{
27 constexpr size_t uuid_str_max = 39;
28
35 inline void uuidtostr(_Out_writes_z_(uuid_str_max) char str[uuid_str_max], _In_ const uuid_t& id)
36 {
37 stdex_assert(str);
38#ifdef _WIN32
39 _snprintf_s_l(str, uuid_str_max, _TRUNCATE, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
40 id.Data1,
41 static_cast<unsigned int>(id.Data2),
42 static_cast<unsigned int>(id.Data3),
43 static_cast<unsigned int>(id.Data4[0]), static_cast<unsigned int>(id.Data4[1]),
44 static_cast<unsigned int>(id.Data4[2]), static_cast<unsigned int>(id.Data4[3]), static_cast<unsigned int>(id.Data4[4]), static_cast<unsigned int>(id.Data4[5]), static_cast<unsigned int>(id.Data4[6]), static_cast<unsigned int>(id.Data4[7]));
45#else
46 snprintf(str, uuid_str_max, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
47 *reinterpret_cast<const uint32_t*>(&id[0]),
48 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[4])),
49 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[6])),
50 static_cast<unsigned int>(id[8]), static_cast<unsigned int>(id[9]),
51 static_cast<unsigned int>(id[10]), static_cast<unsigned int>(id[11]), static_cast<unsigned int>(id[12]), static_cast<unsigned int>(id[13]), static_cast<unsigned int>(id[14]), static_cast<unsigned int>(id[15]));
52#endif
53 }
54
61 inline void uuidtostr(_Out_writes_z_(uuid_str_max) wchar_t str[uuid_str_max], _In_ const uuid_t& id)
62 {
63 stdex_assert(str);
64#ifdef _WIN32
65 _snwprintf_s_l(str, uuid_str_max, _TRUNCATE, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
66 id.Data1,
67 static_cast<unsigned int>(id.Data2),
68 static_cast<unsigned int>(id.Data3),
69 static_cast<unsigned int>(id.Data4[0]), static_cast<unsigned int>(id.Data4[1]),
70 static_cast<unsigned int>(id.Data4[2]), static_cast<unsigned int>(id.Data4[3]), static_cast<unsigned int>(id.Data4[4]), static_cast<unsigned int>(id.Data4[5]), static_cast<unsigned int>(id.Data4[6]), static_cast<unsigned int>(id.Data4[7]));
71#else
72 swprintf(str, uuid_str_max, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
73 *reinterpret_cast<const uint32_t*>(&id[0]),
74 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[4])),
75 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[6])),
76 static_cast<unsigned int>(id[8]), static_cast<unsigned int>(id[9]),
77 static_cast<unsigned int>(id[10]), static_cast<unsigned int>(id[11]), static_cast<unsigned int>(id[12]), static_cast<unsigned int>(id[13]), static_cast<unsigned int>(id[14]), static_cast<unsigned int>(id[15]));
78#endif
79 }
80
90 template <class T> inline _Success_(return != 0) bool strtouuid(
91 _In_reads_or_z_opt_(count) const T* str,
92 _In_ size_t count,
93 _Out_ uuid_t& id)
94 {
95 size_t i = 0, j;
96 uint64_t n;
97
98 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
99 if (i >= count || str[i] != '{') return false;
100 ++i;
101 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
102 n = stdex::strtou64(&str[i], count - i, &j, 16);
103 if (n > UINT32_MAX) return false;
104#ifdef _WIN32
105 id.Data1 = static_cast<unsigned long>(n);
106#else
107 * reinterpret_cast<uint32_t*>(&id[0]) = static_cast<uint32_t>(n);
108#endif
109 i += j;
110 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
111 if (i >= count || str[i] != '-') return false;
112 ++i;
113 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
114 n = stdex::strtou64(&str[i], count - i, &j, 16);
115 if (n > UINT16_MAX) return false;
116#ifdef _WIN32
117 id.Data2 = static_cast<unsigned short>(n);
118#else
119 * reinterpret_cast<uint16_t*>(&id[4]) = static_cast<uint16_t>(n);
120#endif
121 i += j;
122 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
123 if (i >= count || str[i] != '-') return false;
124 ++i;
125 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
126 n = stdex::strtou64(&str[i], count - i, &j, 16);
127 if (n > UINT16_MAX) return false;
128#ifdef _WIN32
129 id.Data3 = static_cast<unsigned short>(n);
130#else
131 * reinterpret_cast<uint16_t*>(&id[6]) = static_cast<uint16_t>(n);
132#endif
133 i += j;
134 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
135 if (i >= count || str[i] != '-') return false;
136 ++i;
137 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
138 n = stdex::strtou64(&str[i], count - i, &j, 16);
139 if (n > UINT16_MAX) return false;
140#ifdef _WIN32
141 id.Data4[0] = static_cast<unsigned char>((n >> 8) & 0xff);
142 id.Data4[1] = static_cast<unsigned char>((n) & 0xff);
143#else
144 id[8] = static_cast<unsigned char>((n >> 8) & 0xff);
145 id[9] = static_cast<unsigned char>((n) & 0xff);
146#endif
147 i += j;
148 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
149 if (i >= count && str[i] != '-') return false;
150 ++i;
151 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
152 n = stdex::strtou64(&str[i], count - i, &j, 16);
153 if (n > 0xffffffffffff) return false;
154#ifdef _WIN32
155 id.Data4[2] = static_cast<unsigned char>((n >> 40) & 0xff);
156 id.Data4[3] = static_cast<unsigned char>((n >> 32) & 0xff);
157 id.Data4[4] = static_cast<unsigned char>((n >> 24) & 0xff);
158 id.Data4[5] = static_cast<unsigned char>((n >> 16) & 0xff);
159 id.Data4[6] = static_cast<unsigned char>((n >> 8) & 0xff);
160 id.Data4[7] = static_cast<unsigned char>((n) & 0xff);
161#else
162 id[10] = static_cast<unsigned char>((n >> 40) & 0xff);
163 id[11] = static_cast<unsigned char>((n >> 32) & 0xff);
164 id[12] = static_cast<unsigned char>((n >> 24) & 0xff);
165 id[13] = static_cast<unsigned char>((n >> 16) & 0xff);
166 id[14] = static_cast<unsigned char>((n >> 8) & 0xff);
167 id[15] = static_cast<unsigned char>((n) & 0xff);
168#endif
169 i += j;
170 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
171 if (i >= count || str[i] != '}') return false;
172 ++i;
173 for (; i < count && str[i] && stdex::isspace(str[i]); ++i);
174 return i >= count || !str[i];
175 }
176}