diff --git a/BitStream.cs b/BitStream.cs deleted file mode 100644 index 3d54d86..0000000 --- a/BitStream.cs +++ /dev/null @@ -1,239 +0,0 @@ -using System; -using System.IO; -using SabreTools.IO; - -// TODO: Add more complete implementation to SabreTools.IO -namespace SabreTools.Compression -{ - /// - /// Wrapper to allow reading bits from a source stream - /// - public class BitStream - { - /// - public long Position => _source.Position; - - /// - public long Length => _source.Length; - - /// - /// Original stream source - /// - private readonly Stream _source; - - /// - /// Last read byte value from the stream - /// - private byte? _bitBuffer; - - /// - /// Index in the byte of the current bit - /// - private int _bitIndex; - - /// - /// Create a new BitStream from a source Stream - /// - public BitStream(Stream? source) - { - if (source == null || !source.CanRead || !source.CanSeek) - throw new ArgumentException(nameof(source)); - - _source = source; - _bitBuffer = null; - _bitIndex = 0; - } - - /// - /// Discard the current cached byte - /// - public void Discard() - { - _bitBuffer = null; - _bitIndex = 0; - } - - /// - /// Read a single bit, if possible - /// - /// The next bit encoded in a byte, null on error or end of stream - public byte? ReadBit() - { - // If we reached the end of the stream - if (_source.Position >= _source.Length) - return null; - - // If we don't have a value cached - if (_bitBuffer == null) - { - // Read the next byte, if possible - _bitBuffer = ReadSourceByte(); - if (_bitBuffer == null) - return null; - - // Reset the bit index - _bitIndex = 0; - } - - // Get the value by bit-shifting - int value = _bitBuffer.Value & 0x01; - _bitBuffer = (byte?)(_bitBuffer >> 1); - _bitIndex++; - - // Reset the byte if we're at the end - if (_bitIndex >= 8) - Discard(); - - return (byte)value; - } - - /// - /// Read a multiple bits in LSB, if possible - /// - /// The next bits encoded in a UInt32, null on error or end of stream - public uint? ReadBitsLSB(int bits) - { - uint value = 0; - for (int i = 0; i < bits; i++) - { - // Read the next bit - byte? bitValue = ReadBit(); - if (bitValue == null) - return null; - - // Add the bit shifted by the current index - value += (uint)(bitValue.Value << i); - } - - return value; - } - - /// - /// Read a multiple bits in MSB, if possible - /// - /// The next bits encoded in a UInt32, null on error or end of stream - public uint? ReadBitsMSB(int bits) - { - uint value = 0; - for (int i = 0; i < bits; i++) - { - // Read the next bit - byte? bitValue = ReadBit(); - if (bitValue == null) - return null; - - // Add the bit shifted by the current index - value += (value << 1) + bitValue.Value; - } - - return value; - } - - /// - /// Read a byte, if possible - /// - /// The next byte, null on error or end of stream - /// Assumes the stream is byte-aligned - public byte? ReadByte() - { - try - { - Discard(); - return _source.ReadByteValue(); - } - catch - { - return null; - } - } - - /// - /// Read a UInt16, if possible - /// - /// The next UInt16, null on error or end of stream - /// Assumes the stream is byte-aligned - public ushort? ReadUInt16() - { - try - { - Discard(); - return _source.ReadUInt16(); - } - catch - { - return null; - } - } - - /// - /// Read a UInt32, if possible - /// - /// The next UInt32, null on error or end of stream - /// Assumes the stream is byte-aligned - public uint? ReadUInt32() - { - try - { - Discard(); - return _source.ReadUInt32(); - } - catch - { - return null; - } - } - - /// - /// Read a UInt64, if possible - /// - /// The next UInt64, null on error or end of stream - /// Assumes the stream is byte-aligned - public ulong? ReadUInt64() - { - try - { - Discard(); - return _source.ReadUInt64(); - } - catch - { - return null; - } - } - - /// - /// Read bytes, if possible - /// - /// Number of bytes to read - /// The next bytes, null on error or end of stream - /// Assumes the stream is byte-aligned - public byte[]? ReadBytes(int bytes) - { - try - { - Discard(); - return _source.ReadBytes(bytes); - } - catch - { - return null; - } - } - - /// - /// Read a single byte from the underlying stream, if possible - /// - /// The next full byte from the stream, null on error or end of stream - private byte? ReadSourceByte() - { - try - { - return _source.ReadByteValue(); - } - catch - { - return null; - } - } - } -} \ No newline at end of file diff --git a/LZ/Decompressor.cs b/LZ/Decompressor.cs index 3d7aae5..70543fd 100644 --- a/LZ/Decompressor.cs +++ b/LZ/Decompressor.cs @@ -1,7 +1,7 @@ using System.IO; using System.Linq; using System.Text; -using SabreTools.IO; +using SabreTools.IO.Extensions; using SabreTools.Models.Compression.LZ; using static SabreTools.Models.Compression.LZ.Constants; diff --git a/MSZIP/DeflateDecompressor.cs b/MSZIP/DeflateDecompressor.cs index aba582e..34d8060 100644 --- a/MSZIP/DeflateDecompressor.cs +++ b/MSZIP/DeflateDecompressor.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using SabreTools.IO.Streams; using SabreTools.Models.Compression.MSZIP; using static SabreTools.Models.Compression.MSZIP.Constants; @@ -13,7 +14,7 @@ namespace SabreTools.Compression.MSZIP /// /// Internal bitstream to use for decompression /// - private readonly BitStream _bitStream; + private readonly ReadOnlyBitStream _bitStream; /// /// Create a new Decompressor from a byte array @@ -28,8 +29,8 @@ namespace SabreTools.Compression.MSZIP // Create a memory stream to wrap var ms = new MemoryStream(input); - // Wrap the stream in a BitStream - _bitStream = new BitStream(ms); + // Wrap the stream in a ReadOnlyBitStream + _bitStream = new ReadOnlyBitStream(ms); } /// @@ -42,8 +43,8 @@ namespace SabreTools.Compression.MSZIP if (input == null || !input.CanRead || !input.CanSeek) throw new ArgumentException(nameof(input)); - // Wrap the stream in a BitStream - _bitStream = new BitStream(input); + // Wrap the stream in a ReadOnlyBitStream + _bitStream = new ReadOnlyBitStream(input); } /// diff --git a/MSZIP/HuffmanDecoder.cs b/MSZIP/HuffmanDecoder.cs index 8dbb8d0..1f954b8 100644 --- a/MSZIP/HuffmanDecoder.cs +++ b/MSZIP/HuffmanDecoder.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using SabreTools.IO.Streams; namespace SabreTools.Compression.MSZIP { @@ -83,7 +84,7 @@ namespace SabreTools.Compression.MSZIP /// /// BitStream representing the input /// Value of the node described by the input - public int Decode(BitStream input) + public int Decode(ReadOnlyBitStream input) { // Start at the root of the tree var node = _root; diff --git a/Quantum/Decompressor.cs b/Quantum/Decompressor.cs index abdd674..dc7d752 100644 --- a/Quantum/Decompressor.cs +++ b/Quantum/Decompressor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using SabreTools.IO.Streams; using SabreTools.Models.Compression.Quantum; using static SabreTools.Compression.Quantum.Constants; @@ -12,7 +13,7 @@ namespace SabreTools.Compression.Quantum /// /// Internal bitstream to use for decompression /// - private BitStream _bitStream; + private readonly ReadOnlyBitStream _bitStream; #region Models @@ -100,8 +101,8 @@ namespace SabreTools.Compression.Quantum // Create a memory stream to wrap var ms = new MemoryStream(input); - // Wrap the stream in a BitStream - _bitStream = new BitStream(ms); + // Wrap the stream in a ReadOnlyBitStream + _bitStream = new ReadOnlyBitStream(ms); // Initialize literal models this._model0 = CreateModel(0, 64); @@ -140,8 +141,8 @@ namespace SabreTools.Compression.Quantum if (windowBits < 10 || windowBits > 21) throw new ArgumentOutOfRangeException(nameof(windowBits)); - // Wrap the stream in a BitStream - _bitStream = new BitStream(input); + // Wrap the stream in a ReadOnlyBitStream + _bitStream = new ReadOnlyBitStream(input); // Initialize literal models this._model0 = CreateModel(0, 64);