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