On 2/6/18 1:46 PM, H. S. Teoh wrote:
Of course, this eagerly constructs an array to store the result, which
allocates, and also requires the hex string to be fully constructed
first.  You can make this code lazy by turning it into a range
algorithm, then you can actually generate the hex digits lazily from
somewhere else, and process the output bytes as they are generated, no
allocation necessary:

        /* Run this example by putting this in a file called 'test.d'
         * and invoking `dmd -unittest -main -run test.d`
         */
        import std.array;
        import std.algorithm;
        import std.conv;
        import std.format;
        import std.range;
        import std.stdio;

        auto hexToBytes(R)(R hex)
                if (isInputRange!R && is(ElementType!R : dchar))
        {
                return hex.chunks(2)
                          .map!(s => s.to!ubyte(16));
        }

        unittest
        {
                // Infinite stream of hex digits
                auto digits = "0123456789abcdef".cycle;

                digits.take(100)        // take the first 100 digits
                      .hexToBytes       // turn them into bytes
                      .map!(b => format("%02X", b)) // print in uppercase
                      .joiner(" ")    // nicely delimit bytes with spaces
                      .chain("\n")    // end with a nice newline
                      .copy(stdout.lockingTextWriter);
                                        // write output directly to stdout

Hm... format in a loop? That returns strings, and allocates. Yuck! ;)

writefln("%(%02X %)", digits.take(100).hexToBytes);

-Steve

Reply via email to