From 225aaab4f4cd62b94277aed73c5fed507afb6c1a Mon Sep 17 00:00:00 2001 From: Twan van Dongen Date: Sat, 27 Jan 2024 18:28:46 +0100 Subject: [PATCH 1/2] Support for decompressing Zip Shrink (method:1) added --- src/SharpCompress/Common/CompressionType.cs | 3 +- .../Common/Zip/ZipCompressionMethod.cs | 1 + src/SharpCompress/Common/Zip/ZipEntry.cs | 4 + src/SharpCompress/Common/Zip/ZipFilePart.cs | 6 + .../Compressors/Shrink/BitStream.cs | 86 ++++ .../Compressors/Shrink/HwUnshrink.cs | 394 ++++++++++++++++++ .../Compressors/Shrink/ShrinkStream.cs | 67 +++ .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 8 + tests/TestArchives/Archives/Zip.shrink.zip | Bin 0 -> 71199 bytes 9 files changed, 568 insertions(+), 1 deletion(-) create mode 100644 src/SharpCompress/Compressors/Shrink/BitStream.cs create mode 100644 src/SharpCompress/Compressors/Shrink/HwUnshrink.cs create mode 100644 src/SharpCompress/Compressors/Shrink/ShrinkStream.cs create mode 100644 tests/TestArchives/Archives/Zip.shrink.zip diff --git a/src/SharpCompress/Common/CompressionType.cs b/src/SharpCompress/Common/CompressionType.cs index 11263245..b26e5a95 100644 --- a/src/SharpCompress/Common/CompressionType.cs +++ b/src/SharpCompress/Common/CompressionType.cs @@ -14,5 +14,6 @@ public enum CompressionType LZip, Xz, Unknown, - Deflate64 + Deflate64, + Shrink } diff --git a/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs b/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs index 13c2dbe7..a98ed667 100644 --- a/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs +++ b/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs @@ -3,6 +3,7 @@ namespace SharpCompress.Common.Zip; internal enum ZipCompressionMethod { None = 0, + Shrink = 1, Deflate = 8, Deflate64 = 9, BZip2 = 12, diff --git a/src/SharpCompress/Common/Zip/ZipEntry.cs b/src/SharpCompress/Common/Zip/ZipEntry.cs index 2c544b94..61e1b6af 100644 --- a/src/SharpCompress/Common/Zip/ZipEntry.cs +++ b/src/SharpCompress/Common/Zip/ZipEntry.cs @@ -52,6 +52,10 @@ public override CompressionType CompressionType { return CompressionType.None; } + case ZipCompressionMethod.Shrink: + { + return CompressionType.Shrink; + } default: { return CompressionType.Unknown; diff --git a/src/SharpCompress/Common/Zip/ZipFilePart.cs b/src/SharpCompress/Common/Zip/ZipFilePart.cs index faefdf15..0463c97f 100644 --- a/src/SharpCompress/Common/Zip/ZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/ZipFilePart.cs @@ -9,6 +9,7 @@ using SharpCompress.Compressors.Deflate64; using SharpCompress.Compressors.LZMA; using SharpCompress.Compressors.PPMd; +using SharpCompress.Compressors.Shrink; using SharpCompress.Compressors.Xz; using SharpCompress.IO; using ZstdSharp; @@ -79,6 +80,10 @@ protected Stream CreateDecompressionStream(Stream stream, ZipCompressionMethod m return new DataDescriptorStream(stream); } + case ZipCompressionMethod.Shrink: + { + return new ShrinkStream(stream, CompressionMode.Decompress, Header.CompressedSize, Header.UncompressedSize); + } case ZipCompressionMethod.Deflate: { return new DeflateStream(stream, CompressionMode.Decompress); @@ -192,6 +197,7 @@ protected Stream GetCryptoStream(Stream plainStream) switch (Header.CompressionMethod) { case ZipCompressionMethod.None: + case ZipCompressionMethod.Shrink: case ZipCompressionMethod.Deflate: case ZipCompressionMethod.Deflate64: case ZipCompressionMethod.BZip2: diff --git a/src/SharpCompress/Compressors/Shrink/BitStream.cs b/src/SharpCompress/Compressors/Shrink/BitStream.cs new file mode 100644 index 00000000..76b59041 --- /dev/null +++ b/src/SharpCompress/Compressors/Shrink/BitStream.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +namespace SharpCompress.Compressors.Shrink +{ + internal class BitStream + { + private byte[] _src; + private int _srcLen; + private int _byteIdx; + private int _bitIdx; + private int _bitsLeft; + private ulong _bitBuffer; + private static uint[] _maskBits = new uint[17] + { + 0U, + 1U, + 3U, + 7U, + 15U, + 31U, + 63U, + (uint) sbyte.MaxValue, + (uint) byte.MaxValue, + 511U, + 1023U, + 2047U, + 4095U, + 8191U, + 16383U, + (uint) short.MaxValue, + (uint) ushort.MaxValue + }; + + public BitStream(byte[] src, int srcLen) + { + _src = src; + _srcLen = srcLen; + _byteIdx = 0; + _bitIdx = 0; + } + + public int BytesRead => (_byteIdx << 3) + _bitIdx; + + private int NextByte() + { + if (_byteIdx >= _srcLen) + { + return 0; + } + + return _src[_byteIdx++]; + } + + public int NextBits(int nbits) + { + int result = 0; + if (nbits > _bitsLeft) + { + int num; + while (_bitsLeft <= 24 && (num = NextByte()) != 1234) + { + _bitBuffer |= (ulong)num << _bitsLeft; + _bitsLeft += 8; + } + } + result = (int)((long)_bitBuffer & (long)_maskBits[nbits]); + _bitBuffer >>= nbits; + _bitsLeft -= nbits; + return result; + } + + public bool Advance(int count) + { + if (_byteIdx > _srcLen) + { + return false; + } + return true; + } + } +} diff --git a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs new file mode 100644 index 00000000..ca3dcbe6 --- /dev/null +++ b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs @@ -0,0 +1,394 @@ +using System; + +namespace SharpCompress.Compressors.Shrink +{ + public class HwUnshrink + { + private const int MIN_CODE_SIZE = 9; + private const int MAX_CODE_SIZE = 13; + + private const ushort MAX_CODE = (ushort)((1U << MAX_CODE_SIZE) - 1); + private const ushort INVALID_CODE = ushort.MaxValue; + private const ushort CONTROL_CODE = 256; + private const ushort INC_CODE_SIZE = 1; + private const ushort PARTIAL_CLEAR = 2; + + private const int HASH_BITS = MAX_CODE_SIZE + 1; // For a load factor of 0.5. + private const int HASHTAB_SIZE = 1 << HASH_BITS; + private const ushort UNKNOWN_LEN = ushort.MaxValue; + + private struct CodeTabEntry + { + public int prefixCode; // INVALID_CODE means the entry is invalid. + public byte extByte; + public ushort len; + public int lastDstPos; + } + + private static void CodeTabInit(CodeTabEntry[] codeTab) + { + for (int i = 0; i <= byte.MaxValue; i++) + { + codeTab[i].prefixCode = (ushort)i; + codeTab[i].extByte = (byte)i; + codeTab[i].len = 1; + } + + for (int i = byte.MaxValue + 1; i <= MAX_CODE; i++) + { + codeTab[i].prefixCode = INVALID_CODE; + } + } + + private static void UnshrinkPartialClear(CodeTabEntry[] codeTab, ref CodeQueue queue) + { + bool[] isPrefix = new bool[MAX_CODE + 1]; + int codeQueueSize; + + // Scan for codes that have been used as a prefix. + for (int i = CONTROL_CODE + 1; i <= MAX_CODE; i++) + { + if (codeTab[i].prefixCode != INVALID_CODE) + { + isPrefix[codeTab[i].prefixCode] = true; + } + } + + // Clear "non-prefix" codes in the table; populate the code queue. + codeQueueSize = 0; + for (int i = CONTROL_CODE + 1; i <= MAX_CODE; i++) + { + if (!isPrefix[i]) + { + codeTab[i].prefixCode = INVALID_CODE; + queue.codes[codeQueueSize++] = (ushort)i; + } + } + + queue.codes[codeQueueSize] = INVALID_CODE; // End-of-queue marker. + queue.nextIdx = 0; + } + + private static bool ReadCode(BitStream stream, ref int codeSize, CodeTabEntry[] codeTab, ref CodeQueue queue, out int nextCode) + { + int code, controlCode; + + code = (int)stream.NextBits(codeSize); + if (!stream.Advance(codeSize)) + { + nextCode = INVALID_CODE; + return false; + } + + // Handle regular codes (the common case). + if (code != CONTROL_CODE) + { + nextCode = code; + return true; + } + + // Handle control codes. + controlCode = (ushort)stream.NextBits(codeSize); + if (!stream.Advance(codeSize)) + { + nextCode = INVALID_CODE; + return true; + } + + if (controlCode == INC_CODE_SIZE && codeSize < MAX_CODE_SIZE) + { + codeSize++; + return ReadCode(stream, ref codeSize, codeTab, ref queue, out nextCode); + } + + if (controlCode == PARTIAL_CLEAR) + { + UnshrinkPartialClear(codeTab, ref queue); + return ReadCode(stream, ref codeSize, codeTab, ref queue, out nextCode); + } + + nextCode = INVALID_CODE; + return true; + } + + private static void CopyFromPrevPos(byte[] dst, int prevPos, int dstPos, int len) + { + if (dstPos + len > dst.Length) + { + // Not enough room in dst for the sloppy copy below. + Array.Copy(dst, prevPos, dst, dstPos, len); + return; + } + + if (prevPos + len > dstPos) + { + // Benign one-byte overlap possible in the KwKwK case. + //assert(prevPos + len == dstPos + 1); + //assert(dst[prevPos] == dst[prevPos + len - 1]); + } + + Buffer.BlockCopy(dst, prevPos, dst, dstPos, len); + } + + private static UnshrnkStatus OutputCode(int code, byte[] dst, int dstPos, int dstCap, int prevCode, + CodeTabEntry[] codeTab, ref CodeQueue queue, out byte firstByte, out int len) + { + int prefixCode; + + //assert(code <= MAX_CODE && code != CONTROL_CODE); + //assert(dstPos < dstCap); + firstByte = 0; + if (code <= byte.MaxValue) + { + // Output literal byte. + firstByte = (byte)code; + len = 1; + dst[dstPos] = (byte)code; + return UnshrnkStatus.Ok; + } + + if (codeTab[code].prefixCode == INVALID_CODE || codeTab[code].prefixCode == code) + { + // Reject invalid codes. Self-referential codes may exist in the table but cannot be used. + firstByte = 0; + len = 0; + return UnshrnkStatus.Error; + } + + if (codeTab[code].len != UNKNOWN_LEN) + { + // Output string with known length (the common case). + if (dstCap - dstPos < codeTab[code].len) + { + firstByte = 0; + len = 0; + return UnshrnkStatus.Full; + } + + CopyFromPrevPos(dst, codeTab[code].lastDstPos, dstPos, codeTab[code].len); + firstByte = dst[dstPos]; + len = codeTab[code].len; + return UnshrnkStatus.Ok; + } + + // Output a string of unknown length. + //assert(codeTab[code].len == UNKNOWN_LEN); + prefixCode = codeTab[code].prefixCode; + // assert(prefixCode > CONTROL_CODE); + + if (prefixCode == queue.codes[queue.nextIdx]) + { + // The prefix code hasn't been added yet, but we were just about to: the KwKwK case. + //assert(codeTab[prevCode].prefixCode != INVALID_CODE); + codeTab[prefixCode].prefixCode = prevCode; + codeTab[prefixCode].extByte = firstByte; + codeTab[prefixCode].len = (ushort)(codeTab[prevCode].len + 1); + codeTab[prefixCode].lastDstPos = codeTab[prevCode].lastDstPos; + dst[dstPos] = firstByte; + } + else if (codeTab[prefixCode].prefixCode == INVALID_CODE) + { + // The prefix code is still invalid. + firstByte = 0; + len = 0; + return UnshrnkStatus.Error; + } + + // Output the prefix string, then the extension byte. + len = codeTab[prefixCode].len + 1; + if (dstCap - dstPos < len) + { + firstByte = 0; + len = 0; + return UnshrnkStatus.Full; + } + + CopyFromPrevPos(dst, codeTab[prefixCode].lastDstPos, dstPos, codeTab[prefixCode].len); + dst[dstPos + len - 1] = codeTab[code].extByte; + firstByte = dst[dstPos]; + + // Update the code table now that the string has a length and pos. + //assert(prevCode != code); + codeTab[code].len = (ushort)len; + codeTab[code].lastDstPos = dstPos; + + return UnshrnkStatus.Ok; + } + + public static UnshrnkStatus Unshrink(byte[] src, int srcLen, out int srcUsed, byte[] dst, int dstCap, out int dstUsed) + { + CodeTabEntry[] codeTab = new CodeTabEntry[HASHTAB_SIZE]; + CodeQueue queue = new CodeQueue(); + var stream = new BitStream(src, srcLen); + int codeSize, dstPos, len; + int currCode, prevCode, newCode; + byte firstByte; + + CodeTabInit(codeTab); + CodeQueueInit(ref queue); + codeSize = MIN_CODE_SIZE; + dstPos = 0; + + // Handle the first code separately since there is no previous code. + if (!ReadCode(stream, ref codeSize, codeTab, ref queue, out currCode)) + { + srcUsed = stream.BytesRead; + dstUsed = 0; + return UnshrnkStatus.Ok; + } + + //assert(currCode != CONTROL_CODE); + if (currCode > byte.MaxValue) + { + srcUsed = stream.BytesRead; + dstUsed = 0; + return UnshrnkStatus.Error; // The first code must be a literal. + } + + if (dstPos == dstCap) + { + srcUsed = stream.BytesRead; + dstUsed = 0; + return UnshrnkStatus.Full; + } + + firstByte = (byte)currCode; + dst[dstPos] = (byte)currCode; + codeTab[currCode].lastDstPos = dstPos; + dstPos++; + + prevCode = currCode; + while (ReadCode(stream, ref codeSize, codeTab, ref queue, out currCode)) + { + if (currCode == INVALID_CODE) + { + srcUsed = stream.BytesRead; + dstUsed = 0; + return UnshrnkStatus.Error; + } + + if (dstPos == dstCap) + { + srcUsed = stream.BytesRead; + dstUsed = 0; + return UnshrnkStatus.Full; + } + + // Handle KwKwK: next code used before being added. + if (currCode == queue.codes[queue.nextIdx]) + { + if (codeTab[prevCode].prefixCode == INVALID_CODE) + { + // The previous code is no longer valid. + srcUsed = stream.BytesRead; + dstUsed = 0; + return UnshrnkStatus.Error; + } + + // Extend the previous code with its first byte. + //assert(currCode != prevCode); + codeTab[currCode].prefixCode = prevCode; + codeTab[currCode].extByte = firstByte; + codeTab[currCode].len = (ushort)(codeTab[prevCode].len + 1); + codeTab[currCode].lastDstPos = codeTab[prevCode].lastDstPos; + //assert(dstPos < dstCap); + dst[dstPos] = firstByte; + } + + // Output the string represented by the current code. + UnshrnkStatus status = OutputCode(currCode, dst, dstPos, dstCap, prevCode, codeTab, ref queue, out firstByte, out len); + if (status != UnshrnkStatus.Ok) + { + srcUsed = stream.BytesRead; + dstUsed = 0; + return status; + } + + // Verify that the output matches walking the prefixes. + var c = currCode; + for (int i = 0; i < len; i++) + { + // assert(codeTab[c].len == len - i); + //assert(codeTab[c].extByte == dst[dstPos + len - i - 1]); + c = codeTab[c].prefixCode; + } + + // Add a new code to the string table if there's room. + // The string is the previous code's string extended with the first byte of the current code's string. + newCode = CodeQueueRemoveNext(ref queue); + if (newCode != INVALID_CODE) + { + //assert(codeTab[prevCode].lastDstPos < dstPos); + codeTab[newCode].prefixCode = prevCode; + codeTab[newCode].extByte = firstByte; + codeTab[newCode].len = (ushort)(codeTab[prevCode].len + 1); + codeTab[newCode].lastDstPos = codeTab[prevCode].lastDstPos; + + if (codeTab[prevCode].prefixCode == INVALID_CODE) + { + // prevCode was invalidated in a partial clearing. Until that code is re-used, the + // string represented by newCode is indeterminate. + codeTab[newCode].len = UNKNOWN_LEN; + } + // If prevCode was invalidated in a partial clearing, it's possible that newCode == prevCode, + // in which case it will never be used or cleared. + } + + codeTab[currCode].lastDstPos = dstPos; + dstPos += len; + + prevCode = currCode; + } + + srcUsed = stream.BytesRead; + dstUsed = dstPos; + + return UnshrnkStatus.Ok; + } + + public enum UnshrnkStatus + { + Ok, + Full, + Error + } + + private struct CodeQueue + { + public int nextIdx; + public ushort[] codes; + } + + private static void CodeQueueInit(ref CodeQueue q) + { + int codeQueueSize; + ushort code; + + codeQueueSize = 0; + q.codes = new ushort[MAX_CODE - CONTROL_CODE + 2]; + + for (code = CONTROL_CODE + 1; code <= MAX_CODE; code++) + { + q.codes[codeQueueSize++] = code; + } + + //assert(codeQueueSize < q.codes.Length); + q.codes[codeQueueSize] = INVALID_CODE; // End-of-queue marker. + q.nextIdx = 0; + } + private static ushort CodeQueueNext(ref CodeQueue q) + { + //assert(q.nextIdx < q.codes.Length); + return q.codes[q.nextIdx]; + } + private static ushort CodeQueueRemoveNext(ref CodeQueue q) + { + ushort code = CodeQueueNext(ref q); + if (code != INVALID_CODE) + { + q.nextIdx++; + } + return code; + } + } +} diff --git a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs new file mode 100644 index 00000000..7926d093 --- /dev/null +++ b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharpCompress.Compressors.Shrink; + +internal class ShrinkStream : Stream +{ + private Stream inStream; + private CompressionMode _compressionMode; + + private ulong _compressedSize; + private long _uncompressedSize; + private byte[] _byteOut; + private long _outBytesCount; + + public ShrinkStream(Stream stream, CompressionMode compressionMode, long compressedSize, long uncompressedSize) + { + inStream = stream; + _compressionMode = compressionMode; + + _compressedSize = (ulong)compressedSize; + _uncompressedSize = uncompressedSize; + _byteOut = new byte[_uncompressedSize]; + _outBytesCount = 0L; + } + + public override bool CanRead => true; + + public override bool CanSeek => true; + + public override bool CanWrite => false; + + public override long Length => _uncompressedSize; + + public override long Position { get => _outBytesCount; set => throw new NotImplementedException(); } + + public override void Flush() => throw new NotImplementedException(); + public override int Read(byte[] buffer, int offset, int count) + { + if (inStream.Position == (long)_compressedSize) + { + return 0; + } + byte[] src = new byte[_compressedSize]; + inStream.Read(src, offset, (int)_compressedSize); + int srcUsed = 0; + int dstUsed = 0; + + HwUnshrink.Unshrink(src, (int)_compressedSize, out srcUsed, _byteOut, (int)_uncompressedSize, out dstUsed); + _outBytesCount = _byteOut.Length; + + for (int index = 0; index < _outBytesCount; ++index) + { + buffer[offset + index] = _byteOut[index]; + } + var tmp = _outBytesCount; + _outBytesCount = 0; + return (int)tmp; + } + public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); + public override void SetLength(long value) => throw new NotImplementedException(); + public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException(); +} diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index fde87dc6..ebcb4243 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -16,6 +16,14 @@ public class ZipArchiveTests : ArchiveTests { public ZipArchiveTests() => UseExtensionInsteadOfNameToVerify = true; + [Fact] + public void Zip_Shrink_ArchiveStreamRead() + { + UseExtensionInsteadOfNameToVerify = true; + UseCaseInsensitiveToVerify = true; + ArchiveStreamRead("Zip.shrink.zip"); + } + [Fact] public void Zip_ZipX_ArchiveStreamRead() => ArchiveStreamRead("Zip.zipx"); diff --git a/tests/TestArchives/Archives/Zip.shrink.zip b/tests/TestArchives/Archives/Zip.shrink.zip new file mode 100644 index 0000000000000000000000000000000000000000..697c7e0047de844f03018b358fdc988dbd33cd4d GIT binary patch literal 71199 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 P2WeV`#>N Date: Sat, 27 Jan 2024 18:59:56 +0100 Subject: [PATCH 2/2] Refrormatted using CSharpier --- src/SharpCompress/Common/Zip/ZipFilePart.cs | 7 ++- .../Compressors/Shrink/BitStream.cs | 37 ++++++------ .../Compressors/Shrink/HwUnshrink.cs | 59 +++++++++++++++---- .../Compressors/Shrink/ShrinkStream.cs | 32 ++++++++-- 4 files changed, 100 insertions(+), 35 deletions(-) diff --git a/src/SharpCompress/Common/Zip/ZipFilePart.cs b/src/SharpCompress/Common/Zip/ZipFilePart.cs index 0463c97f..f8a0e8a8 100644 --- a/src/SharpCompress/Common/Zip/ZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/ZipFilePart.cs @@ -82,7 +82,12 @@ protected Stream CreateDecompressionStream(Stream stream, ZipCompressionMethod m } case ZipCompressionMethod.Shrink: { - return new ShrinkStream(stream, CompressionMode.Decompress, Header.CompressedSize, Header.UncompressedSize); + return new ShrinkStream( + stream, + CompressionMode.Decompress, + Header.CompressedSize, + Header.UncompressedSize + ); } case ZipCompressionMethod.Deflate: { diff --git a/src/SharpCompress/Compressors/Shrink/BitStream.cs b/src/SharpCompress/Compressors/Shrink/BitStream.cs index 76b59041..ef01e2af 100644 --- a/src/SharpCompress/Compressors/Shrink/BitStream.cs +++ b/src/SharpCompress/Compressors/Shrink/BitStream.cs @@ -4,7 +4,6 @@ using System.Text; using System.Threading.Tasks; - namespace SharpCompress.Compressors.Shrink { internal class BitStream @@ -14,26 +13,26 @@ internal class BitStream private int _byteIdx; private int _bitIdx; private int _bitsLeft; - private ulong _bitBuffer; + private ulong _bitBuffer; private static uint[] _maskBits = new uint[17] { - 0U, - 1U, - 3U, - 7U, - 15U, - 31U, - 63U, - (uint) sbyte.MaxValue, - (uint) byte.MaxValue, - 511U, - 1023U, - 2047U, - 4095U, - 8191U, - 16383U, - (uint) short.MaxValue, - (uint) ushort.MaxValue + 0U, + 1U, + 3U, + 7U, + 15U, + 31U, + 63U, + (uint)sbyte.MaxValue, + (uint)byte.MaxValue, + 511U, + 1023U, + 2047U, + 4095U, + 8191U, + 16383U, + (uint)short.MaxValue, + (uint)ushort.MaxValue }; public BitStream(byte[] src, int srcLen) diff --git a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs index ca3dcbe6..04f38c2b 100644 --- a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs +++ b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs @@ -69,9 +69,16 @@ private static void UnshrinkPartialClear(CodeTabEntry[] codeTab, ref CodeQueue q queue.nextIdx = 0; } - private static bool ReadCode(BitStream stream, ref int codeSize, CodeTabEntry[] codeTab, ref CodeQueue queue, out int nextCode) + private static bool ReadCode( + BitStream stream, + ref int codeSize, + CodeTabEntry[] codeTab, + ref CodeQueue queue, + out int nextCode + ) { - int code, controlCode; + int code, + controlCode; code = (int)stream.NextBits(codeSize); if (!stream.Advance(codeSize)) @@ -130,8 +137,17 @@ private static void CopyFromPrevPos(byte[] dst, int prevPos, int dstPos, int len Buffer.BlockCopy(dst, prevPos, dst, dstPos, len); } - private static UnshrnkStatus OutputCode(int code, byte[] dst, int dstPos, int dstCap, int prevCode, - CodeTabEntry[] codeTab, ref CodeQueue queue, out byte firstByte, out int len) + private static UnshrnkStatus OutputCode( + int code, + byte[] dst, + int dstPos, + int dstCap, + int prevCode, + CodeTabEntry[] codeTab, + ref CodeQueue queue, + out byte firstByte, + out int len + ) { int prefixCode; @@ -174,7 +190,7 @@ private static UnshrnkStatus OutputCode(int code, byte[] dst, int dstPos, int ds // Output a string of unknown length. //assert(codeTab[code].len == UNKNOWN_LEN); prefixCode = codeTab[code].prefixCode; - // assert(prefixCode > CONTROL_CODE); + // assert(prefixCode > CONTROL_CODE); if (prefixCode == queue.codes[queue.nextIdx]) { @@ -215,13 +231,24 @@ private static UnshrnkStatus OutputCode(int code, byte[] dst, int dstPos, int ds return UnshrnkStatus.Ok; } - public static UnshrnkStatus Unshrink(byte[] src, int srcLen, out int srcUsed, byte[] dst, int dstCap, out int dstUsed) + public static UnshrnkStatus Unshrink( + byte[] src, + int srcLen, + out int srcUsed, + byte[] dst, + int dstCap, + out int dstUsed + ) { CodeTabEntry[] codeTab = new CodeTabEntry[HASHTAB_SIZE]; CodeQueue queue = new CodeQueue(); var stream = new BitStream(src, srcLen); - int codeSize, dstPos, len; - int currCode, prevCode, newCode; + int codeSize, + dstPos, + len; + int currCode, + prevCode, + newCode; byte firstByte; CodeTabInit(codeTab); @@ -296,7 +323,17 @@ public static UnshrnkStatus Unshrink(byte[] src, int srcLen, out int srcUsed, by } // Output the string represented by the current code. - UnshrnkStatus status = OutputCode(currCode, dst, dstPos, dstCap, prevCode, codeTab, ref queue, out firstByte, out len); + UnshrnkStatus status = OutputCode( + currCode, + dst, + dstPos, + dstCap, + prevCode, + codeTab, + ref queue, + out firstByte, + out len + ); if (status != UnshrnkStatus.Ok) { srcUsed = stream.BytesRead; @@ -308,7 +345,7 @@ public static UnshrnkStatus Unshrink(byte[] src, int srcLen, out int srcUsed, by var c = currCode; for (int i = 0; i < len; i++) { - // assert(codeTab[c].len == len - i); + // assert(codeTab[c].len == len - i); //assert(codeTab[c].extByte == dst[dstPos + len - i - 1]); c = codeTab[c].prefixCode; } @@ -376,11 +413,13 @@ private static void CodeQueueInit(ref CodeQueue q) q.codes[codeQueueSize] = INVALID_CODE; // End-of-queue marker. q.nextIdx = 0; } + private static ushort CodeQueueNext(ref CodeQueue q) { //assert(q.nextIdx < q.codes.Length); return q.codes[q.nextIdx]; } + private static ushort CodeQueueRemoveNext(ref CodeQueue q) { ushort code = CodeQueueNext(ref q); diff --git a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs index 7926d093..52bba1ad 100644 --- a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs +++ b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs @@ -17,7 +17,12 @@ internal class ShrinkStream : Stream private byte[] _byteOut; private long _outBytesCount; - public ShrinkStream(Stream stream, CompressionMode compressionMode, long compressedSize, long uncompressedSize) + public ShrinkStream( + Stream stream, + CompressionMode compressionMode, + long compressedSize, + long uncompressedSize + ) { inStream = stream; _compressionMode = compressionMode; @@ -36,9 +41,14 @@ public ShrinkStream(Stream stream, CompressionMode compressionMode, long compres public override long Length => _uncompressedSize; - public override long Position { get => _outBytesCount; set => throw new NotImplementedException(); } + public override long Position + { + get => _outBytesCount; + set => throw new NotImplementedException(); + } public override void Flush() => throw new NotImplementedException(); + public override int Read(byte[] buffer, int offset, int count) { if (inStream.Position == (long)_compressedSize) @@ -50,7 +60,14 @@ public override int Read(byte[] buffer, int offset, int count) int srcUsed = 0; int dstUsed = 0; - HwUnshrink.Unshrink(src, (int)_compressedSize, out srcUsed, _byteOut, (int)_uncompressedSize, out dstUsed); + HwUnshrink.Unshrink( + src, + (int)_compressedSize, + out srcUsed, + _byteOut, + (int)_uncompressedSize, + out dstUsed + ); _outBytesCount = _byteOut.Length; for (int index = 0; index < _outBytesCount; ++index) @@ -61,7 +78,12 @@ public override int Read(byte[] buffer, int offset, int count) _outBytesCount = 0; return (int)tmp; } - public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); + + public override long Seek(long offset, SeekOrigin origin) => + throw new NotImplementedException(); + public override void SetLength(long value) => throw new NotImplementedException(); - public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException(); + + public override void Write(byte[] buffer, int offset, int count) => + throw new NotImplementedException(); }