From 20d9fc5b5356a1054cb104ba6651b77184abf0db Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Sun, 24 Dec 2023 04:26:00 -0600 Subject: initial commit --- src/uuid/uuid.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/uuid/uuid.h | 27 +++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 src/uuid/uuid.c create mode 100644 src/uuid/uuid.h (limited to 'src/uuid') diff --git a/src/uuid/uuid.c b/src/uuid/uuid.c new file mode 100644 index 0000000..0d49f0b --- /dev/null +++ b/src/uuid/uuid.c @@ -0,0 +1,123 @@ +#include "uuid.h" + +#include +#include +#include +#include /* 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->halves[1] &= ~(UINT64_C(0x0F) << 12); + id->halves[1] |= (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->halves[0] &= mask; + id->halves[0] |= 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->halves[1] >> 32, /* time-low */ + id->halves[1] >> 16 & 0xffff, /* time-mid */ + id->halves[1] & 0xffff, /* time-high-and-version */ + id->halves[0] >> 48, /* clock-seq-and-reserved, clock-seq-low */ + id->halves[0] & 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; +} + +/* 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; +} diff --git a/src/uuid/uuid.h b/src/uuid/uuid.h new file mode 100644 index 0000000..740fa17 --- /dev/null +++ b/src/uuid/uuid.h @@ -0,0 +1,27 @@ +#ifndef L2SU_UUID_H_INCLUDED +#define L2SU_UUID_H_INCLUDED + +#include +#include + +/* A 128-bit GUID as specified by RFC 4122. + * NOTE: halves[0] is the least significant half of the GUID. */ +typedef union tag_uuid_t { + uint8_t bytes[16]; + uint64_t halves[2]; +} uuid_t; + +#define UUID_NULL_INIT { { 0 } } + +#define UUID_STRLEN (36u) +#define UUID_STRLEN_SHORT (32u) + +void l2_uuid_random(uuid_t *id); + +void l2_uuid_to_string(const uuid_t *id, char *out); +void l2_uuid_to_string_short(const uuid_t *id, char *out); + +bool l2_uuid_from_string(uuid_t *id, const char *str); +bool l2_uuid_from_string_short(uuid_t *id, const char *str); + +#endif /* include guard */ -- cgit v1.2.3-70-g09d2