Byte Order Swapping Function

Jonathan M Davis jmdavisProg at gmx.com
Sat Jul 16 23:42:17 PDT 2011


On Saturday 16 July 2011 23:31:09 Andrew Wiley wrote:
> 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.

Okay. Good to know. In other words, we can't have swapEndian work with floating 
point values like that. It can generate a byte array from them (or maybe an 
integral value of the same size), but it can't generate another floating point 
value. Bleh. Okay. Floating point values with have to use an entirely different 
overload then. Thanks for the info.

- Jonathan M Davis


More information about the Digitalmars-d mailing list