more OO way to do hex string to bytes conversion
Ali Çehreli
acehreli at yahoo.com
Tue Feb 6 21:56:05 UTC 2018
On 02/06/2018 11:55 AM, Ralph Doncaster wrote:
> I'll have to do some more reading about
> maps. My initial though is they don't seem as readable as loops.
Surprisingly, they may be very easy to read in some situations.
> The chunks() is useful, so for now what I'm going with is:
> ubyte[] arr;
> foreach (b; "deadbeef".chunks(2))
> {
> arr ~= b.to!ubyte(16);
> }
That is great but it has two issues that may be important in some programs:
1) It makes multiple allocations as the array grows
2) You need another loop to to do the actual work later on
If you needed to go through the elements just once, the memory
allocations would be wasted. Instead, you can solve both issues with a
chained expression like the ones that has been shown by others.
The cool thing is, you can always hide the ugly bits in a function.
Starting with ag0aep6g's code, I went overboard to pick a better
destination type (other than ubyte) to support different chunk sizes:
void main()
{
import std.stdio;
foreach (b; "deadbeef".hexValues)
{
writefln("%2X", b);
}
// Works for different sized chunks as well:
writeln("12345678".hexValues!4);
}
auto hexValues(size_t digits = 2, ToType =
DefaultTypeForSize!digits)(string s) {
import std.algorithm: map;
import std.conv: to;
import std.range: chunks;
return s.chunks(digits).map!(chars => chars.to!ToType(16));
}
template DefaultTypeForSize(size_t s) {
static if (s == 1) {
alias DefaultTypeForSize = ubyte;
} else static if (s == 2) {
alias DefaultTypeForSize = ushort;
} else static if (s == 4) {
alias DefaultTypeForSize = uint;
} else static if (s == 8) {
alias DefaultTypeForSize = ulong;
} else {
import std.string : format;
static assert(false, format("There is no default %s-byte type",
s));
}
}
Ali
More information about the Digitalmars-d-learn
mailing list