1 module zgrf.bits; 2 3 import std.bitmanip; 4 5 /** 6 * Allocates a new [BitArray] of given count. 7 * 8 * Params: 9 * count = The amount of bits in the [BitArray] 10 * 11 * Returns: 12 * The new [BitArray] 13 */ 14 BitArray bitArrayOfSize(ulong count) pure 15 { 16 bool[] buffer = new bool[count]; 17 return BitArray(buffer); 18 } 19 20 /** 21 * Converts ubyte[] to [BitArray]. 22 * 23 * Params: 24 * byteArr = The input ubyte[] to convert to a [BitArray] 25 * 26 * Returns: 27 * The converted [BitArray] 28 * 29 * See_Also: 30 * [toByteArray] 31 */ 32 BitArray toBitArray(const ubyte[] byteArr) pure 33 { 34 auto bitArr = bitArrayOfSize(8 * byteArr.length); 35 for (int i = 0; i < byteArr.length; ++i) 36 { 37 bitArr[8 * i + 0] = (byteArr[i] & 128) != 0; 38 bitArr[8 * i + 1] = (byteArr[i] & 64) != 0; 39 bitArr[8 * i + 2] = (byteArr[i] & 32) != 0; 40 bitArr[8 * i + 3] = (byteArr[i] & 16) != 0; 41 bitArr[8 * i + 4] = (byteArr[i] & 8) != 0; 42 bitArr[8 * i + 5] = (byteArr[i] & 4) != 0; 43 bitArr[8 * i + 6] = (byteArr[i] & 2) != 0; 44 bitArr[8 * i + 7] = (byteArr[i] & 1) != 0; 45 } 46 return bitArr; 47 } 48 49 /** 50 * Converts a [BitArray] to ubyte[]. 51 * 52 * The input must be a multiple of 8 bytes. There is no bounds 53 * check and no padding will be done. 54 * 55 * Params: 56 * bitArr = The [BitArray] to convert to ubyte[] 57 * 58 * Returns: 59 * Converted byte array 60 * 61 * See_Also: 62 * [toBitArray] 63 */ 64 ubyte[] toByteArray(const ref BitArray bitArr) pure 65 in (bitArr.length % 8 == 0, "Length of BitArray must be multiple of 8 bytes") 66 { 67 const size_t length = bitArr.length / 8; 68 ubyte[] arr = new ubyte[length]; 69 foreach (i; 0 .. length) 70 { 71 const j = i * 8; 72 arr[i] = bitArr[j] << 7 | 73 bitArr[j + 1] << 6 | 74 bitArr[j + 2] << 5 | 75 bitArr[j + 3] << 4 | 76 bitArr[j + 4] << 3 | 77 bitArr[j + 5] << 2 | 78 bitArr[j + 6] << 1 | 79 bitArr[j + 7]; 80 } 81 82 return arr; 83 } 84 85 /** 86 * Shifts the first length bits of the source [BitArray] by numBits 87 * and stores it into the target [BitArray]. 88 * 89 * Parameter length must be less than or equal to the source and target length. 90 * 91 * Params: 92 * source = Shift the bits given by this [BitArray] 93 * length = Defines how many bits to shift from the source. Cannot be higher than source/target length 94 * numBits = Defines the shift amount for each bit 95 * target = The output [BitArray] to store the shifted result to 96 */ 97 void shiftLeft(const ref BitArray source, size_t length, size_t numBits, ref BitArray target) pure 98 in (source.length >= length, "Source length is too short") 99 in (target.length >= length, "Target length is too short") 100 { 101 for (size_t p = 0; p < length; ++p) 102 { 103 target[p] = source[(p + numBits) % length]; 104 } 105 } 106 107 /** 108 * Swaps the nibbles of the input data. 109 * 110 * E.g. 0xABCDEF becomes 0xBADCFE 111 * 112 * Params: 113 * data = Input/Output that will be modified 114 */ 115 void swapNibbles(ref ubyte[] data) pure nothrow @safe @nogc 116 { 117 foreach (i; 0 .. data.length) 118 { 119 data[i] = ((data[i] << 4) & 0xFF) | ((data[i] >> 4) & 0xFF); 120 } 121 }