diff --git a/BitStream.cs b/BitStream.cs index 886c3b2..eb30610 100644 --- a/BitStream.cs +++ b/BitStream.cs @@ -27,9 +27,13 @@ namespace SabreTools.Compression /// /// Create a new BitStream from a source Stream /// +#if NET48 public BitStream(Stream source) +#else + public BitStream(Stream? source) +#endif { - if (!source.CanRead || !source.CanSeek) + if (source == null || !source.CanRead || !source.CanSeek) throw new ArgumentException(nameof(source)); _source = source; @@ -70,7 +74,7 @@ namespace SabreTools.Compression // Get the value by bit-shifting int value = _bitBuffer.Value & 0x01; - _bitBuffer >>= 1; + _bitBuffer = (byte?)(_bitBuffer >> 1); _bitIndex++; // Reset the byte if we're at the end @@ -200,7 +204,11 @@ namespace SabreTools.Compression /// Number of bytes to read /// The next bytes, null on error or end of stream /// Assumes the stream is byte-aligned +#if NET48 public byte[] ReadBytes(int bytes) +#else + public byte[]? ReadBytes(int bytes) +#endif { try { diff --git a/MSZIP/DeflateDecompressor.cs b/MSZIP/DeflateDecompressor.cs index be78f08..17c00fa 100644 --- a/MSZIP/DeflateDecompressor.cs +++ b/MSZIP/DeflateDecompressor.cs @@ -33,7 +33,11 @@ namespace SabreTools.Compression.MSZIP /// Decompress a stream into a byte array /// /// Byte array containing the decompressed data on success, null on error +#if NET48 public byte[] Process() +#else + public byte[]? Process() +#endif { // Try to read the header var blockHeader = ReadBlockHeader(); @@ -50,20 +54,23 @@ namespace SabreTools.Compression.MSZIP { // If stored with no compression case CompressionType.NoCompression: - byte[] bytes00 = ReadNoCompression(); - bytes.AddRange(bytes00); + var bytes00 = ReadNoCompression(); + if (bytes00 != null) + bytes.AddRange(bytes00); break; // If compressed with fixed Huffman codes case CompressionType.FixedHuffman: - byte[] bytes01 = ReadFixedHuffman(); - bytes.AddRange(bytes01); + var bytes01 = ReadFixedHuffman(); + if (bytes01 != null) + bytes.AddRange(bytes01); break; // If compressed with dynamic Huffman codes case CompressionType.DynamicHuffman: - byte[] bytes10 = ReadDynamicHuffman(); - bytes.AddRange(bytes10); + var bytes10 = ReadDynamicHuffman(); + if (bytes10 != null) + bytes.AddRange(bytes10); break; // Reserved is not allowed and is treated as an error @@ -140,7 +147,7 @@ namespace SabreTools.Compression.MSZIP uint[] lengthLengths = new uint[19]; for (int i = 0; i < numLength; i++) { - lengthLengths[BitLengthOrder[i]] = (byte)_bitStream.ReadBitsLSB(3); + lengthLengths[BitLengthOrder[i]] = (byte)(_bitStream.ReadBitsLSB(3) ?? 0); } for (int i = (int)numLength; i < 19; i++) { @@ -169,7 +176,11 @@ namespace SabreTools.Compression.MSZIP /// /// Read an RFC1951 block with no compression /// +#if NET48 private byte[] ReadNoCompression() +#else + private byte[]? ReadNoCompression() +#endif { // Skip any remaining bits in current partially processed byte _bitStream.Discard(); @@ -186,7 +197,11 @@ namespace SabreTools.Compression.MSZIP /// /// Read an RFC1951 block with fixed Huffman compression /// +#if NET48 private byte[] ReadFixedHuffman() +#else + private byte[]? ReadFixedHuffman() +#endif { var bytes = new List(); @@ -204,7 +219,11 @@ namespace SabreTools.Compression.MSZIP /// /// Read an RFC1951 block with dynamic Huffman compression /// +#if NET48 private byte[] ReadDynamicHuffman() +#else + private byte[]? ReadDynamicHuffman() +#endif { // Get the dynamic huffman header (var header, uint numLiteral, uint numDistance) = ReadDynamicHuffmanCompressedBlockHeader(); @@ -220,7 +239,11 @@ namespace SabreTools.Compression.MSZIP /// /// Read an RFC1951 block with Huffman compression /// +#if NET48 private byte[] ReadHuffmanBlock(HuffmanDecoder literalTree, HuffmanDecoder distanceTree) +#else + private byte[]? ReadHuffmanBlock(HuffmanDecoder literalTree, HuffmanDecoder distanceTree) +#endif { // Now loop and decode var bytes = new List(); diff --git a/MSZIP/HuffmanDecoder.cs b/MSZIP/HuffmanDecoder.cs index efd0eac..a962ff5 100644 --- a/MSZIP/HuffmanDecoder.cs +++ b/MSZIP/HuffmanDecoder.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using System.Linq; @@ -15,10 +16,22 @@ namespace SabreTools.Compression.MSZIP /// /// Array representing the number of bits for each value /// Number of Huffman codes encoded +#if NET48 public HuffmanDecoder(int[] lengths, uint numCodes) +#else + public HuffmanDecoder(int[]? lengths, uint numCodes) +#endif { + // Ensure we have lengths + if (lengths == null) + throw new ArgumentNullException(nameof(lengths)); + // Set the root to null for now - _root = null; +#if NET48 + HuffmanNode root = null; +#else + HuffmanNode? root = null; +#endif // Determine the value for max_bits uint max_bits = (uint)lengths.Max(); @@ -66,8 +79,15 @@ namespace SabreTools.Compression.MSZIP continue; // Insert the value starting at the root - _root = Insert(_root, i, len, tree[i]); + root = Insert(root, i, len, tree[i]); } + + // Assign the root value +#if NET48 + _root = root; +#else + _root = root!; +#endif } /// @@ -75,10 +95,22 @@ namespace SabreTools.Compression.MSZIP /// /// Array representing the number of bits for each value /// Number of Huffman codes encoded +#if NET48 public HuffmanDecoder(uint[] lengths, uint numCodes) +#else + public HuffmanDecoder(uint[]? lengths, uint numCodes) +#endif { + // Ensure we have lengths + if (lengths == null) + throw new ArgumentNullException(nameof(lengths)); + // Set the root to null for now - _root = null; +#if NET48 + HuffmanNode root = null; +#else + HuffmanNode? root = null; +#endif // Determine the value for max_bits uint max_bits = lengths.Max(); @@ -128,6 +160,13 @@ namespace SabreTools.Compression.MSZIP // Insert the value starting at the root _root = Insert(_root, i, len, tree[i]); } + + // Assign the root value +#if NET48 + _root = root; +#else + _root = root!; +#endif } /// @@ -139,7 +178,7 @@ namespace SabreTools.Compression.MSZIP { // Start at the root of the tree var node = _root; - while (node.Left != null) + while (node?.Left != null) { // Read the next bit to determine direction byte? nextBit = input.ReadBit(); @@ -154,7 +193,7 @@ namespace SabreTools.Compression.MSZIP } // We traversed to the bottom of the branch - return node.Value; + return node?.Value ?? 0; } /// diff --git a/MSZIP/HuffmanNode.cs b/MSZIP/HuffmanNode.cs index ce02d42..8aede0c 100644 --- a/MSZIP/HuffmanNode.cs +++ b/MSZIP/HuffmanNode.cs @@ -8,12 +8,20 @@ namespace SabreTools.Compression.MSZIP /// /// Left child of the current node /// +#if NET48 public HuffmanNode Left { get; set; } +#else + public HuffmanNode? Left { get; set; } +#endif /// /// Right child of the current node /// +#if NET48 public HuffmanNode Right { get; set; } +#else + public HuffmanNode? Right { get; set; } +#endif /// /// Value of the current node