string to character code hex string
    Moritz Maxeiner via Digitalmars-d-learn 
    digitalmars-d-learn at puremagic.com
       
    Sat Sep  2 10:45:30 PDT 2017
    
    
  
On Saturday, 2 September 2017 at 16:23:57 UTC, bitwise wrote:
> On Saturday, 2 September 2017 at 15:53:25 UTC, bitwise wrote:
>> [...]
>
> This seems to work well enough.
>
> string toAsciiHex(string str)
> {
>     import std.array : appender;
>
>     auto ret = appender!string(null);
>     ret.reserve(str.length * 2);
>     foreach(c; str) ret.put(format!"%x"(c));
>     return ret.data;
> }
Note: Each of those format calls is going to allocate a new 
string, followed by put copying that new string's content over 
into the appender, leaving you with \theta(str.length) tiny 
memory chunks that aren't used anymore for the GC to eventually 
collect.
If this (unnecessary waste) is of concern to you (and from the 
fact that you used ret.reserve I assume it is), then the easy fix 
is to use `sformat` instead of `format`:
---
string toHex(string str)
{
	import std.format : sformat;
	import std.exception: assumeUnique;
	auto   ret = new char[str.length * 2];
	size_t len;
	foreach (c; str)
	{
		auto slice = sformat!"%x"(ret[len..$], c);
		//auto slice = toHex(ret[len..$], c);
		assert (slice.length <= 2);
		len += slice.length;
	}
	
	return ret[0..len].assumeUnique;
}
---
If you want to cut out the format import entirely, notice the 
`auto slice = toHex...` line, which can be implemented like this 
(always returns two chars):
---
char[] toHex(char[] buf, char c)
{
	import std.ascii : lowerHexDigits;
	assert (buf.length >= 2);
	buf[0] = lowerHexDigits[(c & 0xF0) >> 4];
	buf[1] = lowerHexDigits[c & 0x0F];
	return buf[0..2];
}
---
    
    
More information about the Digitalmars-d-learn
mailing list