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