More LZMA conversion going, BZip2 not for now

This commit is contained in:
Adam Hathcock
2021-02-13 10:45:57 +00:00
parent db02e8b634
commit 949e90351f
20 changed files with 301 additions and 272 deletions

View File

@@ -24,7 +24,7 @@ namespace SharpCompress.Common
/// Set this when you want to use a custom method for all decoding operations.
/// </summary>
/// <returns>string Func(bytes, index, length)</returns>
public Func<byte[], int, int, string>? CustomDecoder { get; set; }
//public Func<byte[], int, int, string>? CustomDecoder { get; set; }
public ArchiveEncoding()
: this(Encoding.Default, Encoding.Default)
@@ -50,7 +50,12 @@ namespace SharpCompress.Common
public string Decode(byte[] bytes, int start, int length)
{
return GetDecoder().Invoke(bytes, start, length);
return GetEncoding().GetString(bytes, start, length);
}
public string Decode(ReadOnlySpan<byte> span)
{
return GetEncoding().GetString(span);
}
public string DecodeUTF8(byte[] bytes)
@@ -67,10 +72,5 @@ namespace SharpCompress.Common
{
return Forced ?? Default ?? Encoding.UTF8;
}
public Func<byte[], int, int, string> GetDecoder()
{
return CustomDecoder ?? ((bytes, index, count) => GetEncoding().GetString(bytes, index, count));
}
}
}

View File

@@ -73,10 +73,10 @@ namespace SharpCompress.Common.Zip
{
return new Deflate64Stream(stream, CompressionMode.Decompress);
}
case ZipCompressionMethod.BZip2:
/** case ZipCompressionMethod.BZip2:
{
return await BZip2Stream.CreateAsync(stream, CompressionMode.Decompress, false, cancellationToken);
}
} */
case ZipCompressionMethod.LZMA:
{
if (FlagUtility.HasFlag(Header.Flags, HeaderFlags.Encrypted))
@@ -87,7 +87,7 @@ namespace SharpCompress.Common.Zip
reader.ReadUInt16(); //LZMA version
var props = new byte[reader.ReadUInt16()];
reader.Read(props, 0, props.Length);
return new LzmaStream(props, stream,
return await LzmaStream.CreateAsync(props, stream,
Header.CompressedSize > 0 ? Header.CompressedSize - 4 - props.Length : -1,
FlagUtility.HasFlag(Header.Flags, HeaderFlags.Bit1)
? -1

View File

@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Threading.Tasks;
namespace SharpCompress.Compressors.LZMA
{
@@ -59,7 +60,7 @@ namespace SharpCompress.Compressors.LZMA
/// <param name="progress">
/// callback progress reference.
/// </param>
void Code(Stream inStream, Stream outStream,
ValueTask CodeAsync(Stream inStream, Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress);
}

View File

@@ -1,6 +1,8 @@
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.IO;
using System.Threading.Tasks;
using SharpCompress.Crypto;
using SharpCompress.IO;
@@ -16,26 +18,34 @@ namespace SharpCompress.Compressors.LZMA
/// </summary>
public sealed class LZipStream : Stream
{
private readonly Stream _stream;
private readonly CountingWritableSubStream? _countingWritableSubStream;
#nullable disable
private Stream _stream;
#nullable enable
private CountingWritableSubStream? _countingWritableSubStream;
private bool _disposed;
private bool _finished;
private long _writeCount;
public LZipStream(Stream stream, CompressionMode mode)
private LZipStream()
{
Mode = mode;
}
public static async ValueTask<LZipStream> CreateAsync(Stream stream, CompressionMode mode)
{
var lzip = new LZipStream();
lzip.Mode = mode;
if (mode == CompressionMode.Decompress)
{
int dSize = ValidateAndReadSize(stream);
int dSize = await ValidateAndReadSize(stream);
if (dSize == 0)
{
throw new IOException("Not an LZip stream");
}
byte[] properties = GetProperties(dSize);
_stream = new LzmaStream(properties, stream);
lzip._stream = await LzmaStream.CreateAsync(properties, stream);
}
else
{
@@ -43,9 +53,10 @@ namespace SharpCompress.Compressors.LZMA
int dSize = 104 * 1024;
WriteHeaderSize(stream);
_countingWritableSubStream = new CountingWritableSubStream(stream);
_stream = new Crc32Stream(new LzmaStream(new LzmaEncoderProperties(true, dSize), false, _countingWritableSubStream));
lzip._countingWritableSubStream = new CountingWritableSubStream(stream);
lzip._stream = new Crc32Stream(new LzmaStream(new LzmaEncoderProperties(true, dSize), false, lzip._countingWritableSubStream));
}
return lzip;
}
public void Finish()
@@ -90,7 +101,7 @@ namespace SharpCompress.Compressors.LZMA
}
}
public CompressionMode Mode { get; }
public CompressionMode Mode { get; private set; }
public override bool CanRead => Mode == CompressionMode.Decompress;
@@ -155,14 +166,14 @@ namespace SharpCompress.Compressors.LZMA
/// </summary>
/// <param name="stream">The stream to read from. Must not be null.</param>
/// <returns><c>true</c> if the given stream is an LZip file, <c>false</c> otherwise.</returns>
public static bool IsLZipFile(Stream stream) => ValidateAndReadSize(stream) != 0;
public static async ValueTask<bool> IsLZipFileAsync(Stream stream) => await ValidateAndReadSize(stream) != 0;
/// <summary>
/// Reads the 6-byte header of the stream, and returns 0 if either the header
/// couldn't be read or it isn't a validate LZIP header, or the dictionary
/// size if it *is* a valid LZIP file.
/// </summary>
public static int ValidateAndReadSize(Stream stream)
private static async ValueTask<int> ValidateAndReadSize(Stream stream)
{
if (stream is null)
{
@@ -170,8 +181,9 @@ namespace SharpCompress.Compressors.LZMA
}
// Read the header
Span<byte> header = stackalloc byte[6];
int n = stream.Read(header);
using var buffer = MemoryPool<byte>.Shared.Rent(6);
var header = buffer.Memory.Slice(0,6);
int n = await stream.ReadAsync(header);
// TODO: Handle reading only part of the header?
@@ -180,12 +192,12 @@ namespace SharpCompress.Compressors.LZMA
return 0;
}
if (header[0] != 'L' || header[1] != 'Z' || header[2] != 'I' || header[3] != 'P' || header[4] != 1 /* version 1 */)
if (header.Span[0] != 'L' || header.Span[1] != 'Z' || header.Span[2] != 'I' || header.Span[3] != 'P' || header.Span[4] != 1 /* version 1 */)
{
return 0;
}
int basePower = header[5] & 0x1F;
int subtractionNumerator = (header[5] & 0xE0) >> 5;
int basePower = header.Span[5] & 0x1F;
int subtractionNumerator = (header.Span[5] & 0xE0) >> 5;
return (1 << basePower) - subtractionNumerator * (1 << (basePower - 4));
}

View File

@@ -1,7 +1,6 @@
#nullable disable
using System;
using System.IO;
using System.Threading.Tasks;
using SharpCompress.Compressors.LZMA.LZ;
using SharpCompress.Compressors.LZMA.RangeCoder;
@@ -11,11 +10,11 @@ namespace SharpCompress.Compressors.LZMA
{
private class LenDecoder
{
private BitDecoder _choice = new BitDecoder();
private BitDecoder _choice2 = new BitDecoder();
private BitDecoder _choice = new();
private BitDecoder _choice2 = new();
private readonly BitTreeDecoder[] _lowCoder = new BitTreeDecoder[Base.K_NUM_POS_STATES_MAX];
private readonly BitTreeDecoder[] _midCoder = new BitTreeDecoder[Base.K_NUM_POS_STATES_MAX];
private BitTreeDecoder _highCoder = new BitTreeDecoder(Base.K_NUM_HIGH_LEN_BITS);
private BitTreeDecoder _highCoder = new(Base.K_NUM_HIGH_LEN_BITS);
private uint _numPosStates;
public void Create(uint numPosStates)
@@ -113,12 +112,12 @@ namespace SharpCompress.Compressors.LZMA
}
}
private Decoder2[] _coders;
private int _numPrevBits;
private int _numPosBits;
private uint _posMask;
public void Create(int numPosBits, int numPrevBits)
private readonly Decoder2[]_coders;
private readonly int _numPrevBits;
private readonly int _numPosBits;
private readonly uint _posMask;
public LiteralDecoder(int numPosBits, int numPrevBits)
{
if (_coders != null && _numPrevBits == numPrevBits &&
_numPosBits == numPosBits)
@@ -161,7 +160,7 @@ namespace SharpCompress.Compressors.LZMA
}
}
private OutWindow _outWindow;
private OutWindow? _outWindow;
private readonly BitDecoder[] _isMatchDecoders = new BitDecoder[Base.K_NUM_STATES << Base.K_NUM_POS_STATES_BITS_MAX];
private readonly BitDecoder[] _isRepDecoders = new BitDecoder[Base.K_NUM_STATES];
@@ -173,18 +172,18 @@ namespace SharpCompress.Compressors.LZMA
private readonly BitTreeDecoder[] _posSlotDecoder = new BitTreeDecoder[Base.K_NUM_LEN_TO_POS_STATES];
private readonly BitDecoder[] _posDecoders = new BitDecoder[Base.K_NUM_FULL_DISTANCES - Base.K_END_POS_MODEL_INDEX];
private BitTreeDecoder _posAlignDecoder = new BitTreeDecoder(Base.K_NUM_ALIGN_BITS);
private BitTreeDecoder _posAlignDecoder = new(Base.K_NUM_ALIGN_BITS);
private readonly LenDecoder _lenDecoder = new LenDecoder();
private readonly LenDecoder _repLenDecoder = new LenDecoder();
private readonly LenDecoder _lenDecoder = new();
private readonly LenDecoder _repLenDecoder = new();
private readonly LiteralDecoder _literalDecoder = new LiteralDecoder();
private LiteralDecoder? _literalDecoder;
private int _dictionarySize;
private uint _posStateMask;
private Base.State _state = new Base.State();
private Base.State _state = new();
private uint _rep0, _rep1, _rep2, _rep3;
public Decoder()
@@ -196,15 +195,16 @@ namespace SharpCompress.Compressors.LZMA
}
}
private void CreateDictionary()
private OutWindow CreateDictionary()
{
if (_dictionarySize < 0)
{
throw new InvalidParamException();
}
_outWindow = new OutWindow();
var outWindow = new OutWindow();
int blockSize = Math.Max(_dictionarySize, (1 << 12));
_outWindow.Create(blockSize);
outWindow.Create(blockSize);
return outWindow;
}
private void SetLiteralProperties(int lp, int lc)
@@ -217,7 +217,7 @@ namespace SharpCompress.Compressors.LZMA
{
throw new InvalidParamException();
}
_literalDecoder.Create(lp, lc);
_literalDecoder = new(lp, lc);
}
private void SetPosBitsProperties(int pb)
@@ -249,7 +249,7 @@ namespace SharpCompress.Compressors.LZMA
_isRepG2Decoders[i].Init();
}
_literalDecoder.Init();
_literalDecoder?.Init();
for (i = 0; i < Base.K_NUM_LEN_TO_POS_STATES; i++)
{
_posSlotDecoder[i].Init();
@@ -272,12 +272,12 @@ namespace SharpCompress.Compressors.LZMA
_rep3 = 0;
}
public void Code(Stream inStream, Stream outStream,
public async ValueTask CodeAsync(Stream inStream, Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress)
{
if (_outWindow is null)
{
CreateDictionary();
_outWindow = CreateDictionary();
}
_outWindow.Init(outStream);
if (outSize > 0)
@@ -290,7 +290,7 @@ namespace SharpCompress.Compressors.LZMA
}
RangeCoder.Decoder rangeDecoder = new RangeCoder.Decoder();
rangeDecoder.Init(inStream);
await rangeDecoder.InitAsync(inStream);
Code(_dictionarySize, _outWindow, rangeDecoder);
@@ -310,6 +310,7 @@ namespace SharpCompress.Compressors.LZMA
internal bool Code(int dictionarySize, OutWindow outWindow, RangeCoder.Decoder rangeDecoder)
{
_literalDecoder ??= _literalDecoder.CheckNotNull(nameof(_literalDecoder));
int dictionarySizeCheck = Math.Max(dictionarySize, 1);
outWindow.CopyPending();
@@ -450,7 +451,7 @@ namespace SharpCompress.Compressors.LZMA
{
if (_outWindow is null)
{
CreateDictionary();
_outWindow = CreateDictionary();
}
_outWindow.Train(stream);
}

View File

@@ -2,6 +2,7 @@
using System;
using System.IO;
using System.Threading.Tasks;
using SharpCompress.Compressors.LZMA.LZ;
using SharpCompress.Compressors.LZMA.RangeCoder;
@@ -61,7 +62,7 @@ namespace SharpCompress.Compressors.LZMA
return (UInt32)(G_FAST_POS[pos >> 26] + 52);
}
private Base.State _state = new Base.State();
private Base.State _state = new();
private Byte _previousByte;
private readonly UInt32[] _repDistances = new UInt32[Base.K_NUM_REP_DISTANCES];
@@ -97,18 +98,18 @@ namespace SharpCompress.Compressors.LZMA
}
}
public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol)
public async ValueTask EncodeAsync(RangeCoder.Encoder rangeEncoder, byte symbol)
{
uint context = 1;
for (int i = 7; i >= 0; i--)
{
uint bit = (uint)((symbol >> i) & 1);
_encoders[context].Encode(rangeEncoder, bit);
await _encoders[context].EncodeAsync(rangeEncoder, bit);
context = (context << 1) | bit;
}
}
public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
public async ValueTask EncodeMatchedAsync(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
{
uint context = 1;
bool same = true;
@@ -122,7 +123,7 @@ namespace SharpCompress.Compressors.LZMA
state += ((1 + matchBit) << 8);
same = (matchBit == bit);
}
_encoders[state].Encode(rangeEncoder, bit);
await _encoders[state].EncodeAsync(rangeEncoder, bit);
context = (context << 1) | bit;
}
}
@@ -196,11 +197,11 @@ namespace SharpCompress.Compressors.LZMA
private class LenEncoder
{
private BitEncoder _choice = new BitEncoder();
private BitEncoder _choice2 = new BitEncoder();
private BitEncoder _choice = new();
private BitEncoder _choice2 = new();
private readonly BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.K_NUM_POS_STATES_ENCODING_MAX];
private readonly BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.K_NUM_POS_STATES_ENCODING_MAX];
private BitTreeEncoder _highCoder = new BitTreeEncoder(Base.K_NUM_HIGH_LEN_BITS);
private BitTreeEncoder _highCoder = new(Base.K_NUM_HIGH_LEN_BITS);
public LenEncoder()
{
@@ -223,26 +224,26 @@ namespace SharpCompress.Compressors.LZMA
_highCoder.Init();
}
public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
public virtual async ValueTask EncodeAsync(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
{
if (symbol < Base.K_NUM_LOW_LEN_SYMBOLS)
{
_choice.Encode(rangeEncoder, 0);
_lowCoder[posState].Encode(rangeEncoder, symbol);
await _choice.EncodeAsync(rangeEncoder, 0);
await _lowCoder[posState].EncodeAsync(rangeEncoder, symbol);
}
else
{
symbol -= Base.K_NUM_LOW_LEN_SYMBOLS;
_choice.Encode(rangeEncoder, 1);
await _choice.EncodeAsync(rangeEncoder, 1);
if (symbol < Base.K_NUM_MID_LEN_SYMBOLS)
{
_choice2.Encode(rangeEncoder, 0);
_midCoder[posState].Encode(rangeEncoder, symbol);
await _choice2.EncodeAsync(rangeEncoder, 0);
await _midCoder[posState].EncodeAsync(rangeEncoder, symbol);
}
else
{
_choice2.Encode(rangeEncoder, 1);
_highCoder.Encode(rangeEncoder, symbol - Base.K_NUM_MID_LEN_SYMBOLS);
await _choice2.EncodeAsync(rangeEncoder, 1);
await _highCoder.EncodeAsync(rangeEncoder, symbol - Base.K_NUM_MID_LEN_SYMBOLS);
}
}
}
@@ -309,9 +310,9 @@ namespace SharpCompress.Compressors.LZMA
}
}
public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
public override async ValueTask EncodeAsync(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
{
base.Encode(rangeEncoder, symbol, posState);
await base.EncodeAsync(rangeEncoder, symbol, posState);
if (--_counters[posState] == 0)
{
UpdateTable(posState);
@@ -361,7 +362,7 @@ namespace SharpCompress.Compressors.LZMA
private readonly Optimal[] _optimum = new Optimal[K_NUM_OPTS];
private BinTree _matchFinder;
private readonly RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder();
private readonly RangeCoder.Encoder _rangeEncoder = new();
private readonly BitEncoder[] _isMatch =
new BitEncoder[Base.K_NUM_STATES << Base.K_NUM_POS_STATES_BITS_MAX];
@@ -379,12 +380,12 @@ namespace SharpCompress.Compressors.LZMA
private readonly BitEncoder[] _posEncoders =
new BitEncoder[Base.K_NUM_FULL_DISTANCES - Base.K_END_POS_MODEL_INDEX];
private BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.K_NUM_ALIGN_BITS);
private BitTreeEncoder _posAlignEncoder = new(Base.K_NUM_ALIGN_BITS);
private readonly LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
private readonly LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
private readonly LenPriceTableEncoder _lenEncoder = new();
private readonly LenPriceTableEncoder _repMatchLenEncoder = new();
private readonly LiteralEncoder _literalEncoder = new LiteralEncoder();
private readonly LiteralEncoder _literalEncoder = new();
private readonly UInt32[] _matchDistances = new UInt32[Base.K_MATCH_MAX_LEN * 2 + 2];
@@ -1189,40 +1190,40 @@ namespace SharpCompress.Compressors.LZMA
return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));
}
private void WriteEndMarker(UInt32 posState)
private async ValueTask WriteEndMarkerAsync(UInt32 posState)
{
if (!_writeEndMark)
{
return;
}
_isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState].Encode(_rangeEncoder, 1);
_isRep[_state._index].Encode(_rangeEncoder, 0);
await _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState].EncodeAsync(_rangeEncoder, 1);
await _isRep[_state._index].EncodeAsync(_rangeEncoder, 0);
_state.UpdateMatch();
UInt32 len = Base.K_MATCH_MIN_LEN;
_lenEncoder.Encode(_rangeEncoder, len - Base.K_MATCH_MIN_LEN, posState);
await _lenEncoder.EncodeAsync(_rangeEncoder, len - Base.K_MATCH_MIN_LEN, posState);
UInt32 posSlot = (1 << Base.K_NUM_POS_SLOT_BITS) - 1;
UInt32 lenToPosState = Base.GetLenToPosState(len);
_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
await _posSlotEncoder[lenToPosState].EncodeAsync(_rangeEncoder, posSlot);
int footerBits = 30;
UInt32 posReduced = (((UInt32)1) << footerBits) - 1;
_rangeEncoder.EncodeDirectBits(posReduced >> Base.K_NUM_ALIGN_BITS, footerBits - Base.K_NUM_ALIGN_BITS);
_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.K_ALIGN_MASK);
await _rangeEncoder.EncodeDirectBits(posReduced >> Base.K_NUM_ALIGN_BITS, footerBits - Base.K_NUM_ALIGN_BITS);
await _posAlignEncoder.ReverseEncodeAsync(_rangeEncoder, posReduced & Base.K_ALIGN_MASK);
}
private void Flush(UInt32 nowPos)
private async ValueTask FlushAsync(UInt32 nowPos)
{
ReleaseMfStream();
WriteEndMarker(nowPos & _posStateMask);
_rangeEncoder.FlushData();
_rangeEncoder.FlushStream();
await WriteEndMarkerAsync(nowPos & _posStateMask);
await _rangeEncoder.FlushData();
await _rangeEncoder.FlushAsync();
}
public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)
public async ValueTask<(Int64, Int64, bool)> CodeOneBlockAsync()
{
inSize = 0;
outSize = 0;
finished = true;
long inSize = 0;
long outSize = 0;
var finished = true;
if (_inStream != null)
{
@@ -1233,7 +1234,7 @@ namespace SharpCompress.Compressors.LZMA
if (_finished)
{
return;
return (inSize, outSize, finished);
}
_finished = true;
@@ -1254,20 +1255,20 @@ namespace SharpCompress.Compressors.LZMA
if (_processingMode && _matchFinder.IsDataStarved)
{
_finished = false;
return;
return (inSize, outSize, finished);
}
if (_matchFinder.GetNumAvailableBytes() == 0)
{
Flush((UInt32)_nowPos64);
return;
await FlushAsync((UInt32)_nowPos64);
return (inSize, outSize, finished);
}
UInt32 len, numDistancePairs; // it's not used
ReadMatchDistances(out len, out numDistancePairs);
UInt32 posState = (UInt32)(_nowPos64) & _posStateMask;
_isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState].Encode(_rangeEncoder, 0);
await _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState].EncodeAsync(_rangeEncoder, 0);
_state.UpdateChar();
Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
_literalEncoder.GetSubCoder((UInt32)(_nowPos64), _previousByte).Encode(_rangeEncoder, curByte);
await _literalEncoder.GetSubCoder((UInt32)(_nowPos64), _previousByte).EncodeAsync(_rangeEncoder, curByte);
_previousByte = curByte;
_additionalOffset--;
_nowPos64++;
@@ -1275,19 +1276,19 @@ namespace SharpCompress.Compressors.LZMA
if (_processingMode && _matchFinder.IsDataStarved)
{
_finished = false;
return;
return (inSize, outSize, finished);
}
if (_matchFinder.GetNumAvailableBytes() == 0)
{
Flush((UInt32)_nowPos64);
return;
await FlushAsync((UInt32)_nowPos64);
return (inSize, outSize, finished);
}
while (true)
{
if (_processingMode && _matchFinder.IsDataStarved)
{
_finished = false;
return;
return (inSize, outSize, finished);
}
UInt32 pos;
@@ -1297,51 +1298,51 @@ namespace SharpCompress.Compressors.LZMA
UInt32 complexState = (_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState;
if (len == 1 && pos == 0xFFFFFFFF)
{
_isMatch[complexState].Encode(_rangeEncoder, 0);
await _isMatch[complexState].EncodeAsync(_rangeEncoder, 0);
Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)_nowPos64, _previousByte);
if (!_state.IsCharState())
{
Byte matchByte =
_matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset));
subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
await subCoder.EncodeMatchedAsync(_rangeEncoder, matchByte, curByte);
}
else
{
subCoder.Encode(_rangeEncoder, curByte);
await subCoder.EncodeAsync(_rangeEncoder, curByte);
}
_previousByte = curByte;
_state.UpdateChar();
}
else
{
_isMatch[complexState].Encode(_rangeEncoder, 1);
await _isMatch[complexState].EncodeAsync(_rangeEncoder, 1);
if (pos < Base.K_NUM_REP_DISTANCES)
{
_isRep[_state._index].Encode(_rangeEncoder, 1);
await _isRep[_state._index].EncodeAsync(_rangeEncoder, 1);
if (pos == 0)
{
_isRepG0[_state._index].Encode(_rangeEncoder, 0);
await _isRepG0[_state._index].EncodeAsync(_rangeEncoder, 0);
if (len == 1)
{
_isRep0Long[complexState].Encode(_rangeEncoder, 0);
await _isRep0Long[complexState].EncodeAsync(_rangeEncoder, 0);
}
else
{
_isRep0Long[complexState].Encode(_rangeEncoder, 1);
await _isRep0Long[complexState].EncodeAsync(_rangeEncoder, 1);
}
}
else
{
_isRepG0[_state._index].Encode(_rangeEncoder, 1);
await _isRepG0[_state._index].EncodeAsync(_rangeEncoder, 1);
if (pos == 1)
{
_isRepG1[_state._index].Encode(_rangeEncoder, 0);
await _isRepG1[_state._index].EncodeAsync(_rangeEncoder, 0);
}
else
{
_isRepG1[_state._index].Encode(_rangeEncoder, 1);
_isRepG2[_state._index].Encode(_rangeEncoder, pos - 2);
await _isRepG1[_state._index].EncodeAsync(_rangeEncoder, 1);
await _isRepG2[_state._index].EncodeAsync(_rangeEncoder, pos - 2);
}
}
if (len == 1)
@@ -1350,7 +1351,7 @@ namespace SharpCompress.Compressors.LZMA
}
else
{
_repMatchLenEncoder.Encode(_rangeEncoder, len - Base.K_MATCH_MIN_LEN, posState);
await _repMatchLenEncoder.EncodeAsync(_rangeEncoder, len - Base.K_MATCH_MIN_LEN, posState);
_state.UpdateRep();
}
UInt32 distance = _repDistances[pos];
@@ -1365,13 +1366,13 @@ namespace SharpCompress.Compressors.LZMA
}
else
{
_isRep[_state._index].Encode(_rangeEncoder, 0);
await _isRep[_state._index].EncodeAsync(_rangeEncoder, 0);
_state.UpdateMatch();
_lenEncoder.Encode(_rangeEncoder, len - Base.K_MATCH_MIN_LEN, posState);
await _lenEncoder.EncodeAsync(_rangeEncoder, len - Base.K_MATCH_MIN_LEN, posState);
pos -= Base.K_NUM_REP_DISTANCES;
UInt32 posSlot = GetPosSlot(pos);
UInt32 lenToPosState = Base.GetLenToPosState(len);
_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
await _posSlotEncoder[lenToPosState].EncodeAsync(_rangeEncoder, posSlot);
if (posSlot >= Base.K_START_POS_MODEL_INDEX)
{
@@ -1381,15 +1382,15 @@ namespace SharpCompress.Compressors.LZMA
if (posSlot < Base.K_END_POS_MODEL_INDEX)
{
BitTreeEncoder.ReverseEncode(_posEncoders,
baseVal - posSlot - 1, _rangeEncoder, footerBits,
posReduced);
await BitTreeEncoder.ReverseEncodeAsync(_posEncoders,
baseVal - posSlot - 1, _rangeEncoder, footerBits,
posReduced);
}
else
{
_rangeEncoder.EncodeDirectBits(posReduced >> Base.K_NUM_ALIGN_BITS,
await _rangeEncoder.EncodeDirectBits(posReduced >> Base.K_NUM_ALIGN_BITS,
footerBits - Base.K_NUM_ALIGN_BITS);
_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.K_ALIGN_MASK);
await _posAlignEncoder.ReverseEncodeAsync(_rangeEncoder, posReduced & Base.K_ALIGN_MASK);
_alignPriceCount++;
}
}
@@ -1421,19 +1422,19 @@ namespace SharpCompress.Compressors.LZMA
if (_processingMode && _matchFinder.IsDataStarved)
{
_finished = false;
return;
return (inSize, outSize, finished);
}
if (_matchFinder.GetNumAvailableBytes() == 0)
{
Flush((UInt32)_nowPos64);
return;
await FlushAsync((UInt32)_nowPos64);
return (inSize, outSize, finished);
}
if (_nowPos64 - progressPosValuePrev >= (1 << 12))
{
_finished = false;
finished = false;
return;
return (inSize, outSize, finished);
}
}
}
@@ -1488,7 +1489,7 @@ namespace SharpCompress.Compressors.LZMA
_nowPos64 = 0;
}
public void Code(Stream inStream, Stream outStream,
public async ValueTask CodeAsync(Stream inStream, Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress)
{
_needReleaseMfStream = false;
@@ -1498,10 +1499,7 @@ namespace SharpCompress.Compressors.LZMA
SetStreams(inStream, outStream, inSize, outSize);
while (true)
{
Int64 processedInSize;
Int64 processedOutSize;
bool finished;
CodeOneBlock(out processedInSize, out processedOutSize, out finished);
var (processedInSize, processedOutSize, finished) = await CodeOneBlockAsync();
if (finished)
{
return;
@@ -1518,7 +1516,7 @@ namespace SharpCompress.Compressors.LZMA
}
}
public long Code(Stream inStream, bool final)
public async ValueTask<long> CodeAsync(Stream inStream, bool final)
{
_matchFinder.SetStream(inStream);
_processingMode = !final;
@@ -1526,10 +1524,7 @@ namespace SharpCompress.Compressors.LZMA
{
while (true)
{
Int64 processedInSize;
Int64 processedOutSize;
bool finished;
CodeOneBlock(out processedInSize, out processedOutSize, out finished);
var (processedInSize, processedOutSize, finished) = await CodeOneBlockAsync();
if (finished)
{
return processedInSize;

View File

@@ -1,21 +1,24 @@
#nullable disable
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Compressors.LZMA.LZ;
namespace SharpCompress.Compressors.LZMA
{
public class LzmaStream : Stream
{
private readonly Stream _inputStream;
private readonly long _inputSize;
private readonly long _outputSize;
private Stream _inputStream;
private long _inputSize;
private long _outputSize;
private readonly int _dictionarySize;
private readonly OutWindow _outWindow = new OutWindow();
private readonly RangeCoder.Decoder _rangeDecoder = new RangeCoder.Decoder();
private int _dictionarySize;
private OutWindow _outWindow = new OutWindow();
private RangeCoder.Decoder _rangeDecoder = new RangeCoder.Decoder();
private Decoder _decoder;
private long _position;
@@ -25,70 +28,60 @@ namespace SharpCompress.Compressors.LZMA
private long _inputPosition;
// LZMA2
private readonly bool _isLzma2;
private bool _isLzma2;
private bool _uncompressedChunk;
private bool _needDictReset = true;
private bool _needProps = true;
private readonly Encoder _encoder;
private bool _isDisposed;
private LzmaStream() {}
public LzmaStream(byte[] properties, Stream inputStream)
: this(properties, inputStream, -1, -1, null, properties.Length < 5)
public static async ValueTask<LzmaStream> CreateAsync(byte[] properties, Stream inputStream, long inputSize = -1, long outputSize = -1,
Stream presetDictionary = null, bool? isLzma2 = null)
{
}
var ls = new LzmaStream();
ls._inputStream = inputStream;
ls._inputSize = inputSize;
ls._outputSize = outputSize;
ls._isLzma2 = isLzma2 ?? properties.Length < 5;
public LzmaStream(byte[] properties, Stream inputStream, long inputSize)
: this(properties, inputStream, inputSize, -1, null, properties.Length < 5)
{
}
public LzmaStream(byte[] properties, Stream inputStream, long inputSize, long outputSize)
: this(properties, inputStream, inputSize, outputSize, null, properties.Length < 5)
{
}
public LzmaStream(byte[] properties, Stream inputStream, long inputSize, long outputSize,
Stream presetDictionary, bool isLzma2)
{
_inputStream = inputStream;
_inputSize = inputSize;
_outputSize = outputSize;
_isLzma2 = isLzma2;
if (!isLzma2)
if (!ls._isLzma2)
{
_dictionarySize = BinaryPrimitives.ReadInt32LittleEndian(properties.AsSpan(1));
_outWindow.Create(_dictionarySize);
ls._dictionarySize = BinaryPrimitives.ReadInt32LittleEndian(properties.AsSpan(1));
ls._outWindow.Create(ls._dictionarySize);
if (presetDictionary != null)
{
_outWindow.Train(presetDictionary);
ls._outWindow.Train(presetDictionary);
}
_rangeDecoder.Init(inputStream);
await ls._rangeDecoder.InitAsync(inputStream);
_decoder = new Decoder();
_decoder.SetDecoderProperties(properties);
Properties = properties;
ls._decoder = new Decoder();
ls._decoder.SetDecoderProperties(properties);
ls.Properties = properties;
_availableBytes = outputSize < 0 ? long.MaxValue : outputSize;
_rangeDecoderLimit = inputSize;
ls._availableBytes = outputSize < 0 ? long.MaxValue : outputSize;
ls._rangeDecoderLimit = inputSize;
}
else
{
_dictionarySize = 2 | (properties[0] & 1);
_dictionarySize <<= (properties[0] >> 1) + 11;
ls. _dictionarySize = 2 | (properties[0] & 1);
ls. _dictionarySize <<= (properties[0] >> 1) + 11;
_outWindow.Create(_dictionarySize);
ls._outWindow.Create(ls._dictionarySize);
if (presetDictionary != null)
{
_outWindow.Train(presetDictionary);
_needDictReset = false;
ls._outWindow.Train(presetDictionary);
ls._needDictReset = false;
}
Properties = new byte[1];
_availableBytes = 0;
ls. Properties = new byte[1];
ls._availableBytes = 0;
}
return ls;
}
public LzmaStream(LzmaEncoderProperties properties, bool isLzma2, Stream outputStream)
@@ -128,24 +121,26 @@ namespace SharpCompress.Compressors.LZMA
public override void Flush()
{
throw new NotSupportedException();
}
protected override void Dispose(bool disposing)
public override async ValueTask DisposeAsync()
{
if (_isDisposed)
{
return;
}
_isDisposed = true;
if (disposing)
if (_encoder != null)
{
if (_encoder != null)
{
_position = _encoder.Code(null, true);
}
_inputStream?.Dispose();
_position = await _encoder.CodeAsync(null, true);
}
base.Dispose(disposing);
_inputStream?.DisposeAsync();
}
protected override void Dispose(bool disposing)
{
throw new NotSupportedException();
}
public override long Length => _position + _availableBytes;
@@ -153,6 +148,11 @@ namespace SharpCompress.Compressors.LZMA
public override long Position { get => _position; set => throw new NotSupportedException(); }
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (_endReached)
{
@@ -166,7 +166,7 @@ namespace SharpCompress.Compressors.LZMA
{
if (_isLzma2)
{
DecodeChunkHeader();
await DecodeChunkHeader();
}
else
{
@@ -231,7 +231,7 @@ namespace SharpCompress.Compressors.LZMA
return total;
}
private void DecodeChunkHeader()
private async ValueTask DecodeChunkHeader()
{
int control = _inputStream.ReadByte();
_inputPosition++;
@@ -283,7 +283,7 @@ namespace SharpCompress.Compressors.LZMA
_decoder.SetDecoderProperties(Properties);
}
_rangeDecoder.Init(_inputStream);
await _rangeDecoder.InitAsync(_inputStream);
}
else if (control > 0x02)
{
@@ -307,14 +307,22 @@ namespace SharpCompress.Compressors.LZMA
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = new CancellationToken())
{
if (_encoder != null)
{
_position = _encoder.Code(new MemoryStream(buffer, offset, count), false);
var m = ArrayPool<byte>.Shared.Rent(buffer.Length);
buffer.CopyTo(m.AsMemory());
_position = await _encoder.CodeAsync(new MemoryStream(m), false);
ArrayPool<byte>.Shared.Return(m);
}
}
public byte[] Properties { get; } = new byte[5];
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public byte[] Properties { get; private set; }
}
}

View File

@@ -1,11 +1,13 @@
#nullable disable
using System;
using System.Buffers;
using System.IO;
using System.Threading.Tasks;
namespace SharpCompress.Compressors.LZMA.RangeCoder
{
internal class Encoder
internal class Encoder : IAsyncDisposable
{
public const uint K_TOP_VALUE = (1 << 24);
@@ -38,43 +40,46 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
_cache = 0;
}
public void FlushData()
public async ValueTask FlushData()
{
for (int i = 0; i < 5; i++)
{
ShiftLow();
await ShiftLowAsync();
}
}
public void FlushStream()
public Task FlushAsync()
{
_stream.Flush();
return _stream.FlushAsync();
}
public void CloseStream()
public ValueTask DisposeAsync()
{
_stream.Dispose();
return _stream.DisposeAsync();
}
public void Encode(uint start, uint size, uint total)
public async ValueTask EncodeAsync(uint start, uint size, uint total)
{
_low += start * (_range /= total);
_range *= size;
while (_range < K_TOP_VALUE)
{
_range <<= 8;
ShiftLow();
await ShiftLowAsync();
}
}
public void ShiftLow()
public async ValueTask ShiftLowAsync()
{
if ((uint)_low < 0xFF000000 || (uint)(_low >> 32) == 1)
{
using var buffer = MemoryPool<byte>.Shared.Rent(1);
var b = buffer.Memory.Slice(0,1);
byte temp = _cache;
do
{
_stream.WriteByte((byte)(temp + (_low >> 32)));
b.Span[0] = (byte)(temp + (_low >> 32));
await _stream.WriteAsync(b);
temp = 0xFF;
}
while (--_cacheSize != 0);
@@ -84,7 +89,7 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
_low = ((uint)_low) << 8;
}
public void EncodeDirectBits(uint v, int numTotalBits)
public async ValueTask EncodeDirectBits(uint v, int numTotalBits)
{
for (int i = numTotalBits - 1; i >= 0; i--)
{
@@ -96,12 +101,12 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
if (_range < K_TOP_VALUE)
{
_range <<= 8;
ShiftLow();
await ShiftLowAsync();
}
}
}
public void EncodeBit(uint size0, int numTotalBits, uint symbol)
public async ValueTask EncodeBitAsync(uint size0, int numTotalBits, uint symbol)
{
uint newBound = (_range >> numTotalBits) * size0;
if (symbol == 0)
@@ -116,7 +121,7 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
while (_range < K_TOP_VALUE)
{
_range <<= 8;
ShiftLow();
await ShiftLowAsync();
}
}
@@ -129,7 +134,7 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
}
}
internal class Decoder
internal class Decoder: IAsyncDisposable
{
public const uint K_TOP_VALUE = (1 << 24);
public uint _range;
@@ -139,16 +144,19 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
public Stream _stream;
public long _total;
public void Init(Stream stream)
public async ValueTask InitAsync(Stream stream)
{
// Stream.Init(stream);
_stream = stream;
_code = 0;
_range = 0xFFFFFFFF;
using var buffer = MemoryPool<byte>.Shared.Rent(1);
var b = buffer.Memory.Slice(0,1);
for (int i = 0; i < 5; i++)
{
_code = (_code << 8) | (byte)_stream.ReadByte();
await _stream.ReadAsync(b);
_code = (_code << 8) | b.Span[0];
}
_total = 5;
}
@@ -159,41 +167,34 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
_stream = null;
}
public void CloseStream()
public ValueTask DisposeAsync()
{
_stream.Dispose();
return _stream.DisposeAsync();
}
public void Normalize()
public async ValueTask NormalizeAsync()
{
using var buffer = MemoryPool<byte>.Shared.Rent(1);
var b = buffer.Memory.Slice(0,1);
while (_range < K_TOP_VALUE)
{
_code = (_code << 8) | (byte)_stream.ReadByte();
await _stream.ReadAsync(b);
_code = (_code << 8) | b.Span[0];
_range <<= 8;
_total++;
}
}
public void Normalize2()
{
if (_range < K_TOP_VALUE)
{
_code = (_code << 8) | (byte)_stream.ReadByte();
_range <<= 8;
_total++;
}
}
public uint GetThreshold(uint total)
{
return _code / (_range /= total);
}
public void Decode(uint start, uint size)
public async ValueTask Decode(uint start, uint size)
{
_code -= start * _range;
_range *= size;
Normalize();
await NormalizeAsync();
}
public uint DecodeDirectBits(int numTotalBits)
@@ -228,7 +229,7 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
return result;
}
public uint DecodeBit(uint size0, int numTotalBits)
public async ValueTask<uint> DecodeBitAsync(uint size0, int numTotalBits)
{
uint newBound = (_range >> numTotalBits) * size0;
uint symbol;
@@ -243,7 +244,7 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
_code -= newBound;
_range -= newBound;
}
Normalize();
await NormalizeAsync();
return symbol;
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
namespace SharpCompress.Compressors.LZMA.RangeCoder
{
@@ -29,7 +30,7 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
}
}
public void Encode(Encoder encoder, uint symbol)
public async ValueTask EncodeAsync(Encoder encoder, uint symbol)
{
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
// UpdateModel(symbol);
@@ -48,7 +49,7 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
if (encoder._range < Encoder.K_TOP_VALUE)
{
encoder._range <<= 8;
encoder.ShiftLow();
await encoder.ShiftLowAsync();
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
namespace SharpCompress.Compressors.LZMA.RangeCoder
{
@@ -21,25 +22,25 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
}
}
public void Encode(Encoder rangeEncoder, UInt32 symbol)
public async ValueTask EncodeAsync(Encoder rangeEncoder, UInt32 symbol)
{
UInt32 m = 1;
for (int bitIndex = _numBitLevels; bitIndex > 0;)
{
bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1;
_models[m].Encode(rangeEncoder, bit);
await _models[m].EncodeAsync(rangeEncoder, bit);
m = (m << 1) | bit;
}
}
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
public async ValueTask ReverseEncodeAsync(Encoder rangeEncoder, UInt32 symbol)
{
UInt32 m = 1;
for (UInt32 i = 0; i < _numBitLevels; i++)
{
UInt32 bit = symbol & 1;
_models[m].Encode(rangeEncoder, bit);
await _models[m].EncodeAsync(rangeEncoder, bit);
m = (m << 1) | bit;
symbol >>= 1;
}
@@ -88,14 +89,14 @@ namespace SharpCompress.Compressors.LZMA.RangeCoder
return price;
}
public static void ReverseEncode(BitEncoder[] models, UInt32 startIndex,
public static async ValueTask ReverseEncodeAsync(BitEncoder[] models, UInt32 startIndex,
Encoder rangeEncoder, int numBitLevels, UInt32 symbol)
{
UInt32 m = 1;
for (int i = 0; i < numBitLevels; i++)
{
UInt32 bit = symbol & 1;
models[startIndex + m].Encode(rangeEncoder, bit);
await models[startIndex + m].EncodeAsync(rangeEncoder, bit);
m = (m << 1) | bit;
symbol >>= 1;
}

View File

@@ -27,6 +27,7 @@ namespace SharpCompress.Compressors.LZMA
internal static async ValueTask<Stream> CreateDecoderStream(CMethodId id, Stream[] inStreams, byte[] info, IPasswordProvider pass,
long limit, CancellationToken cancellationToken)
{
await Task.CompletedTask;
switch (id._id)
{
case K_COPY:
@@ -37,17 +38,17 @@ namespace SharpCompress.Compressors.LZMA
return inStreams.Single();
case K_LZMA:
case K_LZMA2:
return new LzmaStream(info, inStreams.Single(), -1, limit);
return await LzmaStream.CreateAsync(info, inStreams.Single(), -1, limit);
case CMethodId.K_AES_ID:
return new AesDecoderStream(inStreams.Single(), info, pass, limit);
case K_BCJ:
return new BCJFilter(false, inStreams.Single());
case K_BCJ2:
return new Bcj2DecoderStream(inStreams, info, limit);
case K_B_ZIP2:
return await BZip2Stream.CreateAsync(inStreams.Single(), CompressionMode.Decompress, true, cancellationToken);
/*case K_PPMD:
return new PpmdStream(new PpmdProperties(info), inStreams.Single(), false);*/
/* case K_B_ZIP2:
return await BZip2Stream.CreateAsync(inStreams.Single(), CompressionMode.Decompress, true, cancellationToken);
case K_PPMD:
return new PpmdStream(new PpmdProperties(info), inStreams.Single(), false);*/
case K_DEFLATE:
return new DeflateStream(inStreams.Single(), CompressionMode.Decompress);
default:

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace SharpCompress.Compressors.Xz.Filters
{
@@ -52,6 +53,6 @@ namespace SharpCompress.Compressors.Xz.Filters
return filter;
}
public abstract void SetBaseStream(Stream stream);
public abstract ValueTask SetBaseStreamAsync(Stream stream);
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Threading.Tasks;
using SharpCompress.Compressors.LZMA;
namespace SharpCompress.Compressors.Xz.Filters
@@ -49,9 +50,9 @@ namespace SharpCompress.Compressors.Xz.Filters
{
}
public override void SetBaseStream(Stream stream)
public override async ValueTask SetBaseStreamAsync(Stream stream)
{
BaseStream = new LzmaStream(new[] { _dictionarySize }, stream);
BaseStream = await LzmaStream.CreateAsync(new[] { _dictionarySize }, stream);
}
public override int Read(byte[] buffer, int offset, int count)

View File

@@ -44,7 +44,7 @@ namespace SharpCompress.Compressors.Xz
if (!_streamConnected)
{
ConnectStream();
await ConnectStreamAsync();
}
if (!_endOfStream && _decomStream is not null)
@@ -95,13 +95,13 @@ namespace SharpCompress.Compressors.Xz
_crcChecked = true;
}
private void ConnectStream()
private async ValueTask ConnectStreamAsync()
{
_decomStream = BaseStream;
while (Filters.Any())
{
BlockFilter filter = Filters.Pop();
filter.SetBaseStream(_decomStream);
await filter.SetBaseStreamAsync(_decomStream);
_decomStream = filter;
}
_streamConnected = true;

View File

@@ -56,7 +56,7 @@ namespace SharpCompress.Readers
return GZipReader.Open(rewindableStream, options);
}
rewindableStream.Rewind(false);
/* rewindableStream.Rewind(false);
if (await BZip2Stream.IsBZip2Async(rewindableStream, cancellationToken))
{
rewindableStream.Rewind(false);
@@ -66,13 +66,13 @@ namespace SharpCompress.Readers
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, options, CompressionType.BZip2);
}
}
} */
rewindableStream.Rewind(false);
if (LZipStream.IsLZipFile(rewindableStream))
if (await LZipStream.IsLZipFileAsync(rewindableStream))
{
rewindableStream.Rewind(false);
LZipStream testStream = new(new NonDisposingStream(rewindableStream), CompressionMode.Decompress);
var testStream = await LZipStream.CreateAsync(new NonDisposingStream(rewindableStream), CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream, cancellationToken))
{
rewindableStream.Rewind(true);

View File

@@ -34,17 +34,17 @@ namespace SharpCompress.Readers.Tar
var stream = await base.RequestInitialStream(cancellationToken);
switch (compressionType)
{
case CompressionType.BZip2:
/* case CompressionType.BZip2:
{
return await BZip2Stream.CreateAsync(stream, CompressionMode.Decompress, false, cancellationToken);
}
} */
case CompressionType.GZip:
{
return new GZipStream(stream, CompressionMode.Decompress);
}
case CompressionType.LZip:
{
return new LZipStream(stream, CompressionMode.Decompress);
return await LZipStream.CreateAsync(stream, CompressionMode.Decompress);
}
case CompressionType.Xz:
{
@@ -87,7 +87,7 @@ namespace SharpCompress.Readers.Tar
throw new InvalidFormatException("Not a tar file.");
}
rewindableStream.Rewind(false);
/*rewindableStream.Rewind(false);
if (await BZip2Stream.IsBZip2Async(rewindableStream, cancellationToken))
{
rewindableStream.Rewind(false);
@@ -98,13 +98,13 @@ namespace SharpCompress.Readers.Tar
return new TarReader(rewindableStream, options, CompressionType.BZip2);
}
throw new InvalidFormatException("Not a tar file.");
}
} */
rewindableStream.Rewind(false);
if (LZipStream.IsLZipFile(rewindableStream))
if (await LZipStream.IsLZipFileAsync(rewindableStream))
{
rewindableStream.Rewind(false);
LZipStream testStream = new(rewindableStream, CompressionMode.Decompress);
var testStream = await LZipStream.CreateAsync(rewindableStream, CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream, cancellationToken))
{
rewindableStream.Rewind(true);

View File

@@ -127,12 +127,15 @@ namespace SharpCompress
yield return item;
}
public static void CheckNotNull(this object obj, string name)
public static T CheckNotNull<T>(this T? obj, string name)
where T : class
{
if (obj is null)
{
throw new ArgumentNullException(name);
}
return obj;
}
public static void CheckNotNullOrEmpty(this string obj, string name)

View File

@@ -24,6 +24,7 @@ namespace SharpCompress.Writers.Tar
public static async ValueTask<TarWriter> CreateAsync(Stream destination, TarWriterOptions options, CancellationToken cancellationToken = default)
{
await Task.CompletedTask;
var tw = new TarWriter(options);
tw.finalizeArchiveOnClose = options.FinalizeArchiveOnClose;
@@ -39,11 +40,11 @@ namespace SharpCompress.Writers.Tar
{
case CompressionType.None:
break;
case CompressionType.BZip2:
/* case CompressionType.BZip2:
{
destination = await BZip2Stream.CreateAsync(destination, CompressionMode.Compress, false, cancellationToken);
}
break;
break; */
case CompressionType.GZip:
{
destination = new GZipStream(destination, CompressionMode.Compress);
@@ -51,7 +52,7 @@ namespace SharpCompress.Writers.Tar
break;
case CompressionType.LZip:
{
destination = new LZipStream(destination, CompressionMode.Compress);
destination = await LZipStream.CreateAsync(destination, CompressionMode.Compress);
}
break;
default:
@@ -122,11 +123,11 @@ namespace SharpCompress.Writers.Tar
}
switch (OutputStream)
{
case BZip2Stream b:
/* case BZip2Stream b:
{
await b.FinishAsync(CancellationToken.None);
break;
}
} */
case LZipStream l:
{
l.Finish();

View File

@@ -379,6 +379,7 @@ namespace SharpCompress.Writers.Zip
private async ValueTask<Stream> GetWriteStream(Stream writeStream, CancellationToken cancellationToken)
{
await Task.CompletedTask;
counting = new CountingWritableSubStream(writeStream);
Stream output = counting;
switch (zipCompressionMethod)
@@ -391,10 +392,10 @@ namespace SharpCompress.Writers.Zip
{
return new DeflateStream(counting, CompressionMode.Compress, compressionLevel);
}
case ZipCompressionMethod.BZip2:
/*case ZipCompressionMethod.BZip2:
{
return await BZip2Stream.CreateAsync(counting, CompressionMode.Compress, false, cancellationToken);
}
} */
case ZipCompressionMethod.LZMA:
{
counting.WriteByte(9);

View File

@@ -1,4 +1,5 @@
using System.IO;
using System.Threading.Tasks;
using SharpCompress.Compressors.LZMA;
using Xunit;
@@ -7,13 +8,13 @@ namespace SharpCompress.Test.Streams
public class LzmaStreamTests
{
[Fact]
public void TestLzma2Decompress1Byte()
public async ValueTask TestLzma2Decompress1Byte()
{
byte[] properties = new byte[] { 0x01 };
byte[] compressedData = new byte[] { 0x01, 0x00, 0x00, 0x58, 0x00 };
MemoryStream lzma2Stream = new MemoryStream(compressedData);
LzmaStream decompressor = new LzmaStream(properties, lzma2Stream, 5, 1);
LzmaStream decompressor = await LzmaStream.CreateAsync(properties, lzma2Stream, 5, 1);
Assert.Equal('X', decompressor.ReadByte());
}
}