When working with various sources of data, one often gets UUIDs as strings in differing formats. Often, they come without dashes, or maybe dashes in non-standard locations. I wish UUID would be more lenient in accepting those strings.
So I decided to take a look at the code, and it seemed easy enough to handle arbitrary formats. I coded up a fix, but ran into some issues building swift-corelibs-foundation
.
Before I go to the trouble of getting it to build, would such an enhancement be accepted?
Here's the as-yet uncompiled and untested change to uuid_parse()
I would offer in a PR. Basically, if the existing parsing fails, I'll copy the input string, stripping it of anything not in [0-9a-fA-F]
, and try again. I think it would be cleaner to just do that always, but there's a slight performance hit with the stripping for preferred-formatted input that someone might object to.
int
uuid_parse(const uuid_string_t in, uuid_t uu)
{
int n = 0;
sscanf(in,
"%2hhx%2hhx%2hhx%2hhx-"
"%2hhx%2hhx-"
"%2hhx%2hhx-"
"%2hhx%2hhx-"
"%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%n",
&uu[0], &uu[1], &uu[2], &uu[3],
&uu[4], &uu[5],
&uu[6], &uu[7],
&uu[8], &uu[9],
&uu[10], &uu[11], &uu[12], &uu[13], &uu[14], &uu[15], &n);
if (n == 36 && in[n] == '\0') {
return 0;
}
// Parsing the above failed, so strip anything not in [0-9a-f]
// and try again…
char stripped[37];
int i = 0;
int j = 0;
while (in[j] != '\0' && i < sizeof (stripped) && j < 37) {
if ( '0' <= in[j] <= '9' || 'a' <= in[j] <= 'f' || 'A' <= in[j] <= 'F') {
stripped[i++] = in[j];
}
j += 1;
}
stripped[i] = '\0';
sscanf(stripped,
"%2hhx%2hhx%2hhx%2hhx"
"%2hhx%2hhx"
"%2hhx%2hhx"
"%2hhx%2hhx"
"%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%n",
&uu[0], &uu[1], &uu[2], &uu[3],
&uu[4], &uu[5],
&uu[6], &uu[7],
&uu[8], &uu[9],
&uu[10], &uu[11], &uu[12], &uu[13], &uu[14], &uu[15], &n);
if (n == 32 && stripped[n] == '\0') {
return 0;
}
return -1;
}
Edit: Alternatively, and perhaps better, would be to add UUID(string:String)
to the Swift class, that accepts an arbitrary string.