On 12/21/2013 07:57 PM, Ali Çehreli wrote:
On 12/21/2013 05:44 PM, Charles Hixson wrote:
On 12/21/2013 03:52 PM, Ali Çehreli wrote:
On 12/21/2013 03:13 PM, John Colvin wrote:

> Ideally the compiler will optimise your version to be fast, but you may
> find you get better performance by doing the bit manipulations
eplicitly:

Assuming that the program needs to support only big endian and little
endian systems (i.e. excluding systems where no D compiler exists :)),
the following is less wordy and should be equally fast:

import std.bitmanip;
import std.system;

ulong ubytesToUlong(ubyte[] block, size_t n = 0)
in
{
    assert (n >= 0);
    assert (n + 8 <= block.length);
}
body
{
    ulong value = *cast(ulong*)(block.ptr + n);

    if (std.system.endian == Endian.littleEndian) {
        return *cast(ulong*)(value.nativeToBigEndian.ptr);

    } else {
        return value;
    }
}

Ali


Will that work even when the alignment is to odd bytes?  Because that's
the case I was really worried about.  The ubyte array is a packed
mixture of types, some of which are isolated bytes.


No, it is not guaranteed to work unless the alignment is right.

How about this, then: :)

import std.array;

ulong ubytesToUlong(ubyte[] block, size_t n = 0)
in
{
    assert (n >= 0);
    assert (n + 8 <= block.length);
}
body
{
    ulong value = block.front;
    block.popFront();

    foreach (ub; block) {
        value <<= 8;
        value |= ub;
    }

    return value;
}

Ali


Nice, but the block is longer than 8 bytes, so I should use a "for (i = n; i < n + 8; i++)" rather than a foreach, and index off of i. I clearly need to redo the documentation a bit (even though it's form me of a few months from now). It needs to say something like "Convert a 8 byte slice from a ubyte array starting at index n into a ulong." n should always be required to be specified, so I don't want a default value. (0 was used as a test case, because I'd made a really stupid mistake and used "^" for exponentiation, and then couldn't see what was going on, so I was simplifying everything...and I still couldn't see it. Actually the array starts with a ushort, which specifies the number of ulongs to follow before a bunch of bytes that are unintelligible data to the class that's using this function. (OTOH, it seems like something generally useful, so I'll probably put it in a utils.d file, with some other generally useful routines.)

OTOH, if I'm going to consider this to be a general utility function, then I really don't want to make assumptions about where things start, etc. Perhaps I should throw an exception (other than assertion error) if the index is bad or the array is to short for the given index. I need to think about that a bit more. The alternative is to use enforce rather than assertions...though as long as I'm the only user assertions suffice. (It's not going to be separately compiled.)

--
Charles Hixson

Reply via email to