Add uuid methods to create canonical representation

To enable UUIDs to be printed in canonical form, this commit adds
functions to generate a canonical string from UUID octets in either
standard octet order or GUID octet order.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I43fb5cf82c11cb092ce8497568d6b84cdffaae9b
diff --git a/components/common/uuid/test/uuid_tests.cpp b/components/common/uuid/test/uuid_tests.cpp
index 9a278a6..a568a88 100644
--- a/components/common/uuid/test/uuid_tests.cpp
+++ b/components/common/uuid/test/uuid_tests.cpp
@@ -156,4 +156,26 @@
 
 	uuid_guid_octets_from_canonical(&uuid, "00000000-0000-0000-0000-000000000003");
 	CHECK_FALSE(uuid_is_nil(uuid.octets));
+}
+
+TEST(UuidTests, roundTrip) {
+
+	/* A valid UUID using lower-case */
+	const char *uuid_text = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0";
+	CHECK_TRUE(uuid_is_valid(uuid_text));
+
+	struct uuid_octets uuid;
+	struct uuid_canonical canonical_uuid;
+
+	/* Round trip using standard octet order */
+	uuid_octets_from_canonical(&uuid, uuid_text);
+	uuid_canonical_from_octets(&canonical_uuid, &uuid);
+
+	MEMCMP_EQUAL(uuid_text, canonical_uuid.characters, sizeof(canonical_uuid.characters));
+
+	/* Round trip using GUID octet order */
+	uuid_guid_octets_from_canonical(&uuid, uuid_text);
+	uuid_canonical_from_guid_octets(&canonical_uuid, &uuid);
+
+	MEMCMP_EQUAL(uuid_text, canonical_uuid.characters, sizeof(canonical_uuid.characters));
 }
\ No newline at end of file
diff --git a/components/common/uuid/uuid.c b/components/common/uuid/uuid.c
index 7bf33ed..6d26cfa 100644
--- a/components/common/uuid/uuid.c
+++ b/components/common/uuid/uuid.c
@@ -23,6 +23,20 @@
 	return nibble;
 }
 
+static char nibble_to_hex(uint8_t nibble)
+{
+	char hex;
+
+	nibble &= 0x0f;
+
+	if (nibble <= 9)
+		hex = '0' + nibble;
+	else
+		hex = 'a' + nibble - 10;
+
+	return hex;
+}
+
 static uint8_t hex_to_byte(const char *hex)
 {
 	/* Takes a validated input and returns the byte value */
@@ -35,7 +49,7 @@
 {
 	size_t valid_chars = 0;
 
-	/* Note that a vaild canonical uuid may be part of a longer string
+	/* Note that a valid canonical uuid may be part of a longer string
 	 * such as a urn.
 	 */
 	size_t input_len = strnlen(canonical_form, UUID_CANONICAL_FORM_LEN);
@@ -195,3 +209,38 @@
 
 	assert(valid_chars == UUID_CANONICAL_FORM_LEN);
 }
+
+void uuid_canonical_from_octets(struct uuid_canonical *canonical_form,
+	const struct uuid_octets *uuid_octets)
+{
+	unsigned int octet_index = 0;
+	unsigned int char_index = 0;
+
+	while (octet_index < UUID_OCTETS_LEN) {
+
+		canonical_form->characters[char_index++] =
+			nibble_to_hex(uuid_octets->octets[octet_index] >> 4);
+
+		canonical_form->characters[char_index++] =
+			nibble_to_hex(uuid_octets->octets[octet_index] & 0x0f);
+
+		++octet_index;
+
+		if ((octet_index == 4) ||
+			(octet_index == 6) ||
+			(octet_index == 8) ||
+			(octet_index == 10))
+			canonical_form->characters[char_index++] = '-';
+	}
+
+	canonical_form->characters[char_index] = '\0';
+}
+
+void uuid_canonical_from_guid_octets(struct uuid_canonical *canonical_form,
+	const struct uuid_octets *uuid_octets)
+{
+	struct uuid_octets reversed_octets;
+
+	uuid_reverse_octets(uuid_octets, reversed_octets.octets, sizeof(reversed_octets.octets));
+	uuid_canonical_from_octets(canonical_form, &reversed_octets);
+}
diff --git a/components/common/uuid/uuid.h b/components/common/uuid/uuid.h
index 33921ee..4333ad2 100644
--- a/components/common/uuid/uuid.h
+++ b/components/common/uuid/uuid.h
@@ -101,6 +101,19 @@
 void uuid_guid_octets_from_canonical(struct uuid_octets *uuid_octets,
 	const char *canonical_form);
 
+/*
+ * Converts an octet representation in standard byte order to a canonical string.
+ */
+void uuid_canonical_from_octets(struct uuid_canonical *canonical_form,
+	const struct uuid_octets *uuid_octets);
+
+/*
+ * Converts an octet representation in GUID byte order to a canonical string.
+ */
+void uuid_canonical_from_guid_octets(struct uuid_canonical *canonical_form,
+	const struct uuid_octets *uuid_octets);
+
+
 #ifdef __cplusplus
 }
 #endif