mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 05:25:00 +00:00
LZMA create
This commit is contained in:
@@ -200,7 +200,7 @@ internal abstract partial class ZipFilePart
|
||||
await stream
|
||||
.ReadFullyAsync(props, 0, propsSize, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
return new LzmaStream(
|
||||
return LzmaStream.Create(
|
||||
props,
|
||||
stream,
|
||||
Header.CompressedSize > 0 ? Header.CompressedSize - 4 - props.Length : -1,
|
||||
|
||||
@@ -134,7 +134,7 @@ internal abstract partial class ZipFilePart : FilePart
|
||||
reader.ReadUInt16(); //LZMA version
|
||||
var props = new byte[reader.ReadUInt16()];
|
||||
reader.Read(props, 0, props.Length);
|
||||
return new LzmaStream(
|
||||
return LzmaStream.Create(
|
||||
props,
|
||||
stream,
|
||||
Header.CompressedSize > 0 ? Header.CompressedSize - 4 - props.Length : -1,
|
||||
|
||||
@@ -62,7 +62,7 @@ public sealed partial class LZipStream : Stream, IStreamStack
|
||||
throw new InvalidFormatException("Not an LZip stream");
|
||||
}
|
||||
var properties = GetProperties(dSize);
|
||||
_stream = new LzmaStream(properties, stream, leaveOpen: leaveOpen);
|
||||
_stream = LzmaStream.Create(properties, stream, leaveOpen: leaveOpen);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -72,9 +72,10 @@ public sealed partial class LZipStream : Stream, IStreamStack
|
||||
|
||||
_countingWritableSubStream = new SharpCompressStream(stream, leaveOpen: true);
|
||||
_stream = new Crc32Stream(
|
||||
new LzmaStream(
|
||||
LzmaStream.Create(
|
||||
new LzmaEncoderProperties(true, dSize),
|
||||
false,
|
||||
null,
|
||||
_countingWritableSubStream
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
@@ -17,7 +16,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
#endif
|
||||
int IStreamStack.DefaultBufferSize { get; set; }
|
||||
|
||||
Stream IStreamStack.BaseStream() => _inputStream;
|
||||
Stream IStreamStack.BaseStream() => _inputStream!;
|
||||
|
||||
int IStreamStack.BufferSize
|
||||
{
|
||||
@@ -32,7 +31,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
|
||||
void IStreamStack.SetPosition(long position) { }
|
||||
|
||||
private readonly Stream _inputStream;
|
||||
private readonly Stream? _inputStream;
|
||||
private readonly long _inputSize;
|
||||
private readonly long _outputSize;
|
||||
private readonly bool _leaveOpen;
|
||||
@@ -40,7 +39,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
private readonly int _dictionarySize;
|
||||
private readonly OutWindow _outWindow = new();
|
||||
private readonly RangeCoder.Decoder _rangeDecoder = new();
|
||||
private Decoder _decoder;
|
||||
private Decoder? _decoder;
|
||||
|
||||
private long _position;
|
||||
private bool _endReached;
|
||||
@@ -54,38 +53,14 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
private bool _needDictReset = true;
|
||||
private bool _needProps = true;
|
||||
|
||||
private readonly Encoder _encoder;
|
||||
private readonly Encoder? _encoder;
|
||||
private bool _isDisposed;
|
||||
|
||||
public LzmaStream(byte[] properties, Stream inputStream, bool leaveOpen = false)
|
||||
: this(properties, inputStream, -1, -1, null, properties.Length < 5, leaveOpen) { }
|
||||
|
||||
public LzmaStream(byte[] properties, Stream inputStream, long inputSize, bool leaveOpen = false)
|
||||
: this(properties, inputStream, inputSize, -1, null, properties.Length < 5, leaveOpen) { }
|
||||
|
||||
public LzmaStream(
|
||||
private LzmaStream(
|
||||
byte[] properties,
|
||||
Stream inputStream,
|
||||
long inputSize,
|
||||
long outputSize,
|
||||
bool leaveOpen = false
|
||||
)
|
||||
: this(
|
||||
properties,
|
||||
inputStream,
|
||||
inputSize,
|
||||
outputSize,
|
||||
null,
|
||||
properties.Length < 5,
|
||||
leaveOpen
|
||||
) { }
|
||||
|
||||
public LzmaStream(
|
||||
byte[] properties,
|
||||
Stream inputStream,
|
||||
long inputSize,
|
||||
long outputSize,
|
||||
Stream presetDictionary,
|
||||
bool isLzma2,
|
||||
bool leaveOpen = false
|
||||
)
|
||||
@@ -95,21 +70,10 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
_outputSize = outputSize;
|
||||
_isLzma2 = isLzma2;
|
||||
_leaveOpen = leaveOpen;
|
||||
|
||||
#if DEBUG_STREAMS
|
||||
this.DebugConstruct(typeof(LzmaStream));
|
||||
#endif
|
||||
|
||||
if (!isLzma2)
|
||||
{
|
||||
_dictionarySize = BinaryPrimitives.ReadInt32LittleEndian(properties.AsSpan(1));
|
||||
_outWindow.Create(_dictionarySize);
|
||||
if (presetDictionary != null)
|
||||
{
|
||||
_outWindow.Train(presetDictionary);
|
||||
}
|
||||
|
||||
_rangeDecoder.Init(inputStream);
|
||||
|
||||
_decoder = new Decoder();
|
||||
_decoder.SetDecoderProperties(properties);
|
||||
@@ -124,25 +88,72 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
_dictionarySize <<= (properties[0] >> 1) + 11;
|
||||
|
||||
_outWindow.Create(_dictionarySize);
|
||||
if (presetDictionary != null)
|
||||
{
|
||||
_outWindow.Train(presetDictionary);
|
||||
_needDictReset = false;
|
||||
}
|
||||
|
||||
Properties = new byte[1];
|
||||
_availableBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public LzmaStream(LzmaEncoderProperties properties, bool isLzma2, Stream outputStream)
|
||||
: this(properties, isLzma2, null, outputStream) { }
|
||||
|
||||
public LzmaStream(
|
||||
|
||||
public static LzmaStream Create(byte[] properties, Stream inputStream, bool leaveOpen = false)
|
||||
=> Create(properties, inputStream, -1, -1, null, properties.Length < 5, leaveOpen);
|
||||
|
||||
|
||||
public static LzmaStream Create(byte[] properties, Stream inputStream, long inputSize, bool leaveOpen = false)
|
||||
=> Create(properties, inputStream, inputSize, -1, null, properties.Length < 5, leaveOpen);
|
||||
|
||||
public static LzmaStream Create(
|
||||
byte[] properties,
|
||||
Stream inputStream,
|
||||
long inputSize,
|
||||
long outputSize,
|
||||
bool leaveOpen = false
|
||||
)
|
||||
=> Create(
|
||||
properties,
|
||||
inputStream,
|
||||
inputSize,
|
||||
outputSize,
|
||||
null,
|
||||
properties.Length < 5,
|
||||
leaveOpen
|
||||
);
|
||||
|
||||
public static LzmaStream Create(
|
||||
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)
|
||||
{
|
||||
lzma._outWindow.Train(presetDictionary);
|
||||
}
|
||||
|
||||
lzma._rangeDecoder.Init(inputStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (presetDictionary != null)
|
||||
{
|
||||
lzma. _outWindow.Train(presetDictionary);
|
||||
lzma. _needDictReset = false;
|
||||
}
|
||||
}
|
||||
return lzma;
|
||||
}
|
||||
private LzmaStream(
|
||||
LzmaEncoderProperties properties,
|
||||
bool isLzma2,
|
||||
Stream presetDictionary,
|
||||
Stream outputStream
|
||||
Stream? presetDictionary
|
||||
)
|
||||
{
|
||||
_isLzma2 = isLzma2;
|
||||
@@ -160,17 +171,32 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
_encoder.WriteCoderProperties(prop);
|
||||
Properties = prop;
|
||||
|
||||
_encoder.SetStreams(null, outputStream, -1, -1);
|
||||
|
||||
#if DEBUG_STREAMS
|
||||
this.DebugConstruct(typeof(LzmaStream));
|
||||
#endif
|
||||
|
||||
if (presetDictionary != null)
|
||||
{
|
||||
_encoder.Train(presetDictionary);
|
||||
}
|
||||
}
|
||||
public static LzmaStream Create(LzmaEncoderProperties properties, bool isLzma2, Stream outputStream)
|
||||
=> Create(properties, isLzma2, null, outputStream);
|
||||
|
||||
public static LzmaStream Create(
|
||||
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;
|
||||
}
|
||||
|
||||
public override bool CanRead => _encoder == null;
|
||||
|
||||
@@ -250,7 +276,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
{
|
||||
_inputPosition += _outWindow.CopyStream(_inputStream, toProcess);
|
||||
}
|
||||
else if (_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder) && _outputSize < 0)
|
||||
else if (_decoder!.Code(_dictionarySize, _outWindow, _rangeDecoder) && _outputSize < 0)
|
||||
{
|
||||
_availableBytes = _outWindow.AvailableBytes;
|
||||
}
|
||||
@@ -271,7 +297,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
{
|
||||
// Stream might have End Of Stream marker
|
||||
_outWindow.SetLimit(toProcess + 1);
|
||||
if (!_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder))
|
||||
if (!_decoder!.Code(_dictionarySize, _outWindow, _rangeDecoder))
|
||||
{
|
||||
_rangeDecoder.ReleaseStream();
|
||||
throw new DataErrorException();
|
||||
@@ -341,7 +367,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
{
|
||||
_inputPosition += _outWindow.CopyStream(_inputStream, 1);
|
||||
}
|
||||
else if (_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder) && _outputSize < 0)
|
||||
else if (_decoder!.Code(_dictionarySize, _outWindow, _rangeDecoder) && _outputSize < 0)
|
||||
{
|
||||
_availableBytes = _outWindow.AvailableBytes;
|
||||
}
|
||||
@@ -360,7 +386,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
{
|
||||
// Stream might have End Of Stream marker
|
||||
_outWindow.SetLimit(2);
|
||||
if (!_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder))
|
||||
if (!_decoder!.Code(_dictionarySize, _outWindow, _rangeDecoder))
|
||||
{
|
||||
_rangeDecoder.ReleaseStream();
|
||||
throw new DataErrorException();
|
||||
@@ -381,7 +407,7 @@ public partial class LzmaStream : Stream, IStreamStack
|
||||
|
||||
private void DecodeChunkHeader()
|
||||
{
|
||||
var control = _inputStream.ReadByte();
|
||||
var control = _inputStream!.ReadByte();
|
||||
_inputPosition++;
|
||||
|
||||
if (control == 0x00)
|
||||
|
||||
@@ -51,7 +51,7 @@ internal static class DecoderRegistry
|
||||
return new DeltaFilter(false, inStreams.Single(), info);
|
||||
case K_LZMA:
|
||||
case K_LZMA2:
|
||||
return new LzmaStream(info, inStreams.Single(), -1, limit);
|
||||
return LzmaStream.Create(info, inStreams.Single(), -1, limit);
|
||||
case CMethodId.K_AES_ID:
|
||||
return new AesDecoderStream(inStreams.Single(), info, pass, limit);
|
||||
case K_BCJ:
|
||||
|
||||
@@ -50,7 +50,7 @@ public class Lzma2Filter : BlockFilter
|
||||
public override void ValidateFilter() { }
|
||||
|
||||
public override void SetBaseStream(Stream stream) =>
|
||||
BaseStream = new LzmaStream(new[] { _dictionarySize }, stream);
|
||||
BaseStream = LzmaStream.Create(new[] { _dictionarySize }, stream);
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count) =>
|
||||
BaseStream.Read(buffer, offset, count);
|
||||
|
||||
@@ -443,7 +443,7 @@ public partial class ZipWriter : AbstractWriter
|
||||
counting.WriteByte(5);
|
||||
counting.WriteByte(0);
|
||||
|
||||
var lzmaStream = new LzmaStream(
|
||||
var lzmaStream = LzmaStream.Create(
|
||||
new LzmaEncoderProperties(!originalStream.CanSeek),
|
||||
false,
|
||||
counting
|
||||
|
||||
@@ -147,7 +147,7 @@ public class DisposalTests
|
||||
// 5 bytes: 1 byte properties + 4 bytes dictionary size (little endian)
|
||||
// Dictionary size = 1024 (0x400) -> 00 04 00 00
|
||||
var lzmaProps = new byte[] { 0, 0, 4, 0, 0 };
|
||||
VerifyAlwaysDispose(stream => new LzmaStream(lzmaProps, stream));
|
||||
VerifyAlwaysDispose(stream => LzmaStream.Create(lzmaProps, stream));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -16,7 +16,7 @@ public class LzmaStreamAsyncTests
|
||||
var compressedData = new byte[] { 0x01, 0x00, 0x00, 0x58, 0x00 };
|
||||
var lzma2Stream = new MemoryStream(compressedData);
|
||||
|
||||
var decompressor = new LzmaStream(properties, lzma2Stream, 5, 1);
|
||||
var decompressor = LzmaStream.Create(properties, lzma2Stream, 5, 1);
|
||||
var buffer = new byte[1];
|
||||
var bytesRead = await decompressor.ReadAsync(buffer, 0, 1).ConfigureAwait(false);
|
||||
Assert.Equal(1, bytesRead);
|
||||
@@ -540,7 +540,7 @@ public class LzmaStreamAsyncTests
|
||||
{
|
||||
using var inputStream = new MemoryStream(LzmaResultData);
|
||||
using MemoryStream outputStream = new();
|
||||
using var lzmaStream = new LzmaStream(LzmaEncoderProperties.Default, false, outputStream);
|
||||
using var lzmaStream = LzmaStream.Create(LzmaEncoderProperties.Default, false, outputStream);
|
||||
await inputStream.CopyToAsync(lzmaStream).ConfigureAwait(false);
|
||||
lzmaStream.Close();
|
||||
Assert.NotEqual(0, outputStream.Length);
|
||||
@@ -551,7 +551,7 @@ public class LzmaStreamAsyncTests
|
||||
{
|
||||
var input = new MemoryStream(LzmaResultData);
|
||||
var compressed = new MemoryStream();
|
||||
var lzmaEncodingStream = new LzmaStream(LzmaEncoderProperties.Default, false, compressed);
|
||||
var lzmaEncodingStream = LzmaStream.Create(LzmaEncoderProperties.Default, false, compressed);
|
||||
await input.CopyToAsync(lzmaEncodingStream).ConfigureAwait(false);
|
||||
lzmaEncodingStream.Close();
|
||||
compressed.Position = 0;
|
||||
@@ -577,7 +577,7 @@ public class LzmaStreamAsyncTests
|
||||
long decompressedSize
|
||||
)
|
||||
{
|
||||
var lzmaStream = new LzmaStream(
|
||||
var lzmaStream = LzmaStream.Create(
|
||||
properties,
|
||||
compressedStream,
|
||||
compressedSize,
|
||||
|
||||
@@ -15,7 +15,7 @@ public class LzmaStreamTests
|
||||
var compressedData = new byte[] { 0x01, 0x00, 0x00, 0x58, 0x00 };
|
||||
var lzma2Stream = new MemoryStream(compressedData);
|
||||
|
||||
var decompressor = new LzmaStream(properties, lzma2Stream, 5, 1);
|
||||
var decompressor = LzmaStream.Create(properties, lzma2Stream, 5, 1);
|
||||
Assert.Equal('X', decompressor.ReadByte());
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ public class LzmaStreamTests
|
||||
{
|
||||
using var inputStream = new MemoryStream(LzmaResultData);
|
||||
using MemoryStream outputStream = new();
|
||||
using var lzmaStream = new LzmaStream(LzmaEncoderProperties.Default, false, outputStream);
|
||||
using var lzmaStream = LzmaStream.Create(LzmaEncoderProperties.Default, false, outputStream);
|
||||
inputStream.CopyTo(lzmaStream);
|
||||
lzmaStream.Close();
|
||||
Assert.NotEqual(0, outputStream.Length);
|
||||
@@ -547,7 +547,7 @@ public class LzmaStreamTests
|
||||
{
|
||||
var input = new MemoryStream(LzmaResultData);
|
||||
var compressed = new MemoryStream();
|
||||
var lzmaEncodingStream = new LzmaStream(LzmaEncoderProperties.Default, false, compressed);
|
||||
var lzmaEncodingStream = LzmaStream.Create(LzmaEncoderProperties.Default, false, compressed);
|
||||
input.CopyTo(lzmaEncodingStream);
|
||||
lzmaEncodingStream.Close();
|
||||
compressed.Position = 0;
|
||||
@@ -572,7 +572,7 @@ public class LzmaStreamTests
|
||||
long decompressedSize
|
||||
)
|
||||
{
|
||||
var lzmaStream = new LzmaStream(
|
||||
var lzmaStream = LzmaStream.Create(
|
||||
properties,
|
||||
compressedStream,
|
||||
compressedSize,
|
||||
|
||||
Reference in New Issue
Block a user