ubytes to ulong problem

Charles Hixson charleshixsn at earthlink.net
Sun Dec 22 01:04:41 PST 2013


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



More information about the Digitalmars-d-learn mailing list