mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-03 21:23:38 +00:00
more lzma porting
This commit is contained in:
@@ -1,20 +1,38 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpCompress.Compressors.LZMA.LZ;
|
||||
|
||||
internal partial class OutWindow : IDisposable
|
||||
internal partial class OutWindow : IAsyncDisposable
|
||||
{
|
||||
public async ValueTask InitAsync(Stream stream)
|
||||
{
|
||||
await ReleaseStreamAsync();
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
public async ValueTask ReleaseStreamAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||
_stream = null;
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await ReleaseStreamAsync();
|
||||
if (_buffer is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ArrayPool<byte>.Shared.Return(_buffer);
|
||||
_buffer = null;
|
||||
}
|
||||
|
||||
private async ValueTask FlushAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_stream is null)
|
||||
@@ -140,4 +158,20 @@ internal partial class OutWindow : IDisposable
|
||||
}
|
||||
return len - size;
|
||||
}
|
||||
|
||||
public async ValueTask TrainAsync(Stream stream)
|
||||
{
|
||||
var len = stream.Length;
|
||||
var size = (len < _windowSize) ? (int)len : _windowSize;
|
||||
stream.Position = len - size;
|
||||
_total = 0;
|
||||
_limit = size;
|
||||
_pos = _windowSize - size;
|
||||
await CopyStreamAsync(stream, size);
|
||||
if (_pos == _windowSize)
|
||||
{
|
||||
_pos = 0;
|
||||
}
|
||||
_streamPos = _pos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public partial class Decoder : ICoder, ISetDecoderProperties
|
||||
{
|
||||
CreateDictionary();
|
||||
}
|
||||
_outWindow.Init(outStream);
|
||||
await _outWindow.InitAsync(outStream);
|
||||
if (outSize > 0)
|
||||
{
|
||||
_outWindow.SetLimit(outSize);
|
||||
@@ -156,7 +156,7 @@ public partial class Decoder : ICoder, ISetDecoderProperties
|
||||
await _outWindow.ReleaseStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
rangeDecoder.ReleaseStream();
|
||||
|
||||
_outWindow.Dispose();
|
||||
await _outWindow.DisposeAsync().ConfigureAwait(false);
|
||||
_outWindow = null;
|
||||
}
|
||||
|
||||
@@ -332,4 +332,13 @@ public partial class Decoder : ICoder, ISetDecoderProperties
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async ValueTask TrainAsync(Stream stream)
|
||||
{
|
||||
if (_outWindow is null)
|
||||
{
|
||||
CreateDictionary();
|
||||
}
|
||||
await _outWindow.TrainAsync(stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
@@ -10,10 +8,66 @@ namespace SharpCompress.Compressors.LZMA;
|
||||
|
||||
public partial class LzmaStream
|
||||
{
|
||||
public static async ValueTask<LzmaStream> CreateAsync(
|
||||
byte[] properties,
|
||||
Stream inputStream,
|
||||
long inputSize,
|
||||
long outputSize,
|
||||
Stream? presetDictionary,
|
||||
bool isLzma2,
|
||||
bool leaveOpen = false
|
||||
)
|
||||
{
|
||||
var lzma = new LzmaStream(
|
||||
properties,
|
||||
inputStream,
|
||||
inputSize,
|
||||
outputSize,
|
||||
isLzma2,
|
||||
leaveOpen
|
||||
);
|
||||
if (!isLzma2)
|
||||
{
|
||||
if (presetDictionary != null)
|
||||
{
|
||||
await lzma._outWindow.TrainAsync(presetDictionary);
|
||||
}
|
||||
|
||||
await lzma._rangeDecoder.InitAsync(inputStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (presetDictionary != null)
|
||||
{
|
||||
await lzma._outWindow.TrainAsync(presetDictionary);
|
||||
lzma._needDictReset = false;
|
||||
}
|
||||
}
|
||||
return lzma;
|
||||
}
|
||||
|
||||
/*public static async ValueTask<LzmaStream> CreateAsync(
|
||||
LzmaEncoderProperties properties,
|
||||
bool isLzma2,
|
||||
Stream? presetDictionary,
|
||||
Stream outputStream
|
||||
)
|
||||
{
|
||||
var lzma = new LzmaStream(properties, isLzma2, presetDictionary);
|
||||
|
||||
lzma._encoder!.SetStreams(null, outputStream, -1, -1);
|
||||
|
||||
if (presetDictionary != null)
|
||||
{
|
||||
lzma._encoder.Train(presetDictionary);
|
||||
}
|
||||
return lzma;
|
||||
}*/
|
||||
|
||||
private async ValueTask DecodeChunkHeaderAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var controlBuffer = new byte[1];
|
||||
await _inputStream
|
||||
await _inputStream!
|
||||
.ReadExactAsync(controlBuffer, 0, 1, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
var control = controlBuffer[0];
|
||||
@@ -42,13 +96,13 @@ public partial class LzmaStream
|
||||
|
||||
_availableBytes = (control & 0x1F) << 16;
|
||||
var buffer = new byte[2];
|
||||
await _inputStream
|
||||
await _inputStream!
|
||||
.ReadExactAsync(buffer, 0, 2, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
_availableBytes += (buffer[0] << 8) + buffer[1] + 1;
|
||||
_inputPosition += 2;
|
||||
|
||||
await _inputStream
|
||||
await _inputStream!
|
||||
.ReadExactAsync(buffer, 0, 2, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
_rangeDecoderLimit = (buffer[0] << 8) + buffer[1] + 1;
|
||||
@@ -57,7 +111,7 @@ public partial class LzmaStream
|
||||
if (control >= 0xC0)
|
||||
{
|
||||
_needProps = false;
|
||||
await _inputStream
|
||||
await _inputStream!
|
||||
.ReadExactAsync(controlBuffer, 0, 1, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
Properties[0] = controlBuffer[0];
|
||||
@@ -86,7 +140,7 @@ public partial class LzmaStream
|
||||
{
|
||||
_uncompressedChunk = true;
|
||||
var buffer = new byte[2];
|
||||
await _inputStream
|
||||
await _inputStream!
|
||||
.ReadExactAsync(buffer, 0, 2, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
_availableBytes = (buffer[0] << 8) + buffer[1] + 1;
|
||||
@@ -141,7 +195,7 @@ public partial class LzmaStream
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else if (
|
||||
await _decoder
|
||||
await _decoder!
|
||||
.CodeAsync(_dictionarySize, _outWindow, _rangeDecoder, cancellationToken)
|
||||
.ConfigureAwait(false)
|
||||
&& _outputSize < 0
|
||||
@@ -165,7 +219,7 @@ public partial class LzmaStream
|
||||
{
|
||||
_outWindow.SetLimit(toProcess + 1);
|
||||
if (
|
||||
!await _decoder
|
||||
!await _decoder!
|
||||
.CodeAsync(
|
||||
_dictionarySize,
|
||||
_outWindow,
|
||||
@@ -253,7 +307,7 @@ public partial class LzmaStream
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else if (
|
||||
await _decoder
|
||||
await _decoder!
|
||||
.CodeAsync(_dictionarySize, _outWindow, _rangeDecoder, cancellationToken)
|
||||
.ConfigureAwait(false)
|
||||
&& _outputSize < 0
|
||||
@@ -277,7 +331,7 @@ public partial class LzmaStream
|
||||
{
|
||||
_outWindow.SetLimit(toProcess + 1);
|
||||
if (
|
||||
!await _decoder
|
||||
!await _decoder!
|
||||
.CodeAsync(
|
||||
_dictionarySize,
|
||||
_outWindow,
|
||||
|
||||
@@ -161,7 +161,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
return lzma;
|
||||
}
|
||||
|
||||
private LzmaStream(LzmaEncoderProperties properties, bool isLzma2, Stream? presetDictionary)
|
||||
private LzmaStream(LzmaEncoderProperties properties, bool isLzma2)
|
||||
{
|
||||
_isLzma2 = isLzma2;
|
||||
_availableBytes = 0;
|
||||
@@ -177,11 +177,6 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
var prop = new byte[5];
|
||||
_encoder.WriteCoderProperties(prop);
|
||||
Properties = prop;
|
||||
|
||||
if (presetDictionary != null)
|
||||
{
|
||||
_encoder.Train(presetDictionary);
|
||||
}
|
||||
}
|
||||
|
||||
public static LzmaStream Create(
|
||||
@@ -197,7 +192,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
Stream outputStream
|
||||
)
|
||||
{
|
||||
var lzma = new LzmaStream(properties, isLzma2, presetDictionary);
|
||||
var lzma = new LzmaStream(properties, isLzma2);
|
||||
|
||||
lzma._encoder!.SetStreams(null, outputStream, -1, -1);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ internal partial class Encoder
|
||||
var temp = _cache;
|
||||
do
|
||||
{
|
||||
var b = (byte)(temp + (uint)(_low >> 32));
|
||||
var b = (byte)(temp + (_low >> 32));
|
||||
var buffer = new[] { b };
|
||||
await _stream.WriteAsync(buffer, 0, 1, cancellationToken).ConfigureAwait(false);
|
||||
temp = 0xFF;
|
||||
@@ -26,22 +26,6 @@ internal partial class Encoder
|
||||
_low = ((uint)_low) << 8;
|
||||
}
|
||||
|
||||
public async ValueTask EncodeAsync(
|
||||
uint start,
|
||||
uint size,
|
||||
uint total,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
_low += start * (_range /= total);
|
||||
_range *= size;
|
||||
while (_range < K_TOP_VALUE)
|
||||
{
|
||||
_range <<= 8;
|
||||
await ShiftLowAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask EncodeBitAsync(
|
||||
uint size0,
|
||||
int numTotalBits,
|
||||
@@ -114,8 +98,6 @@ internal partial class Decoder
|
||||
_total = 5;
|
||||
}
|
||||
|
||||
public void ReleaseStream() => _stream = null;
|
||||
|
||||
public async ValueTask NormalizeAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
while (_range < K_TOP_VALUE)
|
||||
|
||||
@@ -44,17 +44,6 @@ internal partial class Encoder
|
||||
|
||||
public void CloseStream() => _stream.Dispose();
|
||||
|
||||
public void Encode(uint start, uint size, uint total)
|
||||
{
|
||||
_low += start * (_range /= total);
|
||||
_range *= size;
|
||||
while (_range < K_TOP_VALUE)
|
||||
{
|
||||
_range <<= 8;
|
||||
ShiftLow();
|
||||
}
|
||||
}
|
||||
|
||||
public void ShiftLow()
|
||||
{
|
||||
if ((uint)_low < 0xFF000000 || (uint)(_low >> 32) == 1)
|
||||
@@ -88,29 +77,7 @@ internal partial class Encoder
|
||||
}
|
||||
}
|
||||
|
||||
public void EncodeBit(uint size0, int numTotalBits, uint symbol)
|
||||
{
|
||||
var newBound = (_range >> numTotalBits) * size0;
|
||||
if (symbol == 0)
|
||||
{
|
||||
_range = newBound;
|
||||
}
|
||||
else
|
||||
{
|
||||
_low += newBound;
|
||||
_range -= newBound;
|
||||
}
|
||||
while (_range < K_TOP_VALUE)
|
||||
{
|
||||
_range <<= 8;
|
||||
ShiftLow();
|
||||
}
|
||||
}
|
||||
|
||||
public long GetProcessedSizeAdd() => -1;
|
||||
|
||||
//return _cacheSize + Stream.Position - StartPosition + 4;
|
||||
// (long)Stream.GetProcessedSize();
|
||||
}
|
||||
|
||||
internal partial class Decoder
|
||||
@@ -119,13 +86,11 @@ internal partial class Decoder
|
||||
public uint _range;
|
||||
public uint _code;
|
||||
|
||||
// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
|
||||
public Stream _stream;
|
||||
public long _total;
|
||||
|
||||
public void Init(Stream stream)
|
||||
{
|
||||
// Stream.Init(stream);
|
||||
_stream = stream;
|
||||
|
||||
_code = 0;
|
||||
@@ -141,8 +106,6 @@ internal partial class Decoder
|
||||
// Stream.ReleaseStream();
|
||||
_stream = null;
|
||||
|
||||
public void CloseStream() => _stream.Dispose();
|
||||
|
||||
public void Normalize()
|
||||
{
|
||||
while (_range < K_TOP_VALUE)
|
||||
@@ -181,14 +144,6 @@ internal partial class Decoder
|
||||
for (var i = numTotalBits; i > 0; i--)
|
||||
{
|
||||
range >>= 1;
|
||||
/*
|
||||
result <<= 1;
|
||||
if (code >= range)
|
||||
{
|
||||
code -= range;
|
||||
result |= 1;
|
||||
}
|
||||
*/
|
||||
var t = (code - range) >> 31;
|
||||
code -= range & (t - 1);
|
||||
result = (result << 1) | (1 - t);
|
||||
|
||||
@@ -26,8 +26,6 @@ internal partial struct BitEncoder
|
||||
|
||||
public void Encode(Encoder encoder, uint symbol)
|
||||
{
|
||||
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
|
||||
// UpdateModel(symbol);
|
||||
var newBound = (encoder._range >> K_NUM_BIT_MODEL_TOTAL_BITS) * _prob;
|
||||
if (symbol == 0)
|
||||
{
|
||||
@@ -86,18 +84,6 @@ internal partial struct BitDecoder
|
||||
|
||||
private uint _prob;
|
||||
|
||||
public void UpdateModel(int numMoveBits, uint symbol)
|
||||
{
|
||||
if (symbol == 0)
|
||||
{
|
||||
_prob += (K_BIT_MODEL_TOTAL - _prob) >> numMoveBits;
|
||||
}
|
||||
else
|
||||
{
|
||||
_prob -= (_prob) >> numMoveBits;
|
||||
}
|
||||
}
|
||||
|
||||
public void Init() => _prob = K_BIT_MODEL_TOTAL >> 1;
|
||||
|
||||
public uint Decode(Decoder rangeDecoder)
|
||||
|
||||
@@ -585,7 +585,7 @@ public class LzmaStreamAsyncTests
|
||||
long decompressedSize
|
||||
)
|
||||
{
|
||||
var lzmaStream = LzmaStream.Create(
|
||||
var lzmaStream = await LzmaStream.CreateAsync(
|
||||
properties,
|
||||
compressedStream,
|
||||
compressedSize,
|
||||
|
||||
Reference in New Issue
Block a user