1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include "uuid.h"
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <sys/random.h> /* not very portable but idc */
bool l2__str_to_uint64(uint64_t *out, const char *str);
void l2_uuid__set_version(uuid_t *id, unsigned version)
{
version &= 0x0F;
id->uuid_ms &= ~(UINT64_C(0x0F) << 12);
id->uuid_ms |= (uint64_t)version << 12;
}
void l2_uuid__set_variant(uuid_t *id, unsigned variant, unsigned bits)
{
uint64_t mask = (UINT64_C(1) << (64 - bits)) - 1;
uint64_t lvariant = (uint64_t)variant << (64 - bits);
lvariant &= ~mask;
id->uuid_ls &= mask;
id->uuid_ls |= lvariant;
}
void l2_uuid_random(uuid_t *id)
{
getentropy(id, sizeof(uuid_t));
l2_uuid__set_version(id, 4);
l2_uuid__set_variant(id, 2, 2);
}
void l2_uuid_to_string(const uuid_t *id, char *out)
{
snprintf(out, UUID_STRLEN + 1, "%08" PRIx64 "-%04" PRIx64 "-%04" PRIx64 "-%04" PRIx64 "-%012" PRIx64,
id->uuid_ms >> 32, /* time-low */
id->uuid_ms >> 16 & 0xffff, /* time-mid */
id->uuid_ms & 0xffff, /* time-high-and-version */
id->uuid_ls >> 48, /* clock-seq-and-reserved, clock-seq-low */
id->uuid_ls & UINT64_C(0xffffffffffff)); /* node */
}
void l2_uuid_to_string_short(const uuid_t *id, char *out)
{
snprintf(out, UUID_STRLEN_SHORT + 1, "%08" PRIx64 "%08" PRIx64, id->halves[1], id->halves[0]);
}
bool l2_uuid_from_string(uuid_t *id, const char *str)
{
size_t slen = strlen(str);
char rbuf[UUID_STRLEN_SHORT + 1];
if (slen != UUID_STRLEN) return false;
memcpy(rbuf, str, 8);
memcpy(rbuf + 8, str + 9, 4);
memcpy(rbuf + 12, str + 14, 4);
memcpy(rbuf + 16, str + 19, 4);
memcpy(rbuf + 20, str + 24, 12);
rbuf[UUID_STRLEN_SHORT] = '\0';
return l2_uuid_from_string_short(id, rbuf);
}
bool l2_uuid_from_string_short(uuid_t *id, const char *str)
{
size_t slen = strlen(str);
uuid_t outid;
if (slen != UUID_STRLEN_SHORT) return false;
if (!l2__str_to_uint64(outid.halves + 1, str)) return false;
if (!l2__str_to_uint64(outid.halves, str + 16)) return false;
memcpy(id, &outid, sizeof(uuid_t));
return true;
}
int l2_uuid_compare(const uuid_t *c1, const uuid_t *c2)
{
return memcmp(c1, c2, sizeof(uuid_t));
}
/* This function exists because there's not a portable way to do this.
* Don't suggest strtoull, because uint64_t may not be a ulonglong. */
bool l2__str_to_uint64(uint64_t *out, const char *str)
{
*out = 0;
str += 15;
for (unsigned i = 0; i < 16; ++i, --str) {
switch (*str) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
*out |= (uint64_t)(*str - '0') << (i * 4);
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
*out |= (uint64_t)(*str - 'a' + 10) << (i * 4);
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
*out |= (uint64_t)(*str - 'A' + 10) << (i * 4);
break;
default:
return false;
}
}
return true;
}
|