From 73e971fc56eaee59c7f9d8f171511c478ca2989d Mon Sep 17 00:00:00 2001
From: Vincent Dupont <vincent@otakeys.com>
Date: Thu, 20 Sep 2018 19:21:11 +0200
Subject: [PATCH] uuid: add uuid_from_string()

---
 sys/include/uuid.h                      | 14 +++++++--
 sys/uuid/uuid.c                         | 39 +++++++++++++++++++++++++
 tests/unittests/tests-uuid/tests-uuid.c | 13 +++++++++
 3 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/sys/include/uuid.h b/sys/include/uuid.h
index 1c8acb41a9..ac050278aa 100644
--- a/sys/include/uuid.h
+++ b/sys/include/uuid.h
@@ -122,7 +122,7 @@ void uuid_v5(uuid_t *uuid, const uuid_t *ns, const uint8_t *name, size_t len);
  *
  * @return              Version number
  */
-static inline unsigned uuid_version(uuid_t *uuid)
+static inline unsigned uuid_version(const uuid_t *uuid)
 {
     uint16_t time_hi_vers = byteorder_ntohs(uuid->time_hi);
 
@@ -137,7 +137,7 @@ static inline unsigned uuid_version(uuid_t *uuid)
  *
  * @return              True when equal
  */
-static inline bool uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
+static inline bool uuid_equal(const uuid_t *uuid1, const uuid_t *uuid2)
 {
     return (memcmp(uuid1, uuid2, sizeof(uuid_t)) == 0);
 }
@@ -150,6 +150,16 @@ static inline bool uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
  */
 void uuid_to_string(const uuid_t *uuid, char *str);
 
+/**
+ * @brief   Populate an UUID structure from an UUID string
+ *
+ * @param[out]  uuid    out UUID
+ * @param[in]   str     null-terminated input UUID string, must be UUID_STR_LEN bytes
+ *
+ * @return 0 on succes, < 0 if @p str is not valid
+ */
+int uuid_from_string(uuid_t *uuid, const char *str);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sys/uuid/uuid.c b/sys/uuid/uuid.c
index aeb94e28b4..464586dcbe 100644
--- a/sys/uuid/uuid.c
+++ b/sys/uuid/uuid.c
@@ -128,3 +128,42 @@ void uuid_to_string(const uuid_t *uuid, char *str)
     *p = '\0';
     fmt_to_lower(str, str);
 }
+
+int uuid_from_string(uuid_t *uuid, const char *str)
+{
+    uint32_t tmp;
+    if (fmt_strlen(str) < UUID_STR_LEN) {
+        return -1;
+    }
+    tmp = scn_u32_hex(str, 8);
+    uuid->time_low = byteorder_htonl(tmp);
+    str += 8;
+    if (*str++ != '-') {
+        return -2;
+    }
+    tmp = scn_u32_hex(str, 4);
+    uuid->time_mid = byteorder_htons(tmp);
+    str += 4;
+    if (*str++ != '-') {
+        return -2;
+    }
+    tmp = scn_u32_hex(str, 4);
+    uuid->time_hi = byteorder_htons(tmp);
+    str += 4;
+    if (*str++ != '-') {
+        return -2;
+    }
+    uuid->clk_seq_hi_res = scn_u32_hex(str, 2);
+    str += 2;
+    uuid->clk_seq_low = scn_u32_hex(str, 2);
+    str += 2;
+    if (*str++ != '-') {
+        return -2;
+    }
+    for (unsigned i = 0; i < UUID_NODE_LEN; i++) {
+        uuid->node[i] = scn_u32_hex(str, 2);
+        str += 2;
+    }
+
+    return 0;
+}
diff --git a/tests/unittests/tests-uuid/tests-uuid.c b/tests/unittests/tests-uuid/tests-uuid.c
index aceadf3982..f0b98bd8c9 100644
--- a/tests/unittests/tests-uuid/tests-uuid.c
+++ b/tests/unittests/tests-uuid/tests-uuid.c
@@ -113,6 +113,19 @@ void test_uuid_str(void)
     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)));
+
+    uuid_t uuid;
+    TEST_ASSERT_EQUAL_INT(0, uuid_from_string(&uuid, dns));
+    TEST_ASSERT_EQUAL_INT(true, uuid_equal(&uuid, &uuid_namespace_dns));
+
+    TEST_ASSERT_EQUAL_INT(0, uuid_from_string(&uuid, url));
+    TEST_ASSERT_EQUAL_INT(true, uuid_equal(&uuid, &uuid_namespace_url));
+
+    TEST_ASSERT_EQUAL_INT(0, uuid_from_string(&uuid, iso));
+    TEST_ASSERT_EQUAL_INT(true, uuid_equal(&uuid, &uuid_namespace_iso));
+
+    TEST_ASSERT_EQUAL_INT(0, uuid_from_string(&uuid, x500));
+    TEST_ASSERT_EQUAL_INT(true, uuid_equal(&uuid, &uuid_namespace_x500));
 }
 
 Test *tests_uuid_all(void)
-- 
GitLab