1
1
/*
2
- * switch_uuidv7.h uuidv7
2
+ * switch_uuidv7.h UUIDv7 generation functions, copied AS IS from https://github.com/LiosK/uuidv7-h
3
+ * with minor fixes to make it compile with FreeSWITCH.
3
4
*/
4
- #include <switch.h>
5
5
6
- #undef _POSIX_C_SOURCE
7
- #define _POSIX_C_SOURCE 199309L
6
+ /**
7
+ * @file
8
+ *
9
+ * uuidv7.h - Single-file C/C++ UUIDv7 Library
10
+ *
11
+ * @version v0.1.6
12
+ * @author LiosK
13
+ * @copyright Licensed under the Apache License, Version 2.0
14
+ * @see https://github.com/LiosK/uuidv7-h
15
+ */
16
+ /*
17
+ * Copyright 2022 LiosK
18
+ *
19
+ * Licensed under the Apache License, Version 2.0 (the "License");
20
+ * you may not use this file except in compliance with the License.
21
+ * You may obtain a copy of the License at
22
+ *
23
+ * http://www.apache.org/licenses/LICENSE-2.0
24
+ *
25
+ * Unless required by applicable law or agreed to in writing, software
26
+ * distributed under the License is distributed on an "AS IS" BASIS,
27
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28
+ * See the License for the specific language governing permissions and
29
+ * limitations under the License.
30
+ */
31
+ #ifndef UUIDV7_H_BAEDKYFQ
32
+ #define UUIDV7_H_BAEDKYFQ
8
33
9
34
#include <stddef.h>
10
35
#include <stdint.h>
11
36
37
+ /**
38
+ * @name Status codes returned by uuidv7_generate()
39
+ *
40
+ * @{
41
+ */
12
42
13
43
/**
14
44
* Indicates that the `unix_ts_ms` passed was used because no preceding UUID was
49
79
*/
50
80
#define UUIDV7_STATUS_ERR_TIMESTAMP_OVERFLOW (-2)
51
81
82
+ /** @} */
52
83
53
84
#ifdef __cplusplus
54
85
extern "C" {
55
86
#endif
56
87
88
+ /**
89
+ * @name Low-level primitives
90
+ *
91
+ * @{
92
+ */
57
93
58
94
/**
59
95
* Generates a new UUIDv7 from the given Unix time, random bytes, and previous
@@ -78,18 +114,19 @@ extern "C" {
78
114
* monotonic order of UUIDs or fine-tune the generation
79
115
* process.
80
116
*/
117
+ static inline int8_t uuidv7_generate (uint8_t * uuid_out , uint64_t unix_ts_ms ,
118
+ const uint8_t * rand_bytes ,
119
+ const uint8_t * uuid_prev ) {
120
+ static const uint64_t MAX_TIMESTAMP = ((uint64_t )1 << 48 ) - 1 ;
121
+ static const uint64_t MAX_COUNTER = ((uint64_t )1 << 42 ) - 1 ;
81
122
82
- static inline int8_t uuidv7_generate (uint8_t * uuid_out , uint64_t unix_ts_ms ,const uint8_t * rand_bytes ,const uint8_t * uuid_prev ) {
83
123
int8_t status ;
84
124
uint64_t timestamp = 0 ;
85
- static const uint64_t MAX_TIMESTAMP = ((uint64_t )1 << 48 ) - 1 ;
86
- static const uint64_t MAX_COUNTER = ((uint64_t )1 << 42 ) - 1 ;
87
125
88
126
if (unix_ts_ms > MAX_TIMESTAMP ) {
89
127
return UUIDV7_STATUS_ERR_TIMESTAMP ;
90
128
}
91
129
92
-
93
130
if (uuid_prev == NULL ) {
94
131
status = UUIDV7_STATUS_UNPRECEDENTED ;
95
132
timestamp = unix_ts_ms ;
@@ -162,9 +199,71 @@ static inline int uuidv7_status_n_rand_consumed(int8_t status) {
162
199
return status == UUIDV7_STATUS_COUNTER_INC ? 4 : 10 ;
163
200
}
164
201
202
+ /**
203
+ * Encodes a UUID in the 8-4-4-4-12 hexadecimal string representation.
204
+ *
205
+ * @param uuid 16-byte byte array representing the UUID to encode.
206
+ * @param string_out Character array where the encoded string is stored. Its
207
+ * length must be 37 (36 digits + NUL) or longer.
208
+ */
209
+ static inline void uuidv7_to_string (const uint8_t * uuid , char * string_out ) {
210
+ static const char DIGITS [] = "0123456789abcdef" ;
211
+ for (int i = 0 ; i < 16 ; i ++ ) {
212
+ uint_fast8_t e = uuid [i ];
213
+ * string_out ++ = DIGITS [e >> 4 ];
214
+ * string_out ++ = DIGITS [e & 15 ];
215
+ if (i == 3 || i == 5 || i == 7 || i == 9 ) {
216
+ * string_out ++ = '-' ;
217
+ }
218
+ }
219
+ * string_out = '\0' ;
220
+ }
221
+
222
+ /**
223
+ * Decodes the 8-4-4-4-12 hexadecimal string representation of a UUID.
224
+ *
225
+ * @param string 37-byte (36 digits + NUL) character array representing the
226
+ * 8-4-4-4-12 hexadecimal string representation.
227
+ * @param uuid_out 16-byte byte array where the decoded UUID is stored.
228
+ * @return Zero on success or non-zero integer on failure.
229
+ */
230
+ static inline int uuidv7_from_string (const char * string , uint8_t * uuid_out ) {
231
+ for (int i = 0 ; i < 32 ; i ++ ) {
232
+ char c = * string ++ ;
233
+ // clang-format off
234
+ uint8_t x = c == '0' ? 0 : c == '1' ? 1 : c == '2' ? 2 : c == '3' ? 3
235
+ : c == '4' ? 4 : c == '5' ? 5 : c == '6' ? 6 : c == '7' ? 7
236
+ : c == '8' ? 8 : c == '9' ? 9 : c == 'a' ? 10 : c == 'b' ? 11
237
+ : c == 'c' ? 12 : c == 'd' ? 13 : c == 'e' ? 14 : c == 'f' ? 15
238
+ : c == 'A' ? 10 : c == 'B' ? 11 : c == 'C' ? 12 : c == 'D' ? 13
239
+ : c == 'E' ? 14 : c == 'F' ? 15 : 0xff ;
240
+ // clang-format on
241
+ if (x == 0xff ) {
242
+ return -1 ; // invalid digit
243
+ }
244
+
245
+ if ((i & 1 ) == 0 ) {
246
+ uuid_out [i >> 1 ] = x << 4 ; // even i => hi 4 bits
247
+ } else {
248
+ uuid_out [i >> 1 ] |= x ; // odd i => lo 4 bits
249
+ }
250
+
251
+ if ((i == 7 || i == 11 || i == 15 || i == 19 ) && (* string ++ != '-' )) {
252
+ return -1 ; // invalid format
253
+ }
254
+ }
255
+ if (* string != '\0' ) {
256
+ return -1 ; // invalid length
257
+ }
258
+ return 0 ; // success
259
+ }
260
+
261
+ /** @} */
165
262
166
263
/**
167
264
* @name High-level APIs that require platform integration
265
+ *
266
+ * @{
168
267
*/
169
268
170
269
/**
@@ -187,10 +286,39 @@ static inline int uuidv7_status_n_rand_consumed(int8_t status) {
187
286
* process. The implementation-dependent code must be out of
188
287
* the range of `int8_t` and negative if it reports an error.
189
288
*/
289
+ int uuidv7_new (uint8_t * uuid_out );
190
290
191
- SWITCH_DECLARE (int ) uuidv7_new (uint8_t * uuid_out );
291
+ /**
292
+ * Generates an 8-4-4-4-12 hexadecimal string representation of new UUIDv7.
293
+ *
294
+ * @param string_out Character array where the encoded string is stored. Its
295
+ * length must be 37 (36 digits + NUL) or longer.
296
+ * @return Return value of `uuidv7_new()`.
297
+ * @note Provide a concrete `uuidv7_new()` implementation to enable
298
+ * this function.
299
+ */
300
+ static inline int uuidv7_new_string (char * string_out ) {
301
+ uint8_t uuid [16 ];
302
+ int result = uuidv7_new (uuid );
303
+ uuidv7_to_string (uuid , string_out );
304
+ return result ;
305
+ }
192
306
307
+ /** @} */
193
308
194
309
#ifdef __cplusplus
195
310
} /* extern "C" { */
196
311
#endif
312
+
313
+ #endif /* #ifndef UUIDV7_H_BAEDKYFQ */
314
+
315
+ /* For Emacs:
316
+ * Local Variables:
317
+ * mode:c
318
+ * indent-tabs-mode:t
319
+ * tab-width:4
320
+ * c-basic-offset:4
321
+ * End:
322
+ * For VIM:
323
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
324
+ */
0 commit comments