2026-03-16 10:35:43 +00:00
|
|
|
#include <fx/core/stringstream.h>
|
|
|
|
|
#include <fx/ds/string.h>
|
|
|
|
|
#include <fx/ds/uuid.h>
|
2024-10-24 19:24:54 +01:00
|
|
|
#include <ctype.h>
|
2025-02-10 13:59:06 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
2024-10-24 19:24:54 +01:00
|
|
|
|
2025-10-19 13:10:45 +01:00
|
|
|
/*** PRIVATE DATA *************************************************************/
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
struct fx_uuid_p {
|
|
|
|
|
union fx_uuid_bytes uuid_bytes;
|
2024-10-24 19:24:54 +01:00
|
|
|
};
|
|
|
|
|
|
2025-10-19 13:10:45 +01:00
|
|
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static fx_status uuid_to_cstr(
|
|
|
|
|
const struct fx_uuid_p *uuid, char out[FX_UUID_STRING_MAX])
|
2024-10-24 19:24:54 +01:00
|
|
|
{
|
2025-10-19 13:10:45 +01:00
|
|
|
snprintf(
|
2026-03-16 10:35:43 +00:00
|
|
|
out, FX_UUID_STRING_MAX,
|
2025-10-19 13:10:45 +01:00
|
|
|
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%"
|
|
|
|
|
"02x%02x",
|
|
|
|
|
uuid->uuid_bytes.uuid_bytes[0], uuid->uuid_bytes.uuid_bytes[1],
|
|
|
|
|
uuid->uuid_bytes.uuid_bytes[2], uuid->uuid_bytes.uuid_bytes[3],
|
|
|
|
|
uuid->uuid_bytes.uuid_bytes[4], uuid->uuid_bytes.uuid_bytes[5],
|
|
|
|
|
uuid->uuid_bytes.uuid_bytes[6], uuid->uuid_bytes.uuid_bytes[7],
|
|
|
|
|
uuid->uuid_bytes.uuid_bytes[8], uuid->uuid_bytes.uuid_bytes[9],
|
|
|
|
|
uuid->uuid_bytes.uuid_bytes[10], uuid->uuid_bytes.uuid_bytes[11],
|
|
|
|
|
uuid->uuid_bytes.uuid_bytes[12], uuid->uuid_bytes.uuid_bytes[13],
|
|
|
|
|
uuid->uuid_bytes.uuid_bytes[14], uuid->uuid_bytes.uuid_bytes[15]);
|
2026-03-16 10:35:43 +00:00
|
|
|
return FX_SUCCESS;
|
2025-10-19 13:10:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void uuid_get_bytes(
|
2026-03-16 10:35:43 +00:00
|
|
|
const struct fx_uuid_p *uuid, unsigned char bytes[FX_UUID_NBYTES])
|
2025-10-19 13:10:45 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
memcpy(bytes, uuid->uuid_bytes.uuid_bytes, FX_UUID_NBYTES);
|
2025-10-19 13:10:45 +01:00
|
|
|
}
|
2024-10-24 19:24:54 +01:00
|
|
|
|
2025-10-19 13:10:45 +01:00
|
|
|
static void uuid_get_uuid_bytes(
|
2026-03-16 10:35:43 +00:00
|
|
|
const struct fx_uuid_p *uuid, union fx_uuid_bytes *bytes)
|
2025-10-19 13:10:45 +01:00
|
|
|
{
|
|
|
|
|
memcpy(bytes, &uuid->uuid_bytes, sizeof *bytes);
|
2024-10-24 19:24:54 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static union fx_uuid_bytes *uuid_ptr(struct fx_uuid_p *uuid)
|
2025-10-19 13:10:45 +01:00
|
|
|
{
|
|
|
|
|
return &uuid->uuid_bytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_uuid *fx_uuid_create_from_bytes(
|
2025-02-10 13:59:06 +00:00
|
|
|
unsigned char u00, unsigned char u01, unsigned char u02,
|
|
|
|
|
unsigned char u03, unsigned char u04, unsigned char u05,
|
|
|
|
|
unsigned char u06, unsigned char u07, unsigned char u08,
|
|
|
|
|
unsigned char u09, unsigned char u10, unsigned char u11,
|
2024-10-24 19:24:54 +01:00
|
|
|
unsigned char u12, unsigned char u13, unsigned char u14, unsigned char u15)
|
|
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_uuid *uuid = fx_uuid_create();
|
2024-10-24 19:24:54 +01:00
|
|
|
if (!uuid) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
struct fx_uuid_p *p = fx_object_get_private(uuid, FX_TYPE_UUID);
|
2025-10-19 13:10:45 +01:00
|
|
|
|
|
|
|
|
p->uuid_bytes.uuid_bytes[0] = u00;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[1] = u01;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[2] = u02;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[3] = u03;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[4] = u04;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[5] = u05;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[6] = u06;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[7] = u07;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[8] = u08;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[9] = u09;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[10] = u10;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[11] = u11;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[12] = u12;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[13] = u13;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[14] = u14;
|
|
|
|
|
p->uuid_bytes.uuid_bytes[15] = u15;
|
2024-10-24 19:24:54 +01:00
|
|
|
|
|
|
|
|
return uuid;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_uuid *fx_uuid_create_from_bytev(const unsigned char bytes[FX_UUID_NBYTES])
|
2024-10-24 19:24:54 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_uuid *uuid = fx_uuid_create();
|
2024-10-24 19:24:54 +01:00
|
|
|
if (!uuid) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
struct fx_uuid_p *p = fx_object_get_private(uuid, FX_TYPE_UUID);
|
2024-10-24 19:24:54 +01:00
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
memcpy(p->uuid_bytes.uuid_bytes, bytes, FX_UUID_NBYTES);
|
2024-10-24 19:24:54 +01:00
|
|
|
|
2025-10-19 13:10:45 +01:00
|
|
|
return uuid;
|
2024-10-24 19:24:54 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_uuid *fx_uuid_create_from_cstr(const char *str)
|
2024-10-24 19:24:54 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
union fx_uuid_bytes bytes;
|
2024-10-24 19:24:54 +01:00
|
|
|
|
|
|
|
|
bool valid = true;
|
|
|
|
|
bool is_guid = false;
|
|
|
|
|
if (*str == '{') {
|
|
|
|
|
is_guid = true;
|
|
|
|
|
str++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t i, byte = 0;
|
2026-03-16 10:35:43 +00:00
|
|
|
for (i = 0; str[i] && byte < FX_UUID_NBYTES;) {
|
2024-10-24 19:24:54 +01:00
|
|
|
if (i == 8 || i == 13 || i == 18 || i == 23) {
|
|
|
|
|
if (str[i] != '-') {
|
|
|
|
|
valid = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char n[3];
|
|
|
|
|
n[0] = str[i];
|
|
|
|
|
n[1] = str[i + 1];
|
|
|
|
|
n[2] = '\0';
|
|
|
|
|
|
|
|
|
|
if (!isxdigit(n[0]) || !isxdigit(n[1])) {
|
|
|
|
|
valid = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *p;
|
|
|
|
|
unsigned long v = strtoul(n, &p, 16);
|
|
|
|
|
bytes.uuid_bytes[byte] = v;
|
|
|
|
|
|
|
|
|
|
byte++;
|
|
|
|
|
i += 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (str[i] == '}') {
|
|
|
|
|
if (is_guid) {
|
|
|
|
|
i++;
|
|
|
|
|
} else {
|
|
|
|
|
valid = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
if (str[i] != '\0' || byte != FX_UUID_NBYTES) {
|
2024-10-24 19:24:54 +01:00
|
|
|
valid = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!valid) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
return fx_uuid_create_from_uuid_bytes(&bytes);
|
2024-10-24 19:24:54 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_status fx_uuid_to_cstr(const fx_uuid *uuid, char out[FX_UUID_STRING_MAX])
|
2024-10-24 19:24:54 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
FX_CLASS_DISPATCH_STATIC(FX_TYPE_UUID, uuid_to_cstr, uuid, out);
|
2025-10-19 13:10:45 +01:00
|
|
|
}
|
2024-10-24 19:24:54 +01:00
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
void fx_uuid_get_bytes(const fx_uuid *uuid, unsigned char bytes[FX_UUID_NBYTES])
|
2025-10-19 13:10:45 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
FX_CLASS_DISPATCH_STATIC(FX_TYPE_UUID, uuid_get_bytes, uuid, bytes);
|
2024-10-24 19:24:54 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
void fx_uuid_get_uuid_bytes(const fx_uuid *uuid, union fx_uuid_bytes *bytes)
|
2024-10-24 19:24:54 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
FX_CLASS_DISPATCH_STATIC(FX_TYPE_UUID, uuid_get_uuid_bytes, uuid, bytes);
|
2025-10-19 13:10:45 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
union fx_uuid_bytes *fx_uuid_ptr(fx_uuid *uuid)
|
2025-10-19 13:10:45 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_UUID, uuid_ptr, uuid);
|
2025-10-19 13:10:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_uuid *fx_uuid_create_from_uuid_bytes(const union fx_uuid_bytes *bytes)
|
2025-10-19 13:10:45 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
return fx_uuid_create_from_bytev(bytes->uuid_bytes);
|
2024-10-24 19:24:54 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_uuid *fx_uuid_create_from_string(const fx_string *string)
|
2025-10-19 13:10:45 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
return fx_uuid_create_from_cstr(fx_string_ptr(string));
|
2025-10-19 13:10:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static void uuid_init(fx_object *obj, void *priv)
|
2024-10-24 19:24:54 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
struct fx_uuid_p *uuid = priv;
|
2024-10-24 19:24:54 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static void uuid_fini(fx_object *obj, void *priv)
|
2024-10-24 19:24:54 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
struct fx_uuid_p *uuid = priv;
|
2024-10-24 19:24:54 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static void uuid_to_string(const fx_object *uuid, fx_stream *out)
|
2024-10-24 19:24:54 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
char str[FX_UUID_STRING_MAX];
|
|
|
|
|
fx_uuid_to_cstr(uuid, str);
|
|
|
|
|
fx_stream_write_string(out, str, NULL);
|
2024-10-24 19:24:54 +01:00
|
|
|
}
|
2025-10-19 13:10:45 +01:00
|
|
|
|
|
|
|
|
/*** CLASS DEFINITION *********************************************************/
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_uuid)
|
|
|
|
|
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
|
|
|
|
FX_INTERFACE_ENTRY(to_string) = uuid_to_string;
|
|
|
|
|
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
|
|
|
|
FX_TYPE_CLASS_DEFINITION_END(fx_uuid)
|
|
|
|
|
|
|
|
|
|
FX_TYPE_DEFINITION_BEGIN(fx_uuid)
|
|
|
|
|
FX_TYPE_ID(0x17037068, 0x92f7, 0x4582, 0xad1f, 0x0dea43b628de);
|
|
|
|
|
FX_TYPE_CLASS(fx_uuid_class);
|
|
|
|
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_uuid_p);
|
|
|
|
|
FX_TYPE_INSTANCE_INIT(uuid_init);
|
|
|
|
|
FX_TYPE_INSTANCE_FINI(uuid_fini);
|
|
|
|
|
FX_TYPE_DEFINITION_END(fx_uuid)
|