Byte Order Swapping Function

Christian Manning cmanning999 at gmail.com
Sun Jul 17 06:27:27 PDT 2011


How about this?:

private template Eqsize(T) {
    static if (T.sizeof == 4) {
        alias uint S;
    }
    else static if (T.sizeof == 8) {
        alias ulong S;
    }
}

private union IntFloat {
    uint _int;
    float _float;
}

private union IntDouble {
    ulong _long;
    double _double;
}

T byteSwap(T)(T val) if (isIntegral!T || isSomeChar!T) {
    static if (T.sizeof == 2) {
        return cast(T) ((cast(ushort) val >> 8) | (cast(ushort) val << 8));
    }
    else static if (T.sizeof == 4) {
        return cast(T) bswap(cast(uint) val);
    }
    else static if (T.sizeof == 8) {
        return cast(T)bswap(cast(uint) (val >> 32)) |
            (cast(T)bswap(cast(uint) val) << 32);
    }
}

Eqsize!(T).S byteSwap(T)(T val) if (isFloatingPoint!T) {
    static if (T.sizeof == 4) {
        IntFloat _if;
        _if._float = val;
        _if._int = bswap(_if._int);
        return _if._int;
    }
    else static if (T.sizeof == 8) {
        IntDouble id;
        id._double = val;
        id._long = byteSwap(id._long);
        return id._long;
    }
}

unittest {
    float a = 45.17249;
    IntFloat _if;
    _if._int = byteSwap(byteSwap(a));
    assert(a is _if._float);
    assert(a == _if._float);

    double b = 835.48502;
    IntDouble id;
    id._long = cast(ulong) byteSwap(byteSwap(b));
    assert(b is id._double);
    assert(b == id._double);

    long c = 0x0102040880402010;
    long d = 0x1020408008040201;
    assert(byteSwap(c) == d);
    assert(byteSwap(c) is d);
    assert(byteSwap(byteSwap(c)) == c);
    assert(byteSwap(byteSwap(c)) is c);

    assert(byteSwap(cast(short) -45) == -11265);
    assert(byteSwap(cast(short) -45) is -11265);

    assert(byteSwap(0x18244281) == 0x81422418);
    assert(byteSwap(0x18244281) is 0x81422418);
}

T bigEndianToNative(T)(T val) if (isNumeric!T || isSomeChar!T) {
    static if (endian == Endian.BigEndian) {
        return val;
    }
    else {
        return byteSwap(val);
    }
}

alias bigEndianToNative nativeToBigEndian;

T littleEndianToNative(T)(T val) if (isNumeric!T || isSomeChar!T) {
    static if (endian == Endian.LittleEndian) {
        return val;
    }
    else {
        return byteSwap(val);
    }
}

alias littleEndianToNative nativeToLittleEndian;


More information about the Digitalmars-d mailing list