mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 05:25:00 +00:00
make an async code
This commit is contained in:
@@ -87,6 +87,12 @@ internal class OutWindow : IDisposable
|
||||
_stream = null;
|
||||
}
|
||||
|
||||
public async Task ReleaseStreamAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||
_stream = null;
|
||||
}
|
||||
|
||||
private void Flush()
|
||||
{
|
||||
if (_stream is null)
|
||||
@@ -147,6 +153,26 @@ internal class OutWindow : IDisposable
|
||||
_pendingLen = rem;
|
||||
}
|
||||
|
||||
public async Task CopyPendingAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_pendingLen < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var rem = _pendingLen;
|
||||
var pos = (_pendingDist < _pos ? _pos : _pos + _windowSize) - _pendingDist - 1;
|
||||
while (rem > 0 && HasSpace)
|
||||
{
|
||||
if (pos >= _windowSize)
|
||||
{
|
||||
pos = 0;
|
||||
}
|
||||
await PutByteAsync(_buffer[pos++], cancellationToken).ConfigureAwait(false);
|
||||
rem--;
|
||||
}
|
||||
_pendingLen = rem;
|
||||
}
|
||||
|
||||
public void CopyBlock(int distance, int len)
|
||||
{
|
||||
var rem = len;
|
||||
@@ -180,6 +206,39 @@ internal class OutWindow : IDisposable
|
||||
_pendingDist = distance;
|
||||
}
|
||||
|
||||
public async Task CopyBlockAsync(int distance, int len, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var rem = len;
|
||||
var pos = (distance < _pos ? _pos : _pos + _windowSize) - distance - 1;
|
||||
var targetSize = HasSpace ? (int)Math.Min(rem, _limit - _total) : 0;
|
||||
var sizeUntilWindowEnd = Math.Min(_windowSize - _pos, _windowSize - pos);
|
||||
var sizeUntilOverlap = Math.Abs(pos - _pos);
|
||||
var fastSize = Math.Min(Math.Min(sizeUntilWindowEnd, sizeUntilOverlap), targetSize);
|
||||
if (fastSize >= 2)
|
||||
{
|
||||
_buffer.AsSpan(pos, fastSize).CopyTo(_buffer.AsSpan(_pos, fastSize));
|
||||
_pos += fastSize;
|
||||
pos += fastSize;
|
||||
_total += fastSize;
|
||||
if (_pos >= _windowSize)
|
||||
{
|
||||
await FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
rem -= fastSize;
|
||||
}
|
||||
while (rem > 0 && HasSpace)
|
||||
{
|
||||
if (pos >= _windowSize)
|
||||
{
|
||||
pos = 0;
|
||||
}
|
||||
await PutByteAsync(_buffer[pos++], cancellationToken).ConfigureAwait(false);
|
||||
rem--;
|
||||
}
|
||||
_pendingLen = rem;
|
||||
_pendingDist = distance;
|
||||
}
|
||||
|
||||
public void PutByte(byte b)
|
||||
{
|
||||
_buffer[_pos++] = b;
|
||||
@@ -190,6 +249,16 @@ internal class OutWindow : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public async Task PutByteAsync(byte b, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_buffer[_pos++] = b;
|
||||
_total++;
|
||||
if (_pos >= _windowSize)
|
||||
{
|
||||
await FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public byte GetByte(int distance)
|
||||
{
|
||||
var pos = _pos - distance - 1;
|
||||
|
||||
@@ -313,6 +313,42 @@ public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
|
||||
_outWindow = null;
|
||||
}
|
||||
|
||||
public async System.Threading.Tasks.Task CodeAsync(
|
||||
Stream inStream,
|
||||
Stream outStream,
|
||||
long inSize,
|
||||
long outSize,
|
||||
ICodeProgress progress,
|
||||
System.Threading.CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
if (_outWindow is null)
|
||||
{
|
||||
CreateDictionary();
|
||||
}
|
||||
_outWindow.Init(outStream);
|
||||
if (outSize > 0)
|
||||
{
|
||||
_outWindow.SetLimit(outSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_outWindow.SetLimit(long.MaxValue - _outWindow.Total);
|
||||
}
|
||||
|
||||
var rangeDecoder = new RangeCoder.Decoder();
|
||||
rangeDecoder.Init(inStream);
|
||||
|
||||
await CodeAsync(_dictionarySize, _outWindow, rangeDecoder, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
await _outWindow.ReleaseStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
rangeDecoder.ReleaseStream();
|
||||
|
||||
_outWindow.Dispose();
|
||||
_outWindow = null;
|
||||
}
|
||||
|
||||
internal bool Code(int dictionarySize, OutWindow outWindow, RangeCoder.Decoder rangeDecoder)
|
||||
{
|
||||
var dictionarySizeCheck = Math.Max(dictionarySize, 1);
|
||||
@@ -439,6 +475,141 @@ public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
|
||||
return false;
|
||||
}
|
||||
|
||||
internal async System.Threading.Tasks.Task<bool> CodeAsync(
|
||||
int dictionarySize,
|
||||
OutWindow outWindow,
|
||||
RangeCoder.Decoder rangeDecoder,
|
||||
System.Threading.CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
var dictionarySizeCheck = Math.Max(dictionarySize, 1);
|
||||
|
||||
await outWindow.CopyPendingAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
while (outWindow.HasSpace)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var posState = (uint)outWindow.Total & _posStateMask;
|
||||
if (
|
||||
_isMatchDecoders[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState]
|
||||
.Decode(rangeDecoder) == 0
|
||||
)
|
||||
{
|
||||
byte b;
|
||||
var prevByte = outWindow.GetByte(0);
|
||||
if (!_state.IsCharState())
|
||||
{
|
||||
b = _literalDecoder.DecodeWithMatchByte(
|
||||
rangeDecoder,
|
||||
(uint)outWindow.Total,
|
||||
prevByte,
|
||||
outWindow.GetByte((int)_rep0)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
b = _literalDecoder.DecodeNormal(rangeDecoder, (uint)outWindow.Total, prevByte);
|
||||
}
|
||||
await outWindow.PutByteAsync(b, cancellationToken).ConfigureAwait(false);
|
||||
_state.UpdateChar();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint len;
|
||||
if (_isRepDecoders[_state._index].Decode(rangeDecoder) == 1)
|
||||
{
|
||||
if (_isRepG0Decoders[_state._index].Decode(rangeDecoder) == 0)
|
||||
{
|
||||
if (
|
||||
_isRep0LongDecoders[
|
||||
(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState
|
||||
]
|
||||
.Decode(rangeDecoder) == 0
|
||||
)
|
||||
{
|
||||
_state.UpdateShortRep();
|
||||
await outWindow
|
||||
.PutByteAsync(outWindow.GetByte((int)_rep0), cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint distance;
|
||||
if (_isRepG1Decoders[_state._index].Decode(rangeDecoder) == 0)
|
||||
{
|
||||
distance = _rep1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_isRepG2Decoders[_state._index].Decode(rangeDecoder) == 0)
|
||||
{
|
||||
distance = _rep2;
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = _rep3;
|
||||
_rep3 = _rep2;
|
||||
}
|
||||
_rep2 = _rep1;
|
||||
}
|
||||
_rep1 = _rep0;
|
||||
_rep0 = distance;
|
||||
}
|
||||
len = _repLenDecoder.Decode(rangeDecoder, posState) + Base.K_MATCH_MIN_LEN;
|
||||
_state.UpdateRep();
|
||||
}
|
||||
else
|
||||
{
|
||||
_rep3 = _rep2;
|
||||
_rep2 = _rep1;
|
||||
_rep1 = _rep0;
|
||||
len = Base.K_MATCH_MIN_LEN + _lenDecoder.Decode(rangeDecoder, posState);
|
||||
_state.UpdateMatch();
|
||||
var posSlot = _posSlotDecoder[Base.GetLenToPosState(len)].Decode(rangeDecoder);
|
||||
if (posSlot >= Base.K_START_POS_MODEL_INDEX)
|
||||
{
|
||||
var numDirectBits = (int)((posSlot >> 1) - 1);
|
||||
_rep0 = ((2 | (posSlot & 1)) << numDirectBits);
|
||||
if (posSlot < Base.K_END_POS_MODEL_INDEX)
|
||||
{
|
||||
_rep0 += BitTreeDecoder.ReverseDecode(
|
||||
_posDecoders,
|
||||
_rep0 - posSlot - 1,
|
||||
rangeDecoder,
|
||||
numDirectBits
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_rep0 += (
|
||||
rangeDecoder.DecodeDirectBits(numDirectBits - Base.K_NUM_ALIGN_BITS)
|
||||
<< Base.K_NUM_ALIGN_BITS
|
||||
);
|
||||
_rep0 += _posAlignDecoder.ReverseDecode(rangeDecoder);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_rep0 = posSlot;
|
||||
}
|
||||
}
|
||||
if (_rep0 >= outWindow.Total || _rep0 >= dictionarySizeCheck)
|
||||
{
|
||||
if (_rep0 == 0xFFFFFFFF)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
throw new DataErrorException();
|
||||
}
|
||||
await outWindow.CopyBlockAsync((int)_rep0, (int)len, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetDecoderProperties(byte[] properties)
|
||||
{
|
||||
if (properties.Length < 1)
|
||||
|
||||
@@ -559,7 +559,7 @@ public class LzmaStream : Stream, IStreamStack
|
||||
.CopyStreamAsync(_inputStream, toProcess, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else if (_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder) && _outputSize < 0)
|
||||
else if (await _decoder.CodeAsync(_dictionarySize, _outWindow, _rangeDecoder, cancellationToken).ConfigureAwait(false) && _outputSize < 0)
|
||||
{
|
||||
_availableBytes = _outWindow.AvailableBytes;
|
||||
}
|
||||
@@ -578,7 +578,7 @@ public class LzmaStream : Stream, IStreamStack
|
||||
)
|
||||
{
|
||||
_outWindow.SetLimit(toProcess + 1);
|
||||
if (!_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder))
|
||||
if (!await _decoder.CodeAsync(_dictionarySize, _outWindow, _rangeDecoder, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
_rangeDecoder.ReleaseStream();
|
||||
throw new DataErrorException();
|
||||
@@ -614,7 +614,7 @@ public class LzmaStream : Stream, IStreamStack
|
||||
byte[] buffer,
|
||||
int offset,
|
||||
int count,
|
||||
CancellationToken cancellationToken = default
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
Reference in New Issue
Block a user