Skip to content

Commit 0d94215

Browse files
committed
Replace MS-ZIP implementation (nw)
1 parent 9bf7839 commit 0d94215

File tree

6 files changed

+122
-566
lines changed

6 files changed

+122
-566
lines changed

SabreTools.Compression/Deflate/DeflateStream.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,17 @@ public override void Write(byte[] buffer, int offset, int count)
615615
if (_disposed) throw new ObjectDisposedException("DeflateStream");
616616
_baseStream.Write(buffer, offset, count);
617617
}
618+
619+
/// <summary>
620+
/// Set the dictionary to be used for either Inflation or Deflation.
621+
/// </summary>
622+
/// <param name="dictionary">The dictionary bytes to use.</param>
623+
/// <returns>Z_OK if all goes well.</returns>
624+
public int SetDictionary(byte[] dictionary)
625+
{
626+
return _baseStream.SetDictionary(dictionary);
627+
}
628+
618629
#endregion
619630

620631

SabreTools.Compression/Deflate/ZlibBaseStream.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,16 @@ public static byte[] UncompressBuffer(byte[] compressed, Stream decompressor)
620620
}
621621
}
622622

623+
/// <summary>
624+
/// Set the dictionary to be used for either Inflation or Deflation.
625+
/// </summary>
626+
/// <param name="dictionary">The dictionary bytes to use.</param>
627+
/// <returns>Z_OK if all goes well.</returns>
628+
public int SetDictionary(byte[] dictionary)
629+
{
630+
return z.SetDictionary(dictionary);
631+
}
632+
623633
}
624634

625635

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System;
2+
using System.IO;
3+
using SabreTools.IO.Extensions;
4+
5+
namespace SabreTools.Compression.MSZIP
6+
{
7+
/// <see href="https://msopenspecs.azureedge.net/files/MS-MCI/%5bMS-MCI%5d.pdf"/>
8+
public class Decompressor
9+
{
10+
/// <summary>
11+
/// Source stream for the decompressor
12+
/// </summary>
13+
private readonly Stream _source;
14+
15+
#region Constructors
16+
17+
/// <summary>
18+
/// Create a MS-ZIP decompressor
19+
/// </summary>
20+
private Decompressor(Stream source)
21+
{
22+
// Validate the inputs
23+
if (source.Length == 0)
24+
throw new ArgumentOutOfRangeException(nameof(source));
25+
if (!source.CanRead)
26+
throw new InvalidOperationException(nameof(source));
27+
28+
_source = source;
29+
}
30+
31+
/// <summary>
32+
/// Create a MS-ZIP decompressor
33+
/// </summary>
34+
public static Decompressor Create(byte[] source)
35+
=> Create(new MemoryStream(source));
36+
37+
/// <summary>
38+
/// Create a MS-ZIP decompressor
39+
/// </summary>
40+
public static Decompressor Create(Stream source)
41+
{
42+
// Create the decompressor
43+
var decompressor = new Decompressor(source);
44+
45+
// Validate the header
46+
var header = new Models.Compression.MSZIP.BlockHeader();
47+
header.Signature = source.ReadUInt16();
48+
if (header.Signature != 0x4B43)
49+
throw new InvalidDataException(nameof(source));
50+
51+
// Return
52+
return decompressor;
53+
}
54+
55+
#endregion
56+
57+
/// <summary>
58+
/// Decompress source data to an output stream
59+
/// </summary>
60+
public bool CopyTo(Stream dest)
61+
{
62+
// Ignore unwritable streams
63+
if (!dest.CanWrite)
64+
return false;
65+
66+
byte[]? history = null;
67+
while (true)
68+
{
69+
byte[] buffer = new byte[32 * 1024];
70+
var blockStream = new Deflate.DeflateStream(_source, Deflate.CompressionMode.Decompress);
71+
if (history != null)
72+
blockStream.SetDictionary(history);
73+
74+
int read = blockStream.Read(buffer, 0, buffer.Length);
75+
if (read <= 0)
76+
break;
77+
78+
// Write to output
79+
dest.Write(buffer, 0, read);
80+
81+
// Save the history for rollover
82+
history = new byte[read];
83+
Array.Copy(buffer, history, read);
84+
85+
// Handle end of stream
86+
if (_source.Position >= _source.Length)
87+
break;
88+
89+
// Validate the header
90+
var header = new Models.Compression.MSZIP.BlockHeader();
91+
header.Signature = _source.ReadUInt16();
92+
if (header.Signature != 0x4B43)
93+
break;
94+
}
95+
96+
// Flush and return
97+
dest.Flush();
98+
return true;
99+
}
100+
}
101+
}

0 commit comments

Comments
 (0)