mirror of
https://github.com/SabreTools/SabreTools.Compression.git
synced 2026-02-05 21:30:01 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07b50e8c46 | ||
|
|
8eb82384d6 | ||
|
|
dd6cc0e2f3 | ||
|
|
58502e0362 |
@@ -33,11 +33,7 @@ namespace SabreTools.Compression
|
||||
/// <summary>
|
||||
/// Create a new BitStream from a source Stream
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public BitStream(Stream source)
|
||||
#else
|
||||
public BitStream(Stream? source)
|
||||
#endif
|
||||
{
|
||||
if (source == null || !source.CanRead || !source.CanSeek)
|
||||
throw new ArgumentException(nameof(source));
|
||||
@@ -210,11 +206,7 @@ namespace SabreTools.Compression
|
||||
/// <param name="bytes">Number of bytes to read</param>
|
||||
/// <returns>The next <paramref name="bytes"/> bytes, null on error or end of stream</returns>
|
||||
/// <remarks>Assumes the stream is byte-aligned</remarks>
|
||||
#if NET48
|
||||
public byte[] ReadBytes(int bytes)
|
||||
#else
|
||||
public byte[]? ReadBytes(int bytes)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -17,11 +17,7 @@ namespace SabreTools.Compression.LZ
|
||||
/// </summary>
|
||||
/// <param name="compressed">Byte array representing the compressed data</param>
|
||||
/// <returns>Decompressed data as a byte array, null on error</returns>
|
||||
#if NET48
|
||||
public static byte[] Decompress(byte[] compressed)
|
||||
#else
|
||||
public static byte[]? Decompress(byte[]? compressed)
|
||||
#endif
|
||||
{
|
||||
// If we have and invalid input
|
||||
if (compressed == null || compressed.Length == 0)
|
||||
@@ -37,11 +33,7 @@ namespace SabreTools.Compression.LZ
|
||||
/// </summary>
|
||||
/// <param name="compressed">Stream representing the compressed data</param>
|
||||
/// <returns>Decompressed data as a byte array, null on error</returns>
|
||||
#if NET48
|
||||
public static byte[] Decompress(Stream compressed)
|
||||
#else
|
||||
public static byte[]? Decompress(Stream? compressed)
|
||||
#endif
|
||||
{
|
||||
// If we have and invalid input
|
||||
if (compressed == null || compressed.Length == 0)
|
||||
@@ -87,11 +79,7 @@ namespace SabreTools.Compression.LZ
|
||||
/// <summary>
|
||||
/// Reconstructs the full filename of the compressed file
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string GetExpandedName(string input, out LZERROR error)
|
||||
#else
|
||||
public static string? GetExpandedName(string input, out LZERROR error)
|
||||
#endif
|
||||
{
|
||||
// Try to open the file as a compressed stream
|
||||
var fileStream = File.Open(input, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
@@ -137,11 +125,7 @@ namespace SabreTools.Compression.LZ
|
||||
/// <param name="error">Output representing the last error</param>
|
||||
/// <returns>An initialized State, null on error</returns>
|
||||
/// <remarks>Uncompressed streams are represented by a State with no buffer</remarks>
|
||||
#if NET48
|
||||
public State Open(Stream stream, out LZERROR error)
|
||||
#else
|
||||
public State? Open(Stream stream, out LZERROR error)
|
||||
#endif
|
||||
{
|
||||
var lzs = Init(stream, out error);
|
||||
if (error == LZERROR.LZERROR_OK || error == LZERROR.LZERROR_NOT_LZ)
|
||||
@@ -170,11 +154,7 @@ namespace SabreTools.Compression.LZ
|
||||
/// <param name="error">Output representing the last error</param>
|
||||
/// <returns>An initialized State, null on error</returns>
|
||||
/// <remarks>Uncompressed streams are represented by a State with no buffer</remarks>
|
||||
#if NET48
|
||||
public State Init(Stream source, out LZERROR error)
|
||||
#else
|
||||
public State? Init(Stream? source, out LZERROR error)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid source
|
||||
if (source == null)
|
||||
@@ -540,11 +520,7 @@ namespace SabreTools.Compression.LZ
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="error">Output representing the last error</param>
|
||||
/// <returns>Filled file header on success, null on error</returns>
|
||||
#if NET48
|
||||
private FileHeaader ParseFileHeader(Stream data, out LZERROR error)
|
||||
#else
|
||||
private FileHeaader? ParseFileHeader(Stream data, out LZERROR error)
|
||||
#endif
|
||||
{
|
||||
error = LZERROR.LZERROR_OK;
|
||||
var fileHeader = new FileHeaader();
|
||||
|
||||
@@ -19,11 +19,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// Create a new Decompressor from a byte array
|
||||
/// </summary>
|
||||
/// <param name="input">Byte array to decompress</param>
|
||||
#if NET48
|
||||
public DeflateDecompressor(byte[] input)
|
||||
#else
|
||||
public DeflateDecompressor(byte[]? input)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid stream
|
||||
if (input == null || input.Length == 0)
|
||||
@@ -40,11 +36,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// Create a new Decompressor from a Stream
|
||||
/// </summary>
|
||||
/// <param name="input">Stream to decompress</param>
|
||||
#if NET48
|
||||
public DeflateDecompressor(Stream input)
|
||||
#else
|
||||
public DeflateDecompressor(Stream? input)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid stream
|
||||
if (input == null || !input.CanRead || !input.CanSeek)
|
||||
@@ -58,11 +50,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// Decompress a stream into a <see cref="Block"/>
|
||||
/// </summary>
|
||||
/// <returns>Block containing the decompressed data on success, null on error</returns>
|
||||
#if NET48
|
||||
public Block Process()
|
||||
#else
|
||||
public Block? Process()
|
||||
#endif
|
||||
{
|
||||
// Create a new block
|
||||
var block = new Block();
|
||||
@@ -85,11 +73,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
deflateBlocks.Add(deflateBlock);
|
||||
|
||||
// If we're at the final block, exit out of the loop
|
||||
#if NET48
|
||||
if (deflateBlock.Header.BFINAL)
|
||||
#else
|
||||
if (deflateBlock.Header!.BFINAL)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -187,11 +171,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// <summary>
|
||||
/// Read an RFC1951 block
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private DeflateBlock ReadDeflateBlock()
|
||||
#else
|
||||
private DeflateBlock? ReadDeflateBlock()
|
||||
#endif
|
||||
{
|
||||
var deflateBlock = new DeflateBlock();
|
||||
|
||||
@@ -241,11 +221,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// <summary>
|
||||
/// Read an RFC1951 block with no compression
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private (NonCompressedBlockHeader, byte[]) ReadNoCompression()
|
||||
#else
|
||||
private (NonCompressedBlockHeader?, byte[]?) ReadNoCompression()
|
||||
#endif
|
||||
{
|
||||
// Skip any remaining bits in current partially processed byte
|
||||
_bitStream.Discard();
|
||||
@@ -262,11 +238,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// <summary>
|
||||
/// Read an RFC1951 block with fixed Huffman compression
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private (FixedCompressedDataHeader, byte[]) ReadFixedHuffman()
|
||||
#else
|
||||
private (FixedCompressedDataHeader, byte[]?) ReadFixedHuffman()
|
||||
#endif
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
|
||||
@@ -284,11 +256,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// <summary>
|
||||
/// Read an RFC1951 block with dynamic Huffman compression
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private (DynamicCompressedDataHeader, byte[]) ReadDynamicHuffman()
|
||||
#else
|
||||
private (DynamicCompressedDataHeader?, byte[]?) ReadDynamicHuffman()
|
||||
#endif
|
||||
{
|
||||
// Get the dynamic huffman header
|
||||
(var header, uint numLiteral, uint numDistance) = ReadDynamicCompressedDataHeader();
|
||||
@@ -304,11 +272,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// <summary>
|
||||
/// Read an RFC1951 block with Huffman compression
|
||||
/// </summary>
|
||||
#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<byte>();
|
||||
|
||||
@@ -16,22 +16,14 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// </summary>
|
||||
/// <param name="lengths">Array representing the number of bits for each value</param>
|
||||
/// <param name="numCodes">Number of Huffman codes encoded</param>
|
||||
#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
|
||||
#if NET48
|
||||
HuffmanNode root = null;
|
||||
#else
|
||||
HuffmanNode? root = null;
|
||||
#endif
|
||||
|
||||
// Determine the value for max_bits
|
||||
uint max_bits = lengths.Max();
|
||||
@@ -83,11 +75,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
}
|
||||
|
||||
// Assign the root value
|
||||
#if NET48
|
||||
_root = root;
|
||||
#else
|
||||
_root = root!;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -125,11 +113,7 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// <param name="length">Length of the current encoding</param>
|
||||
/// <param name="code">Encoding of the value to traverse</param>
|
||||
/// <returns>New instance of the node with value appended</returns>
|
||||
#if NET48
|
||||
private static HuffmanNode Insert(HuffmanNode node, int value, uint length, int code)
|
||||
#else
|
||||
private static HuffmanNode Insert(HuffmanNode? node, int value, uint length, int code)
|
||||
#endif
|
||||
{
|
||||
// If no node is provided, create a new one
|
||||
if (node == null)
|
||||
|
||||
@@ -8,20 +8,12 @@ namespace SabreTools.Compression.MSZIP
|
||||
/// <summary>
|
||||
/// Left child of the current node
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public HuffmanNode Left { get; set; }
|
||||
#else
|
||||
public HuffmanNode? Left { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Right child of the current node
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public HuffmanNode Right { get; set; }
|
||||
#else
|
||||
public HuffmanNode? Right { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Value of the current node
|
||||
|
||||
@@ -87,11 +87,7 @@ namespace SabreTools.Compression.Quantum
|
||||
/// </summary>
|
||||
/// <param name="input">Byte array to decompress</param>
|
||||
/// <param name="windowBits">Number of bits in the sliding window</param>
|
||||
#if NET48
|
||||
public Decompressor(byte[] input, uint windowBits)
|
||||
#else
|
||||
public Decompressor(byte[]? input, uint windowBits)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid stream
|
||||
if (input == null || input.Length == 0)
|
||||
@@ -134,11 +130,7 @@ namespace SabreTools.Compression.Quantum
|
||||
/// </summary>
|
||||
/// <param name="input">Stream to decompress</param>
|
||||
/// <param name="windowBits">Number of bits in the sliding window</param>
|
||||
#if NET48
|
||||
public Decompressor(Stream input, uint windowBits)
|
||||
#else
|
||||
public Decompressor(Stream? input, uint windowBits)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid stream
|
||||
if (input == null || !input.CanRead || !input.CanSeek)
|
||||
@@ -293,36 +285,20 @@ namespace SabreTools.Compression.Quantum
|
||||
/// </summary>
|
||||
private int GetSymbol(Model model)
|
||||
{
|
||||
#if NET48
|
||||
int freq = GetFrequency(model.Symbols[0].CumulativeFrequency);
|
||||
#else
|
||||
int freq = GetFrequency(model.Symbols![0]!.CumulativeFrequency);
|
||||
#endif
|
||||
|
||||
int i;
|
||||
for (i = 1; i < model.Entries; i++)
|
||||
{
|
||||
#if NET48
|
||||
if (model.Symbols[i].CumulativeFrequency <= freq)
|
||||
#else
|
||||
if (model.Symbols[i]!.CumulativeFrequency <= freq)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
#if NET48
|
||||
int sym = model.Symbols[i - 1].Symbol;
|
||||
|
||||
GetCode(model.Symbols[i - 1].CumulativeFrequency,
|
||||
model.Symbols[i].CumulativeFrequency,
|
||||
model.Symbols[0].CumulativeFrequency);
|
||||
#else
|
||||
int sym = model.Symbols![i - 1]!.Symbol;
|
||||
|
||||
GetCode(model.Symbols![i - 1]!.CumulativeFrequency,
|
||||
model.Symbols![i]!.CumulativeFrequency,
|
||||
model.Symbols![0]!.CumulativeFrequency);
|
||||
#endif
|
||||
|
||||
UpdateModel(model, i);
|
||||
|
||||
@@ -369,20 +345,12 @@ namespace SabreTools.Compression.Quantum
|
||||
// Update cumulative frequencies
|
||||
for (int i = 0; i < lastUpdated; i++)
|
||||
{
|
||||
#if NET48
|
||||
var sym = model.Symbols[i];
|
||||
#else
|
||||
var sym = model.Symbols![i]!;
|
||||
#endif
|
||||
sym.CumulativeFrequency += 8;
|
||||
}
|
||||
|
||||
// Decrement reordering time, if needed
|
||||
#if NET48
|
||||
if (model.Symbols[0].CumulativeFrequency > 3800)
|
||||
#else
|
||||
if (model.Symbols![0]!.CumulativeFrequency > 3800)
|
||||
#endif
|
||||
model.TimeToReorder--;
|
||||
|
||||
// If we haven't hit the reordering time
|
||||
@@ -392,21 +360,12 @@ namespace SabreTools.Compression.Quantum
|
||||
for (int i = model.Entries - 1; i >= 0; i--)
|
||||
{
|
||||
// Divide with truncation by 2
|
||||
#if NET48
|
||||
var sym = model.Symbols[i];
|
||||
#else
|
||||
var sym = model.Symbols![i]!;
|
||||
#endif
|
||||
sym.CumulativeFrequency >>= 1;
|
||||
|
||||
// If we are lower the next frequency
|
||||
#if NET48
|
||||
if (i != 0 && sym.CumulativeFrequency <= model.Symbols[i + 1].CumulativeFrequency)
|
||||
sym.CumulativeFrequency = (ushort)(model.Symbols[i + 1].CumulativeFrequency + 1);
|
||||
#else
|
||||
if (i != 0 && sym.CumulativeFrequency <= model.Symbols![i + 1]!.CumulativeFrequency)
|
||||
sym.CumulativeFrequency = (ushort)(model.Symbols![i + 1]!.CumulativeFrequency + 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,19 +375,11 @@ namespace SabreTools.Compression.Quantum
|
||||
// Calculate frequencies from cumulative frequencies
|
||||
for (int i = 0; i < model.Entries; i++)
|
||||
{
|
||||
#if NET48
|
||||
if (i != model.Entries - 1)
|
||||
model.Symbols[i].CumulativeFrequency -= model.Symbols[i + 1].CumulativeFrequency;
|
||||
|
||||
model.Symbols[i].CumulativeFrequency++;
|
||||
model.Symbols[i].CumulativeFrequency >>= 1;
|
||||
#else
|
||||
if (i != model.Entries - 1)
|
||||
model.Symbols![i]!.CumulativeFrequency -= model.Symbols![i + 1]!.CumulativeFrequency;
|
||||
|
||||
model.Symbols![i]!.CumulativeFrequency++;
|
||||
model.Symbols![i]!.CumulativeFrequency >>= 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Sort frequencies in decreasing order
|
||||
@@ -436,11 +387,7 @@ namespace SabreTools.Compression.Quantum
|
||||
{
|
||||
for (int j = i + 1; j < model.Entries; j++)
|
||||
{
|
||||
#if NET48
|
||||
if (model.Symbols[i].CumulativeFrequency < model.Symbols[j].CumulativeFrequency)
|
||||
#else
|
||||
if (model.Symbols![i]!.CumulativeFrequency < model.Symbols![j]!.CumulativeFrequency)
|
||||
#endif
|
||||
{
|
||||
var temp = model.Symbols[i];
|
||||
model.Symbols[i] = model.Symbols[j];
|
||||
@@ -453,11 +400,7 @@ namespace SabreTools.Compression.Quantum
|
||||
for (int i = model.Entries - 1; i >= 0; i--)
|
||||
{
|
||||
if (i != model.Entries - 1)
|
||||
#if NET48
|
||||
model.Symbols[i].CumulativeFrequency += model.Symbols[i + 1].CumulativeFrequency;
|
||||
#else
|
||||
model.Symbols![i]!.CumulativeFrequency += model.Symbols![i + 1]!.CumulativeFrequency;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Reset the time to reorder
|
||||
|
||||
@@ -1,36 +1,34 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net48;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Version>0.1.1</Version>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>0.2.0</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Description>Clean compression implementations</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2022-2023</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/SabreTools/SabreTools.Printing</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>compression decompression lz mszip</PackageTags>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Description>Clean compression implementations</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2022-2023</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/SabreTools/SabreTools.Printing</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>compression decompression lz mszip</PackageTags>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" PackagePath=""/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" PackagePath=""/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.IO" Version="1.1.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.IO" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user