From db4ce5eff2dd3e85f4162faa8725135b5590eb09 Mon Sep 17 00:00:00 2001
From: Vincent Dupont <vincent@otakeys.com>
Date: Thu, 23 Aug 2018 14:00:44 +0200
Subject: [PATCH] uuid: add uuid_to_string()

---
 Makefile.dep                            |  1 +
 sys/include/uuid.h                      | 10 ++++++++++
 sys/uuid/uuid.c                         | 18 ++++++++++++++++++
 tests/unittests/tests-uuid/tests-uuid.c | 21 +++++++++++++++++++++
 4 files changed, 50 insertions(+)

diff --git a/Makefile.dep b/Makefile.dep
index 5cbbf1db90..fec1eac125 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -780,6 +780,7 @@ endif
 ifneq (,$(filter uuid,$(USEMODULE)))
   USEMODULE += hashes
   USEMODULE += random
+  USEMODULE += fmt
 endif
 
 # Enable periph_gpio when periph_gpio_irq is enabled
diff --git a/sys/include/uuid.h b/sys/include/uuid.h
index 2616ebd3b4..1c8acb41a9 100644
--- a/sys/include/uuid.h
+++ b/sys/include/uuid.h
@@ -38,6 +38,8 @@ extern "C" {
 
 #define UUID_NODE_LEN    (6U)   /**< Size of the node identifier in bytes */
 
+#define UUID_STR_LEN     (36U)  /**< Size of a string UUID without null character */
+
 /**
  * @name UUID version identifiers
  * @{
@@ -140,6 +142,14 @@ static inline bool uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
     return (memcmp(uuid1, uuid2, sizeof(uuid_t)) == 0);
 }
 
+/**
+ * @brief   Generate an UUID string from an UUID structure
+ *
+ * @param[in]   uuid    UUID
+ * @param[out]  str     null-terminated UUID string, must be at least UUID_STR_LEN + 1 bytes
+ */
+void uuid_to_string(const uuid_t *uuid, char *str);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sys/uuid/uuid.c b/sys/uuid/uuid.c
index a7c9c95e40..aeb94e28b4 100644
--- a/sys/uuid/uuid.c
+++ b/sys/uuid/uuid.c
@@ -23,6 +23,7 @@
 #include "hashes/sha1.h"
 #include "random.h"
 #include "uuid.h"
+#include "fmt.h"
 
 const uuid_t uuid_namespace_dns = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */
     .time_low.u8 =      { 0x6b, 0xa7, 0xb8, 0x10 },
@@ -110,3 +111,20 @@ void uuid_v5(uuid_t *uuid, const uuid_t *ns, const uint8_t *name, size_t len)
     _set_version(uuid, UUID_V5);
     _set_reserved(uuid);
 }
+
+void uuid_to_string(const uuid_t *uuid, char *str)
+{
+    char *p = str;
+    p += fmt_u32_hex(p, byteorder_ntohl(uuid->time_low));
+    p += fmt_char(p, '-');
+    p += fmt_u16_hex(p, byteorder_ntohs(uuid->time_mid));
+    p += fmt_char(p, '-');
+    p += fmt_u16_hex(p, byteorder_ntohs(uuid->time_hi));
+    p += fmt_char(p, '-');
+    p += fmt_byte_hex(p, uuid->clk_seq_hi_res);
+    p += fmt_byte_hex(p, uuid->clk_seq_low);
+    p += fmt_char(p, '-');
+    p += fmt_bytes_hex(p, uuid->node, UUID_NODE_LEN);
+    *p = '\0';
+    fmt_to_lower(str, str);
+}
diff --git a/tests/unittests/tests-uuid/tests-uuid.c b/tests/unittests/tests-uuid/tests-uuid.c
index 0552d24ae8..aceadf3982 100644
--- a/tests/unittests/tests-uuid/tests-uuid.c
+++ b/tests/unittests/tests-uuid/tests-uuid.c
@@ -95,12 +95,33 @@ void test_uuid_v5(void)
     TEST_ASSERT_EQUAL_INT(uuid_version(&uuid_next), UUID_V5);
 }
 
+void test_uuid_str(void)
+{
+    char str[40];
+    const char dns[] = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
+    uuid_to_string(&uuid_namespace_dns, str);
+    TEST_ASSERT_EQUAL_INT(0, memcmp(dns, str, sizeof(dns)));
+
+    const char url[] = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
+    uuid_to_string(&uuid_namespace_url, str);
+    TEST_ASSERT_EQUAL_INT(0, memcmp(url, str, sizeof(dns)));
+
+    const char iso[] = "6ba7b812-9dad-11d1-80b4-00c04fd430c8";
+    uuid_to_string(&uuid_namespace_iso, str);
+    TEST_ASSERT_EQUAL_INT(0, memcmp(iso, str, sizeof(dns)));
+
+    const char x500[] = "6ba7b814-9dad-11d1-80b4-00c04fd430c8";
+    uuid_to_string(&uuid_namespace_x500, str);
+    TEST_ASSERT_EQUAL_INT(0, memcmp(x500, str, sizeof(dns)));
+}
+
 Test *tests_uuid_all(void)
 {
     EMB_UNIT_TESTFIXTURES(fixtures) {
         new_TestFixture(test_uuid_v3),
         new_TestFixture(test_uuid_v4),
         new_TestFixture(test_uuid_v5),
+        new_TestFixture(test_uuid_str),
     };
 
     EMB_UNIT_TESTCALLER(uuid_tests, NULL, NULL, fixtures);
-- 
GitLab