2016-02-14 12:01:00 +01:00
|
|
|
module bitmanip;
|
|
|
|
|
|
|
|
private import std.traits : isUnsigned;
|
2016-02-17 02:39:40 +01:00
|
|
|
private import std.bitmanip : nativeToLittleEndian, littleEndianToNative;
|
2016-02-14 12:01:00 +01:00
|
|
|
|
2016-02-16 19:32:34 +01:00
|
|
|
UIntType rotateLeft(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure @safe
|
2016-02-14 12:01:00 +01:00
|
|
|
if(isUnsigned!UIntType)
|
|
|
|
{
|
|
|
|
auto reducedLen = len % (8 * UIntType.sizeof);
|
|
|
|
// TODO: ensure the compiler does not create different code paths here
|
|
|
|
return cast(UIntType)((val << reducedLen) | (val >> (8 * UIntType.sizeof - reducedLen)));
|
|
|
|
}
|
|
|
|
|
|
|
|
unittest
|
|
|
|
{
|
|
|
|
ubyte[] test = [0, 1, 128];
|
|
|
|
assert(test[0].rotateLeft(1) == 0);
|
|
|
|
assert(test[1].rotateLeft(1) == 2);
|
|
|
|
assert(test[2].rotateLeft(1) == 1);
|
|
|
|
assert(test[1].rotateLeft(7) == 128);
|
|
|
|
}
|
|
|
|
|
2016-02-16 19:32:34 +01:00
|
|
|
UIntType rotateRight(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure @safe
|
2016-02-14 12:01:00 +01:00
|
|
|
if(isUnsigned!UIntType)
|
|
|
|
{
|
|
|
|
auto reducedLen = len % (8 * UIntType.sizeof);
|
|
|
|
// TODO: ensure the compiler does not create different code paths here
|
|
|
|
return cast(UIntType)((val >> reducedLen) | (val << (8 * UIntType.sizeof - reducedLen)));
|
|
|
|
}
|
|
|
|
|
|
|
|
unittest
|
|
|
|
{
|
|
|
|
ubyte[] test = [0, 1, 128];
|
|
|
|
assert(test[0].rotateRight(1) == 0);
|
|
|
|
assert(test[1].rotateRight(1) == 128);
|
|
|
|
assert(test[2].rotateRight(1) == 64);
|
|
|
|
assert(test[2].rotateRight(7) == 1);
|
|
|
|
}
|
2016-02-17 02:39:40 +01:00
|
|
|
|
|
|
|
alias littleEndianInv = nativeToLittleEndian;
|
|
|
|
|
|
|
|
uint littleEndian(in ubyte[] input) @safe pure nothrow @nogc
|
|
|
|
in
|
|
|
|
{
|
|
|
|
assert(input.length == uint.sizeof);
|
|
|
|
}
|
|
|
|
body
|
|
|
|
{
|
|
|
|
ubyte[uint.sizeof] buf = input;
|
|
|
|
return littleEndianToNative!uint(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
unittest
|
|
|
|
{
|
|
|
|
ubyte[] test0 = [0, 0, 0, 0];
|
|
|
|
ubyte[] test1 = [86, 75, 30, 9];
|
|
|
|
ubyte[] test2 = [255, 255, 255, 250];
|
|
|
|
assert(littleEndian(test0) == 0x00000000);
|
|
|
|
assert(littleEndian(test1) == 0x091e4b56);
|
|
|
|
assert(littleEndian(test2) == 0xfaffffff);
|
|
|
|
}
|