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 11, 2019
1 parent f8196e6 commit fe5c1b9
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 array of ubytes allocated on the GC heap
* References:
* $(LREF hexString)
*/
ubyte[] hexData(const(char)[] s) pure nothrow @safe
{
ubyte[] result;
result.length = (s.length + 1) / 2;
size_t i;

Check warning on line 6165 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6163-L6165

Added lines #L6163 - L6165 were not covered by tests
void append(ubyte u)
{
result[i++] = u;
}

Check warning on line 6169 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6169

Added line #L6169 was not covered by tests

ubyte u;
uint digits;
foreach (char c; s)
{

Check warning on line 6174 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6172-L6174

Added lines #L6172 - L6174 were not covered by tests
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

Check warning on line 6181 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6176-L6181

Added lines #L6176 - L6181 were not covered by tests
{
if (digits)
append(u);
u = 0;
digits = 0;
continue;
}

Check warning on line 6188 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6184-L6188

Added lines #L6184 - L6188 were not covered by tests


if (++digits == 2)
{

Check warning on line 6192 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6192

Added line #L6192 was not covered by tests
append(cast(ubyte)((u << 4) + c));
digits = 0;
}

Check warning on line 6195 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6194-L6195

Added lines #L6194 - L6195 were not covered by tests
else
u = c;
}

Check warning on line 6198 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6198

Added line #L6198 was not covered by tests
if (digits)
append(u);

Check warning on line 6201 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6200-L6201

Added lines #L6200 - L6201 were not covered by tests
return result[0 .. i];
}

Check warning on line 6203 in std/conv.d

View check run for this annotation

Codecov / codecov/patch

std/conv.d#L6203

Added line #L6203 was not covered by tests

///
@safe nothrow unittest
{
static 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 fe5c1b9

Please sign in to comment.