Skip to content

Commit

Permalink
add std.conv.hexData()
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Oct 3, 2019
1 parent f8196e6 commit 2012455
Showing 1 changed file with 86 additions and 0 deletions.
86 changes: 86 additions & 0 deletions std/conv.d
Original file line number Diff line number Diff line change
Expand Up @@ -6031,6 +6031,10 @@ Params:
Returns:
a `string`, a `wstring` or a `dstring`, according to the type of hexData.
References:
Prefer using $(LREF hexData) instead, especially if the `hexData` string is long
because it does not use templates.
*/
template hexString(string hexData)
if (hexData.isHexLiteral)
Expand Down Expand Up @@ -6136,6 +6140,88 @@ private auto hexStrLiteral(String)(scope String hexData)
assert(hexString!"ab cd" == hexString!"ABCD");
}

/************************************************
* Convert string of `[0-9A-Fa-f]` characters to an array of ubytes.
*
* Other characters in the string are considered separators.
* Adjacent pairs of characters form the nibbles of the ubyte.
* Non-pairing characters form the low nibble of the ubyte.
* The returned array does not have a terminating zero appended.
* The GC is used because `hexData()` is intended to be used
* at compile time to, for example, initialize manifest constants
* and statically initialize global variables.
* Params:
* s = string of data to convert
* Returns:
* unique immutable array of ubytes allocated on the GC heap
* References:
* $(LREF hexString)
*/
immutable(ubyte)[] hexData(const(char)[] s) pure nothrow @trusted
{
ubyte[] result;
result.length = (s.length + 1) / 2;
size_t i;

void append(ubyte u)
{
result[i++] = u;
}

ubyte u;
uint digits;
foreach (char c; s)
{
if ('0' <= c && c <= '9')
c -= '0';
else if ('a' <= c && c <= 'f')
c -= 'a' - 10;
else if ('A' <= c && c <= 'F')
c -= 'A' - 10;
else
{
if (digits)
append(u);
u = 0;
digits = 0;
continue;
}


if (++digits == 2)
{
append(cast(ubyte)((u << 4) + c));
digits = 0;
}
else
u = c;
}
if (digits)
append(u);

return cast(immutable)result[0 .. i];
}

///
@safe nothrow unittest
{
__gshared g1 = hexData("af,fa");
assert(g1 == [0xAF, 0xFA]);

enum a1 = hexData("AAbb");
assert(a1 == [0xAA, 0xBB]);
enum a2 = hexData("");
assert(a2 == []);
enum a3 = hexData(" \t\r\n");
assert(a3 == []);
enum a4 = hexData("f");
assert(a4 == [0xF]);
enum a5 = hexData(" f,");
assert(a5 == [0xF]);
enum a6 = hexData("0BF ");
assert(a6 == [0x0B, 0x0F]);
}


/**
* Convert integer to a range of characters.
Expand Down

0 comments on commit 2012455

Please sign in to comment.