All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] uuid: Added l_uuid_parse
@ 2019-02-01 13:46 =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  2019-02-01 16:15 ` Marcel Holtmann
  2019-02-01 17:22 ` Denis Kenzior
  0 siblings, 2 replies; 10+ messages in thread
From: =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek @ 2019-02-01 13:46 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 5235 bytes --]

From: Michał Lowas-Rzechonek <michal.lowas-rzechonek@silvair.com>

This commit adds API complementary to l_uuid_to_string, allowing parsing
canonical string representation into a byte array.

I've also changed printf/scanf formatting to use PRIx/SCNx macros, for
better portability.
---
 ell/uuid.c       | 54 ++++++++++++++++++++++++++++++++++++-------
 ell/uuid.h       |  1 +
 unit/test-uuid.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+), 8 deletions(-)

diff --git a/ell/uuid.c b/ell/uuid.c
index a4d72fc..26893a5 100644
--- a/ell/uuid.c
+++ b/ell/uuid.c
@@ -25,6 +25,7 @@
 #endif
 
 #define _GNU_SOURCE
+#include <inttypes.h>
 #include <stdio.h>
 
 #include "checksum.h"
@@ -210,17 +211,54 @@ LIB_EXPORT bool l_uuid_to_string(const uint8_t uuid[16],
 {
 	int n;
 
-	n = snprintf(dest, dest_size, "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-					"%02x%02x-%02x%02x%02x%02x%02x%02x",
-					uuid[0], uuid[1], uuid[2], uuid[3],
-					uuid[4], uuid[5],
-					uuid[6], uuid[7],
-					uuid[8], uuid[9],
-					uuid[10], uuid[11], uuid[12],
-					uuid[13], uuid[14], uuid[15]);
+	n = snprintf(dest, dest_size,
+			"%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "-"
+			"%02" PRIx8 "%02" PRIx8 "-"
+			"%02" PRIx8 "%02" PRIx8 "-"
+			"%02" PRIx8 "%02" PRIx8 "-"
+			"%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "",
+			uuid[0], uuid[1], uuid[2], uuid[3],
+			uuid[4], uuid[5],
+			uuid[6], uuid[7],
+			uuid[8], uuid[9],
+			uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
 
 	if (n < 0 || (size_t) n >= dest_size)
 		return false;
 
 	return true;
 }
+
+LIB_EXPORT bool l_uuid_parse(const char *src, size_t src_size,
+							 uint8_t uuid[16])
+{
+	uint8_t buf[16];
+	int n;
+
+	/*
+	 * textual representation: 32 hex digits + 4 group separators
+	 */
+	if (src_size != 16 * 2 + 4)
+		return false;
+
+	n = sscanf(src,
+			"%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "-"
+			"%02" SCNx8 "%02" SCNx8 "-"
+			"%02" SCNx8 "%02" SCNx8 "-"
+			"%02" SCNx8 "%02" SCNx8 "-"
+			"%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "",
+			&buf[0], &buf[1], &buf[2], &buf[3],
+			&buf[4], &buf[5],
+			&buf[6], &buf[7],
+			&buf[8], &buf[9],
+			&buf[10], &buf[11], &buf[12], &buf[13], &buf[14], &buf[15]);
+
+	if (n != 16)
+		return false;
+
+	if (!l_uuid_is_valid(buf))
+		return false;
+
+	memcpy(uuid, buf, sizeof(buf));
+	return true;
+}
diff --git a/ell/uuid.h b/ell/uuid.h
index 89be520..1cb7923 100644
--- a/ell/uuid.h
+++ b/ell/uuid.h
@@ -53,6 +53,7 @@ bool l_uuid_is_valid(const uint8_t uuid[16]);
 enum l_uuid_version l_uuid_get_version(const uint8_t uuid[16]);
 
 bool l_uuid_to_string(const uint8_t uuid[16], char *dest, size_t dest_size);
+bool l_uuid_parse(const char *src, size_t src_size, uint8_t uuid[16]);
 
 #ifdef __cplusplus
 }
diff --git a/unit/test-uuid.c b/unit/test-uuid.c
index 088d45c..5a4650d 100644
--- a/unit/test-uuid.c
+++ b/unit/test-uuid.c
@@ -158,6 +158,61 @@ static void test_to_string(const void *data)
 	assert(!strcmp(buf, expected_uuid));
 }
 
+static void test_parse_too_short(const void *data)
+{
+	uint8_t uuid[16];
+	const char *string_uuid = "65fcc697-0776-5bf9-8573-72a51080c7d";
+	bool r;
+
+	r = l_uuid_parse(string_uuid, strlen(string_uuid), uuid);
+	assert(!r);
+}
+
+static void test_parse_too_long(const void *data)
+{
+	uint8_t uuid[16];
+	const char *string_uuid = "65fcc697-0776-5bf9-8573-72a51080c7detoolong";
+	bool r;
+
+	r = l_uuid_parse(string_uuid, strlen(string_uuid), uuid);
+	assert(!r);
+}
+
+static void test_parse_invalid_variant(const void *data)
+{
+	uint8_t uuid[16];
+	const char *string_uuid = "65fcc697-0776-5bf9-c573-72a51080c7de";
+	bool r;
+
+	r = l_uuid_parse(string_uuid, strlen(string_uuid), uuid);
+	assert(!r);
+}
+
+static void test_parse_invalid_hex(const void *data)
+{
+	uint8_t uuid[16];
+	const char *string_uuid = "65fcc697-this-isno-tava-lidhexstring";
+	bool r;
+
+	r = l_uuid_parse(string_uuid, strlen(string_uuid), uuid);
+	assert(!r);
+}
+
+static void test_parse(const void *data)
+{
+	uint8_t uuid[16];
+	bool r;
+	const char *string_uuid = "65fcc697-0776-5bf9-8573-72a51080c7de";
+	uint8_t expected_uuid[16] = { 0x65, 0xfc, 0xc6, 0x97, 0x07, 0x76, 0x5b, 0xf9,
+		                          0x85, 0x73, 0x72, 0xa5, 0x10, 0x80, 0xc7, 0xde };
+
+	r = l_uuid_parse(string_uuid, strlen(string_uuid), uuid);
+	assert(r);
+
+	assert(!memcmp(uuid, expected_uuid, sizeof(uuid)));
+
+}
+
 int main(int argc, char *argv[])
 {
 	l_test_init(&argc, &argv);
@@ -169,6 +224,11 @@ int main(int argc, char *argv[])
 
 	l_test_add("/uuid/v5", test_v5, NULL);
 	l_test_add("/uuid/to string", test_to_string, NULL);
+	l_test_add("/uuid/parse too short", test_parse_too_short, NULL);
+	l_test_add("/uuid/parse too long", test_parse_too_long, NULL);
+	l_test_add("/uuid/parse invalid variant", test_parse_invalid_variant, NULL);
+	l_test_add("/uuid/parse invalid hex", test_parse_invalid_hex, NULL);
+	l_test_add("/uuid/parse", test_parse, NULL);
 
 	return l_test_run();
 
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] uuid: Added l_uuid_parse
  2019-02-01 13:46 [PATCH] uuid: Added l_uuid_parse =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
@ 2019-02-01 16:15 ` Marcel Holtmann
  2019-02-01 17:22   ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  2019-02-01 17:22 ` Denis Kenzior
  1 sibling, 1 reply; 10+ messages in thread
From: Marcel Holtmann @ 2019-02-01 16:15 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2315 bytes --]

Hi Michal,

> This commit adds API complementary to l_uuid_to_string, allowing parsing
> canonical string representation into a byte array.

I would have called it l_uuid_from_string.

> I've also changed printf/scanf formatting to use PRIx/SCNx macros, for
> better portability.

This should be a separate patch.

> ---
> ell/uuid.c       | 54 ++++++++++++++++++++++++++++++++++++-------
> ell/uuid.h       |  1 +
> unit/test-uuid.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 107 insertions(+), 8 deletions(-)
> 
> diff --git a/ell/uuid.c b/ell/uuid.c
> index a4d72fc..26893a5 100644
> --- a/ell/uuid.c
> +++ b/ell/uuid.c
> @@ -25,6 +25,7 @@
> #endif
> 
> #define _GNU_SOURCE
> +#include <inttypes.h>
> #include <stdio.h>
> 
> #include "checksum.h"
> @@ -210,17 +211,54 @@ LIB_EXPORT bool l_uuid_to_string(const uint8_t uuid[16],
> {
> 	int n;
> 
> -	n = snprintf(dest, dest_size, "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
> -					"%02x%02x-%02x%02x%02x%02x%02x%02x",
> -					uuid[0], uuid[1], uuid[2], uuid[3],
> -					uuid[4], uuid[5],
> -					uuid[6], uuid[7],
> -					uuid[8], uuid[9],
> -					uuid[10], uuid[11], uuid[12],
> -					uuid[13], uuid[14], uuid[15]);
> +	n = snprintf(dest, dest_size,
> +			"%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "-"
> +			"%02" PRIx8 "%02" PRIx8 "-"
> +			"%02" PRIx8 "%02" PRIx8 "-"
> +			"%02" PRIx8 "%02" PRIx8 "-"
> +			"%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "",
> +			uuid[0], uuid[1], uuid[2], uuid[3],
> +			uuid[4], uuid[5],
> +			uuid[6], uuid[7],
> +			uuid[8], uuid[9],
> +			uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
> 
> 	if (n < 0 || (size_t) n >= dest_size)
> 		return false;
> 
> 	return true;
> }
> +
> +LIB_EXPORT bool l_uuid_parse(const char *src, size_t src_size,
> +							 uint8_t uuid[16])
> +{

Don’t bother with src_size parameter. You can use strlen for that since supporting non null-terminated strings seems rather pointless. You will required space or null terminator at the end of make sscanf actually work correctly anyway. So I would rather check that the string is long enough to hold an actual UUID text representation and that you have a proper terminator at the end.

Regards

Marcel


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] uuid: Added l_uuid_parse
  2019-02-01 13:46 [PATCH] uuid: Added l_uuid_parse =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  2019-02-01 16:15 ` Marcel Holtmann
@ 2019-02-01 17:22 ` Denis Kenzior
  2019-02-01 17:28   ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  2019-02-01 21:14   ` Jan Engelhardt
  1 sibling, 2 replies; 10+ messages in thread
From: Denis Kenzior @ 2019-02-01 17:22 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 508 bytes --]

Hi Michał,

> I've also changed printf/scanf formatting to use PRIx/SCNx macros, for
> better portability

Hmm, portability where?  Is this an actual concern? Any platform that 
ell can actually run on, PRIx/SCNx == 'x', no?

The use of PRI* macros makes the printf statement quite a bit less 
readable IMO.  I can understand the need when using size_t or other 
esoteric types that depend on the arch, but uint8_t isn't one of them...

Anyway, no biggie, just wondering...

Regards,
-Denis

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] uuid: Added l_uuid_parse
  2019-02-01 16:15 ` Marcel Holtmann
@ 2019-02-01 17:22   ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  2019-02-01 17:25     ` Denis Kenzior
  0 siblings, 1 reply; 10+ messages in thread
From: =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek @ 2019-02-01 17:22 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 1217 bytes --]

Hi Marcel,

Thanks for the review. I'll change the name and extract formatting
macros to a separate commit.

On 02/01, Marcel Holtmann wrote:
> > +LIB_EXPORT bool l_uuid_parse(const char *src, size_t src_size,
> > +							 uint8_t uuid[16])
> > +{
> 
> Don’t bother with src_size parameter. You can use strlen for that
> since supporting non null-terminated strings seems rather pointless.
> You will required space or null terminator at the end of make sscanf
> actually work correctly anyway. So I would rather check that the
> string is long enough to hold an actual UUID text representation and
> that you have a proper terminator at the end.

I don't think that's true. Since format passed to scanf expects a fixed
input length, this works as expected:

    const char *string_uuid = "65fcc697-0776-5bf9-8573-72a51080c7detoolong";
    l_uuid_parse(string_uuid, strlen(string_uuid) - strlen('toolong'), uuid);

The use case would be retrieving the UUID from a substring (at given
offset), e.g. from a path. I'll add the unit test for this.

regards
-- 
Michał Lowas-Rzechonek <michal.lowas-rzechonek@silvair.com>
Silvair http://silvair.com
Jasnogórska 44, 31-358 Krakow, POLAND

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] uuid: Added l_uuid_parse
  2019-02-01 17:22   ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
@ 2019-02-01 17:25     ` Denis Kenzior
  2019-02-01 17:29       ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  0 siblings, 1 reply; 10+ messages in thread
From: Denis Kenzior @ 2019-02-01 17:25 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 635 bytes --]

Hi Michał,

> I don't think that's true. Since format passed to scanf expects a fixed
> input length, this works as expected:
> 
>      const char *string_uuid = "65fcc697-0776-5bf9-8573-72a51080c7detoolong";
>      l_uuid_parse(string_uuid, strlen(string_uuid) - strlen('toolong'), uuid);
> 
> The use case would be retrieving the UUID from a substring (at given
> offset), e.g. from a path. I'll add the unit test for this.

But then you know the expected UUID length anyway.  So you can simply 
check that strlen(string_uuid) is at least that long and pass in the 
expected UUID length to sscanf.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] uuid: Added l_uuid_parse
  2019-02-01 17:22 ` Denis Kenzior
@ 2019-02-01 17:28   ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  2019-02-01 17:33     ` Denis Kenzior
  2019-02-01 21:14   ` Jan Engelhardt
  1 sibling, 1 reply; 10+ messages in thread
From: =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek @ 2019-02-01 17:28 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 628 bytes --]

Hi Denis.

On 02/01, Denis Kenzior wrote:
> Hmm, portability where?  Is this an actual concern? Any platform that ell
> can actually run on, PRIx/SCNx == 'x', no?

You're right about PRIx, but it's different for SCN:

#include <stdio.h>
#include <inttypes.h>

int main()
{
    printf("PRIx8=%s, SCNx8=%s\n", PRIx8 "", SCNx8 "");
}

$ ./a.out
PRIx8=x, SCNx8=hhx

I'll drop the change in l_uuid_to_string, but I'd like to keep SCNx,
even though it indeed does look messy.

-- 
Michał Lowas-Rzechonek <michal.lowas-rzechonek@silvair.com>
Silvair http://silvair.com
Jasnogórska 44, 31-358 Krakow, POLAND

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] uuid: Added l_uuid_parse
  2019-02-01 17:25     ` Denis Kenzior
@ 2019-02-01 17:29       ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  0 siblings, 0 replies; 10+ messages in thread
From: =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek @ 2019-02-01 17:29 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 441 bytes --]

Hi Denis,

On 02/01, Denis Kenzior wrote:
> But then you know the expected UUID length anyway.  So you can simply check
> that strlen(string_uuid) is at least that long and pass in the expected UUID
> length to sscanf.

You're right, of course. Silly me. I'll fix the patch accordingly,
thanks.

-- 
Michał Lowas-Rzechonek <michal.lowas-rzechonek@silvair.com>
Silvair http://silvair.com
Jasnogórska 44, 31-358 Krakow, POLAND

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] uuid: Added l_uuid_parse
  2019-02-01 17:28   ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
@ 2019-02-01 17:33     ` Denis Kenzior
  2019-02-01 17:39       ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  0 siblings, 1 reply; 10+ messages in thread
From: Denis Kenzior @ 2019-02-01 17:33 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 218 bytes --]

Hi Michał,

> $ ./a.out
> PRIx8=x, SCNx8=hhx

Ah right.  But then I would just use hhx instead of SCNx8.  There should 
be no portability concerns and it is makes things much more readable.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] uuid: Added l_uuid_parse
  2019-02-01 17:33     ` Denis Kenzior
@ 2019-02-01 17:39       ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
  0 siblings, 0 replies; 10+ messages in thread
From: =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek @ 2019-02-01 17:39 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 462 bytes --]

Denis,

On 02/01, Denis Kenzior wrote:
> Hi Michał,
> 
> > $ ./a.out
> > PRIx8=x, SCNx8=hhx
> 
> Ah right.  But then I would just use hhx instead of SCNx8.  There should be
> no portability concerns and it is makes things much more readable.

Ok, will do.

Too much bare metal does something to one's brain...

-- 
Michał Lowas-Rzechonek <michal.lowas-rzechonek@silvair.com>
Silvair http://silvair.com
Jasnogórska 44, 31-358 Krakow, POLAND

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] uuid: Added l_uuid_parse
  2019-02-01 17:22 ` Denis Kenzior
  2019-02-01 17:28   ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
@ 2019-02-01 21:14   ` Jan Engelhardt
  1 sibling, 0 replies; 10+ messages in thread
From: Jan Engelhardt @ 2019-02-01 21:14 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 639 bytes --]

On Friday 2019-02-01 18:22, Denis Kenzior wrote:

> Hi Michał,
>
>> I've also changed printf/scanf formatting to use PRIx/SCNx macros, for
>> better portability
>
> Hmm, portability where?  Is this an actual concern? Any platform that ell can
> actually run on, PRIx/SCNx == 'x', no?
>
> The use of PRI* macros makes the printf statement quite a bit less readable
> IMO.  I can understand the need when using size_t or other esoteric types that
> depend on the arch, but uint8_t isn't one of them...

size_t isn't esoteric, it has its own standard specifier, %zu.
Unless, of course, you're somehow depending on MSVCRT6...

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-02-01 21:14 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-01 13:46 [PATCH] uuid: Added l_uuid_parse =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
2019-02-01 16:15 ` Marcel Holtmann
2019-02-01 17:22   ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
2019-02-01 17:25     ` Denis Kenzior
2019-02-01 17:29       ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
2019-02-01 17:22 ` Denis Kenzior
2019-02-01 17:28   ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
2019-02-01 17:33     ` Denis Kenzior
2019-02-01 17:39       ` =?unknown-8bit?q?Micha=C5=82?= 'Khorne' Lowas-Rzechonek
2019-02-01 21:14   ` Jan Engelhardt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.