Files
bluelib/ds/uuid.c

246 lines
6.0 KiB
C

#include <blue/core/stringstream.h>
#include <blue/ds/string.h>
#include <blue/ds/uuid.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*** PRIVATE DATA *************************************************************/
struct b_uuid_p {
struct b_uuid_bytes uuid_bytes;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static b_status uuid_to_cstr(
const struct b_uuid_p *uuid, char out[B_UUID_STRING_MAX])
{
snprintf(
out, B_UUID_STRING_MAX,
"%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]);
return B_SUCCESS;
}
static void uuid_get_bytes(
const struct b_uuid_p *uuid, unsigned char bytes[B_UUID_NBYTES])
{
memcpy(bytes, uuid->uuid_bytes.uuid_bytes, B_UUID_NBYTES);
}
static void uuid_get_uuid_bytes(
const struct b_uuid_p *uuid, struct b_uuid_bytes *bytes)
{
memcpy(bytes, &uuid->uuid_bytes, sizeof *bytes);
}
static struct b_uuid_bytes *uuid_ptr(struct b_uuid_p *uuid)
{
return &uuid->uuid_bytes;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_uuid *b_uuid_create_from_bytes(
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,
unsigned char u12, unsigned char u13, unsigned char u14, unsigned char u15)
{
b_uuid *uuid = b_uuid_create();
if (!uuid) {
return NULL;
}
struct b_uuid_p *p = b_object_get_private(uuid, B_TYPE_UUID);
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;
return uuid;
}
b_uuid *b_uuid_create_from_bytev(const unsigned char bytes[B_UUID_NBYTES])
{
b_uuid *uuid = b_uuid_create();
if (!uuid) {
return NULL;
}
struct b_uuid_p *p = b_object_get_private(uuid, B_TYPE_UUID);
memcpy(p->uuid_bytes.uuid_bytes, bytes, B_UUID_NBYTES);
return uuid;
}
b_uuid *b_uuid_create_from_cstr(const char *str)
{
struct b_uuid_bytes bytes;
bool valid = true;
bool is_guid = false;
if (*str == '{') {
is_guid = true;
str++;
}
size_t i, byte = 0;
for (i = 0; str[i] && byte < B_UUID_NBYTES;) {
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;
}
}
if (str[i] != '\0' || byte != B_UUID_NBYTES) {
valid = false;
}
if (!valid) {
return NULL;
}
return b_uuid_create_from_uuid_bytes(&bytes);
}
b_status b_uuid_to_cstr(const b_uuid *uuid, char out[B_UUID_STRING_MAX])
{
B_CLASS_DISPATCH_STATIC(B_TYPE_UUID, uuid_to_cstr, uuid, out);
}
void b_uuid_get_bytes(const b_uuid *uuid, unsigned char bytes[B_UUID_NBYTES])
{
B_CLASS_DISPATCH_STATIC(B_TYPE_UUID, uuid_get_bytes, uuid, bytes);
}
void b_uuid_get_uuid_bytes(const b_uuid *uuid, struct b_uuid_bytes *bytes)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_UUID, uuid_get_uuid_bytes, uuid, bytes);
}
struct b_uuid_bytes *b_uuid_ptr(b_uuid *uuid)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_UUID, uuid_ptr, uuid);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
b_uuid *b_uuid_create_from_uuid_bytes(const struct b_uuid_bytes *bytes)
{
return b_uuid_create_from_bytev(bytes->uuid_bytes);
}
b_uuid *b_uuid_create_from_string(const b_string *string)
{
return b_uuid_create_from_cstr(b_string_ptr(string));
}
b_status b_uuid_to_stringstream(const b_uuid *uuid, struct b_stringstream *out)
{
char str[B_UUID_STRING_MAX];
b_uuid_to_cstr(uuid, str);
b_stringstream_add(out, str);
return B_SUCCESS;
}
b_status b_uuid_to_string(const b_uuid *uuid, b_string *out)
{
char str[B_UUID_STRING_MAX];
b_uuid_to_cstr(uuid, str);
b_string_append_cstr(out, str);
return B_SUCCESS;
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void uuid_init(b_object *obj, void *priv)
{
struct b_uuid_p *uuid = priv;
}
static void uuid_fini(b_object *obj, void *priv)
{
struct b_uuid_p *uuid = priv;
}
static void uuid_to_string(const b_object *uuid, struct b_stream *out)
{
char str[B_UUID_STRING_MAX];
b_uuid_to_cstr(uuid, str);
b_stream_write_string(out, str, NULL);
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_uuid)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = uuid_to_string;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_uuid)
B_TYPE_DEFINITION_BEGIN(b_uuid)
B_TYPE_ID(0x17037068, 0x92f7, 0x4582, 0xad1f, 0x0dea43b628de);
B_TYPE_CLASS(b_uuid_class);
B_TYPE_INSTANCE_PRIVATE(struct b_uuid_p);
B_TYPE_INSTANCE_INIT(uuid_init);
B_TYPE_INSTANCE_FINI(uuid_fini);
B_TYPE_DEFINITION_END(b_uuid)