public DebugBinaryNumber Read(int bits) { if (bits < 0 || position + bits > length) { throw new ArgumentOutOfRangeException($"Attempting to read {bits} bits, but there's only {bitsLeft} bits left"); } DebugBinaryNumber value = 0; //For every bit we want to read... for (int i = 0; i < bits; i++) { //...first, get the byte we are currently reading from... DebugBinaryNumber @byte = data[byteIndex]; //...and then get the appropiate bit from that byte DebugBinaryNumber mask = MaskUtility.MakeShifted(bitIndex); DebugBinaryNumber bit = @byte & mask; //Put the bit into the correct position be want to write int shiftAmount = i - bitIndex; if (shiftAmount < 0) { bit >>= -shiftAmount; } else { bit <<= shiftAmount; } //And write that bit into the final value value |= bit; //Update the bit and byte we next have to read from bitIndex++; if (bitIndex == 8) { byteIndex++; bitIndex = 0; } } return(value); }
//Transforms the first "bits" into an array of bytes public byte[] GetBytes(int bits) { if (bits < 0 || bits > 64) { throw new ArgumentOutOfRangeException(nameof(bits), $"Must be 0 < {nameof(bits)} < 64"); } int length = (int)Math.Ceiling((float)bits / bitsPerByte); byte[] bytes = new byte[length]; //clamp value to the bits we were asked for DebugBinaryNumber clampedValue = value & MaskUtility.MakeFilled(bits); //Here we shift packs of 8 bits to the right so that we can get that particular byte value for (int i = 0; i < length; i++) { bytes[i] = clampedValue; clampedValue >>= bitsPerByte; } return(bytes); }