Skip to content

Commit fe5c1b9

Browse files
committed
add std.conv.hexData()
1 parent f8196e6 commit fe5c1b9

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

std/conv.d

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6031,6 +6031,10 @@ Params:
60316031
60326032
Returns:
60336033
a `string`, a `wstring` or a `dstring`, according to the type of hexData.
6034+
6035+
References:
6036+
Prefer using $(LREF hexData) instead, especially if the `hexData` string is long
6037+
because it does not use templates.
60346038
*/
60356039
template hexString(string hexData)
60366040
if (hexData.isHexLiteral)
@@ -6136,6 +6140,88 @@ private auto hexStrLiteral(String)(scope String hexData)
61366140
assert(hexString!"ab cd" == hexString!"ABCD");
61376141
}
61386142

6143+
/************************************************
6144+
* Convert string of `[0-9A-Fa-f]` characters to an array of ubytes.
6145+
*
6146+
* Other characters in the string are considered separators.
6147+
* Adjacent pairs of characters form the nibbles of the ubyte.
6148+
* Non-pairing characters form the low nibble of the ubyte.
6149+
* The returned array does not have a terminating zero appended.
6150+
* The GC is used because `hexData()` is intended to be used
6151+
* at compile time to, for example, initialize manifest constants
6152+
* and statically initialize global variables.
6153+
* Params:
6154+
* s = string of data to convert
6155+
* Returns:
6156+
* unique array of ubytes allocated on the GC heap
6157+
* References:
6158+
* $(LREF hexString)
6159+
*/
6160+
ubyte[] hexData(const(char)[] s) pure nothrow @safe
6161+
{
6162+
ubyte[] result;
6163+
result.length = (s.length + 1) / 2;
6164+
size_t i;
6165+
6166+
void append(ubyte u)
6167+
{
6168+
result[i++] = u;
6169+
}
6170+
6171+
ubyte u;
6172+
uint digits;
6173+
foreach (char c; s)
6174+
{
6175+
if ('0' <= c && c <= '9')
6176+
c -= '0';
6177+
else if ('a' <= c && c <= 'f')
6178+
c -= 'a' - 10;
6179+
else if ('A' <= c && c <= 'F')
6180+
c -= 'A' - 10;
6181+
else
6182+
{
6183+
if (digits)
6184+
append(u);
6185+
u = 0;
6186+
digits = 0;
6187+
continue;
6188+
}
6189+
6190+
6191+
if (++digits == 2)
6192+
{
6193+
append(cast(ubyte)((u << 4) + c));
6194+
digits = 0;
6195+
}
6196+
else
6197+
u = c;
6198+
}
6199+
if (digits)
6200+
append(u);
6201+
6202+
return result[0 .. i];
6203+
}
6204+
6205+
///
6206+
@safe nothrow unittest
6207+
{
6208+
static g1 = hexData("af,fa");
6209+
assert(g1 == [0xAF, 0xFA]);
6210+
6211+
enum a1 = hexData("AAbb");
6212+
assert(a1 == [0xAA, 0xBB]);
6213+
enum a2 = hexData("");
6214+
assert(a2 == []);
6215+
enum a3 = hexData(" \t\r\n");
6216+
assert(a3 == []);
6217+
enum a4 = hexData("f");
6218+
assert(a4 == [0xF]);
6219+
enum a5 = hexData(" f,");
6220+
assert(a5 == [0xF]);
6221+
enum a6 = hexData("0BF ");
6222+
assert(a6 == [0x0B, 0x0F]);
6223+
}
6224+
61396225

61406226
/**
61416227
* Convert integer to a range of characters.

0 commit comments

Comments
 (0)