--- uuid.c 2004/01/09 09:06:25 1.4
+++ uuid.c 2004/01/09 11:28:56 1.5
@@ -32,6 +32,7 @@
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#include <ctype.h>
#include "config.h"
#include "uuid.h"
@@ -92,7 +93,14 @@
#error unexpected: no type found for uuid_uint32_t
#endif
-/* private data type declaration */
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE !FALSE
+#endif
+
+/* UUID binary representation according to UUID standards */
struct uuid_st {
uuid_uint32_t time_low;
uuid_uint16_t time_mid;
@@ -104,39 +112,41 @@
uuid_rc_t uuid_create(uuid_t **uuid)
{
+ /* argument sanity check */
if (uuid == NULL)
return UUID_RC_ARG;
+
+ /* allocate UUID binary representation buffer */
if ((*uuid = (uuid_t *)malloc(sizeof(uuid_t))) == NULL)
return UUID_RC_MEM;
- uuid_null(*uuid);
+
+ /* set initially to "nil UUID" */
+ uuid_nil(*uuid);
+
return UUID_RC_OK;
}
uuid_rc_t uuid_destroy(uuid_t *uuid)
{
+ /* argument sanity check */
if (uuid == NULL)
return UUID_RC_ARG;
+
+ /* free UUID binary representation buffer */
free(uuid);
+
return UUID_RC_OK;
}
-uuid_rc_t uuid_null(uuid_t *uuid)
+uuid_rc_t uuid_nil(uuid_t *uuid)
{
+ /* argument sanity check */
if (uuid == NULL)
return UUID_RC_ARG;
- memset(uuid, '\0', sizeof(uuid_t));
- return UUID_RC_OK;
-}
-uuid_rc_t uuid_generate(uuid_t *uuid, unsigned int mode, ...)
-{
- va_list ap;
+ /* clear all octets to create "nil UUID" */
+ memset(uuid, '\0', sizeof(uuid_t));
- if (uuid == NULL)
- return UUID_RC_ARG;
- va_start(ap, mode);
- /* FIXME */
- va_end(ap);
return UUID_RC_OK;
}
@@ -144,112 +154,268 @@
{
int r;
+ /* argument sanity check */
if (result == NULL)
return UUID_RC_ARG;
- /* deal with NULL or equal pointers. */
- if (a == b) {
- *result = 0;
- return UUID_RC_OK;
- }
- if (a == NULL && b == NULL) {
- *result = 0;
- return UUID_RC_OK;
- }
- if (a == NULL) {
- *result = ((uuid_isnil(b, &r), r) ? 0 : -1);
- return UUID_RC_OK;
- }
- if (b == NULL) {
- *result = ((uuid_isnil(a, &r), r) ? 0 : 1);
- return UUID_RC_OK;
- }
+ /* convinience macro for setting result */
+# define RESULT(r) \
+ do { \
+ *result = (r); \
+ goto result_exit; \
+ } while (0)
+
+ /* special cases: NULL or equal UUIDs */
+ if (a == b)
+ RESULT(0);
+ if (a == NULL && b == NULL)
+ RESULT(0);
+ if (a == NULL)
+ RESULT((uuid_isnil(b, &r), r) ? 0 : -1);
+ if (b == NULL)
+ RESULT((uuid_isnil(a, &r), r) ? 0 : 1);
+
+ /* standard cases: regular different UUIDs */
+ if (a->time_low != b->time_low)
+ RESULT((a->time_low < b->time_low) ? -1 : 1);
+ if ((r = (int)a->time_mid
+ - (int)b->time_mid) != 0)
+ RESULT((r < 0) ? -1 : 1);
+ if ((r = (int)a->time_hi_and_version
+ - (int)b->time_hi_and_version) != 0)
+ RESULT((r < 0) ? -1 : 1);
+ if ((r = (int)a->clock_seq_hi_and_reserved
+ - (int)b->clock_seq_hi_and_reserved) != 0)
+ RESULT((r < 0) ? -1 : 1);
+ if ((r = (int)a->clock_seq_low
+ - (int)b->clock_seq_low) != 0)
+ RESULT((r < 0) ? -1 : 1);
+ if ((r = memcmp(a->node, b->node, sizeof(a->node))) != 0)
+ RESULT((r < 0) ? -1 : 1);
- /* we have to compare the hard way. */
- if (a->time_low != b->time_low) {
- *result = ((a->time_low < b->time_low) ? -1 : 1);
- return UUID_RC_OK;
- }
- if ((r = (int)a->time_mid - (int)b->time_mid) != 0) {
- *result = ((r < 0) ? -1 : 1);
- return UUID_RC_OK;
- }
- if ((r = (int)a->time_hi_and_version - (int)b->time_hi_and_version) != 0) {
- *result = ((r < 0) ? -1 : 1);
- return UUID_RC_OK;
- }
- if ((r = (int)a->clock_seq_hi_and_reserved - (int)b->clock_seq_hi_and_reserved) != 0) {
- *result = ((r < 0) ? -1 : 1);
- return UUID_RC_OK;
- }
- if ((r = (int)a->clock_seq_low - (int)b->clock_seq_low) != 0) {
- *result = ((r < 0) ? -1 : 1);
- return UUID_RC_OK;
- }
- if ((r = memcmp(a->node, b->node, sizeof(a->node))) != 0) {
- *result = ((r < 0) ? -1 : 1);
- return UUID_RC_OK;
- }
-
- /* else the keys are equal */
+ /* default case: the keys are equal */
*result = 0;
+
+ result_exit:
return UUID_RC_OK;
}
uuid_rc_t uuid_isnil(uuid_t *uuid, int *result)
{
+ const unsigned char *ucp;
+ int i;
+
+ /* sanity check argument(s) */
if (uuid == NULL || result == NULL)
return UUID_RC_ARG;
- *result = 0;
- if ( uuid->time_low == 0
- && uuid->time_mid == 0
- && uuid->time_hi_and_version == 0
- && uuid->clock_seq_hi_and_reserved == 0
- && uuid->clock_seq_low == 0
- && uuid->node[0] == 0
- && uuid->node[1] == 0
- && uuid->node[2] == 0
- && uuid->node[3] == 0
- && uuid->node[4] == 0
- && uuid->node[5] == 0)
- *result = 1;
+
+ /* a "nil UUID" is defined as all octets zero, so check for this case */
+ *result = TRUE;
+ for (i = 0, ucp = (unsigned char *)uuid; i < UUID_LEN_BIN; i++) {
+ if (*ucp++ != '\0') {
+ *result = FALSE;
+ break;
+ }
+ }
+
return UUID_RC_OK;
}
-uuid_rc_t uuid_parse(uuid_t *uuid, const char *str)
+uuid_rc_t uuid_unpack(uuid_t *uuid, const void *buf)
{
- if (uuid == NULL)
+ const uuid_uint8_t *in;
+ uuid_uint32_t tmp32;
+ uuid_uint16_t tmp16;
+ int i;
+
+ /* sanity check argument(s) */
+ if (uuid == NULL || buf == NULL)
return UUID_RC_ARG;
- /* FIXME */
+
+ /* treat input buffer as octet stream */
+ in = (const uuid_uint8_t *)buf;
+
+ /* unpack "time_low" field */
+ tmp32 = *in++;
+ tmp32 = (tmp32 << 8) | *in++;
+ tmp32 = (tmp32 << 8) | *in++;
+ tmp32 = (tmp32 << 8) | *in++;
+ uuid->time_low = tmp32;
+
+ /* unpack "time_mid" field */
+ tmp16 = *in++;
+ tmp16 = (tmp16 << 8) | *in++;
+ uuid->time_mid = tmp16;
+
+ /* unpack "time_hi_and_version" field */
+ tmp16 = *in++;
+ tmp16 = (tmp16 << 8) | *in++;
+ uuid->time_hi_and_version = tmp16;
+
+ /* unpack "clock_seq_hi_and_reserved" field */
+ uuid->clock_seq_hi_and_reserved = *in++;
+
+ /* unpack "clock_seq_low" field */
+ uuid->clock_seq_low = *in++;
+
+ /* unpack "node" field */
+ for (i = 0; i < sizeof(uuid->node); i++)
+ uuid->node[i] = *in++;
+
return UUID_RC_OK;
}
-uuid_rc_t uuid_format(uuid_t *uuid, char **str)
+uuid_rc_t uuid_pack(uuid_t *uuid, void **buf)
{
+ uuid_uint8_t *out;
+ uuid_uint32_t tmp32;
+ uuid_uint16_t tmp16;
+ int i;
+
+ /* sanity check argument(s) */
+ if (uuid == NULL || buf == NULL)
+ return UUID_RC_ARG;
+
+ /* optionally allocate octet buffer */
+ if (*buf == NULL)
+ if ((*buf = malloc(sizeof(uuid_t))) == NULL)
+ return UUID_RC_MEM;
+
+ /* treat output buffer as octet stream */
+ out = (uuid_uint8_t *)(*buf);
+
+ /* pack "time_low" field */
+ tmp32 = uuid->time_low;
+ out[3] = (uuid_uint8_t)(tmp32 & 0xff); tmp32 >>= 8;
+ out[2] = (uuid_uint8_t)(tmp32 & 0xff); tmp32 >>= 8;
+ out[1] = (uuid_uint8_t)(tmp32 & 0xff); tmp32 >>= 8;
+ out[0] = (uuid_uint8_t)(tmp32 & 0xff);
+
+ /* pack "time_mid" field */
+ tmp16 = uuid->time_mid;
+ out[5] = (uuid_uint8_t)(tmp16 & 0xff); tmp16 >>= 8;
+ out[4] = (uuid_uint8_t)(tmp16 & 0xff);
+
+ /* pack "time_hi_and_version" field */
+ tmp16 = uuid->time_hi_and_version;
+ out[7] = (uuid_uint8_t)(tmp16 & 0xff); tmp16 >>= 8;
+ out[6] = (uuid_uint8_t)(tmp16 & 0xff);
+
+ /* pack "clock_seq_hi_and_reserved" field */
+ out[8] = uuid->clock_seq_hi_and_reserved;
+
+ /* pack "clock_seq_low" field */
+ out[9] = uuid->clock_seq_low;
+
+ /* pack "node" field */
+ for (i = 0; i < sizeof(uuid->node); i++)
+ out[10+i] = uuid->node[i];
+
+ return UUID_RC_OK;
+}
+
+uuid_rc_t uuid_parse(uuid_t *uuid, const char *str)
+{
+ uuid_t uuid_tmp;
+ uuid_uint16_t tmp16;
+ const char *cp;
+ char hexbuf[3];
+ int i;
+
+ /* sanity check argument(s) */
if (uuid == NULL || str == NULL)
return UUID_RC_ARG;
- /* FIXME */
+
+ /*
+ * pass 1: check UUID string representation syntax
+ * example reference:
+ * f81d4fae-7dec-11d0-a765-00a0c91e6bf6
+ * 012345678901234567890123456789012345
+ * 0 1 2 3
+ */
+ if (strlen(str) != UUID_LEN_STR)
+ return UUID_RC_ARG;
+ for (i = 0, cp = str; i <= UUID_LEN_STR; i++, cp++) {
+ if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) {
+ if (*cp == '-')
+ continue;
+ else
+ return -1;
+ }
+ if (i == UUID_LEN_STR)
+ if (*cp == '\0')
+ continue;
+ if (!isxdigit(*cp))
+ return UUID_RC_ARG;
+ }
+
+ /*
+ * pass 2: parse hex values of string representation syntax
+ */
+ uuid_tmp.time_low = (uuid_uint32_t)strtoul(str, NULL, 16);
+ uuid_tmp.time_mid = (uuid_uint16_t)strtoul(str+9, NULL, 16);
+ uuid_tmp.time_hi_and_version = (uuid_uint16_t)strtoul(str+14, NULL, 16);
+ tmp16 = (uuid_uint16_t)strtoul(str+19, NULL, 16);
+ uuid_tmp.clock_seq_low = (uuid_uint8_t)(tmp16 & 0xff); tmp16 >>= 8;
+ uuid_tmp.clock_seq_hi_and_reserved = (uuid_uint8_t)(tmp16 & 0xff);
+ cp = str+24;
+ hexbuf[2] = '\0';
+ for (i = 0; i < sizeof(uuid_tmp.node); i++) {
+ hexbuf[0] = *cp++;
+ hexbuf[1] = *cp++;
+ uuid_tmp.node[i] = strtoul(hexbuf, NULL, 16);
+ }
+
return UUID_RC_OK;
}
-uuid_rc_t uuid_read(uuid_t *uuid, const void *buf)
+uuid_rc_t uuid_unparse(uuid_t *uuid, char **str)
{
- if (uuid == NULL)
+ uuid_t uuid_tmp;
+
+ /* sanity check argument(s) */
+ if (uuid == NULL || str == NULL)
return UUID_RC_ARG;
- /* FIXME */
+
+ /* optionally allocate string buffer */
+ if (*str == NULL)
+ if ((*str = (char *)malloc(UUID_LEN_STR+1)) == NULL)
+ return UUID_RC_MEM;
+
+ /* format UUID into string representation */
+ sprintf(*str,
+ "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (unsigned long)uuid_tmp.time_low,
+ (unsigned int)uuid_tmp.time_mid,
+ (unsigned int)uuid_tmp.time_hi_and_version,
+ (unsigned int)uuid_tmp.clock_seq_hi_and_reserved,
+ (unsigned int)uuid_tmp.clock_seq_low,
+ (unsigned int)uuid_tmp.node[0],
+ (unsigned int)uuid_tmp.node[1],
+ (unsigned int)uuid_tmp.node[2],
+ (unsigned int)uuid_tmp.node[3],
+ (unsigned int)uuid_tmp.node[4],
+ (unsigned int)uuid_tmp.node[5]);
+
return UUID_RC_OK;
}
-uuid_rc_t uuid_write(uuid_t *uuid, void **buf)
+uuid_rc_t uuid_generate(uuid_t *uuid, unsigned int mode, ...)
{
- if (uuid == NULL || buf == NULL)
+ va_list ap;
+
+ /* sanity check argument(s) */
+ if (uuid == NULL)
return UUID_RC_ARG;
+ va_start(ap, mode);
/* FIXME */
+ va_end(ap);
return UUID_RC_OK;
}
uuid_rc_t uuid_dump(uuid_t *uuid, char **str)
{
+ /* sanity check argument(s) */
if (uuid == NULL || str == NULL)
return UUID_RC_ARG;
/* FIXME */
|