Byte Order Swapping Function
Andrew Wiley
wiley.andrew.j at gmail.com
Sat Jul 16 23:31:09 PDT 2011
On Sat, Jul 16, 2011 at 2:51 PM, Jonathan M Davis <jmdavisProg at gmx.com>wrote:
> On Saturday 16 July 2011 15:38:29 Andrei Alexandrescu wrote:
> > Just paste the code here.
>
> This is what I have at the moment:
>
> import core.bitop;
>
> /++
> Swaps the endianness of the given value. Any integral value,
> character, or floating point value is accepted.
> +/
> T swapEndian(T)(T val)
> if(isNumeric!T || isSomeChar!T)
> {
> static if(val.sizeof == 1)
> return val;
> else static if(isUnsigned!T || isFloatingPoint!T)
> return swapEndianImpl(val);
> else static if(isIntegral!T)
> return swapEndianImpl(cast(Unsigned!T) val);
> else static if(is(Unqual!T == wchar))
> return cast(T)swapEndian(cast(ushort)val);
> else static if(is(Unqual!T == dchar))
> return cast(T)swapEndian(cast(uint)val);
> else
> static assert(0, T.stringof ~ " unsupported by swapEndian.");
> }
>
> private T swapEndianImpl(T)(T val)
> if(is(Unqual!T == ushort))
> {
> return ((val & 0xff00U) >> 8) |
> ((val & 0x00ffU) << 8);
> }
>
> private T swapEndianImpl(T)(T val)
> if(is(Unqual!T == uint))
> {
> return bswap(val);
> }
>
> private T swapEndianImpl(T)(T val)
> if(is(Unqual!T == ulong))
> {
> return ((val & 0xff00000000000000UL) >> 56) |
> ((val & 0x00ff000000000000UL) >> 40) |
> ((val & 0x0000ff0000000000UL) >> 24) |
> ((val & 0x000000ff00000000UL) >> 8) |
> ((val & 0x00000000ff000000UL) << 8) |
> ((val & 0x0000000000ff0000UL) << 24) |
> ((val & 0x000000000000ff00UL) << 40) |
> ((val & 0x00000000000000ffUL) << 56);
> }
>
> private T swapEndianImpl(T)(T val)
> if(isFloatingPoint!T)
> {
> import std.algorithm;
>
> union Union
> {
> Unqual!T _floating;
> ubyte[T.sizeof] _array;
> }
>
> Union u;
> u._floating = val;
> std.algorithm.reverse(u._array[]);
>
> return u._floating;
> }
>
> unittest
> {
> import std.stdio;
> import std.typetuple;
>
> foreach(T; TypeTuple!(byte, ubyte, short, ushort, int, uint, long,
> ulong,
> char, wchar, dchar, float, double, real))
> {
> scope(failure) writefln("Failed type: %s", T.stringof);
> T val;
> const T cval;
> immutable T ival;
>
> assert(swapEndian(swapEndian(val)) == val);
> assert(swapEndian(swapEndian(cval)) == cval);
> assert(swapEndian(swapEndian(ival)) == ival);
> assert(swapEndian(swapEndian(T.min)) == T.min);
> assert(swapEndian(swapEndian(T.max)) == T.max);
> static if(isSigned!T) assert(swapEndian(swapEndian(cast(T)0)) == 0);
> }
> }
>
>
> I think that the problem is a combination of NaN and real. If I change the
> first three tests (which all test using init) to use is, then all of the
> tests
> pass until real is tested with T.max, and it's doesn't survive being
> swapped
> twice). So, maybe something special needs to be done for NaN, and the issue
> with real may involve issues with padding. I don't know.
>
> - Jonathan M Davis
>
Take a look at http://www.dmh2000.com/cpp/dswap.shtml . It made the odd
behavior make a lot more sense to me.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20110716/7889a3be/attachment.html>
More information about the Digitalmars-d
mailing list