LZMA decoder allows repeated calls to Code

This commit is contained in:
2025-05-16 18:40:48 +00:00
parent d4d2c5a4cc
commit 53c4c16cd0
2 changed files with 49 additions and 30 deletions

View File

@@ -6,7 +6,8 @@ namespace SevenZip.Compression.LZ
uint _pos;
uint _windowSize = 0;
uint _streamPos;
System.IO.Stream _stream;
uint _writePos;
internal System.IO.Stream _stream;
public uint TrainSize = 0;
@@ -20,6 +21,7 @@ namespace SevenZip.Compression.LZ
_windowSize = windowSize;
_pos = 0;
_streamPos = 0;
_writePos = 0;
}
public void Init(System.IO.Stream stream, bool solid)
@@ -29,6 +31,7 @@ namespace SevenZip.Compression.LZ
if (!solid)
{
_streamPos = 0;
_writePos = 0;
_pos = 0;
TrainSize = 0;
}
@@ -40,7 +43,7 @@ namespace SevenZip.Compression.LZ
uint size = (len < _windowSize) ? (uint)len : _windowSize;
TrainSize = size;
stream.Position = len - size;
_streamPos = _pos = 0;
_streamPos = _pos = _writePos = 0;
while (size > 0)
{
uint curSize = _windowSize - _pos;
@@ -52,8 +55,9 @@ namespace SevenZip.Compression.LZ
size -= (uint)numReadBytes;
_pos += (uint)numReadBytes;
_streamPos += (uint)numReadBytes;
_writePos += (uint)numReadBytes;
if (_pos == _windowSize)
_streamPos = _pos = 0;
_streamPos = _pos = _writePos = 0;
}
return true;
}
@@ -64,15 +68,19 @@ namespace SevenZip.Compression.LZ
_stream = null;
}
public void Flush()
public void Flush(bool writeOnly = false, int avoidNewestCount = 0)
{
uint size = _pos - _streamPos;
if (size == 0)
int size = (int)(_pos - _writePos) - avoidNewestCount;
if (size <= 0)
return;
_stream.Write(_buffer, (int)_streamPos, (int)size);
if (_pos >= _windowSize)
_pos = 0;
_streamPos = _pos;
_stream.Write(_buffer, (int)_writePos, (int)size);
_writePos += (uint)size;
if (!writeOnly) {
if (_pos >= _windowSize)
_pos = 0;
_streamPos = _pos;
}
}
public void CopyBlock(uint distance, uint len)

View File

@@ -4,7 +4,7 @@ namespace SevenZip.Compression.LZMA
{
using RangeCoder;
public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
public class Decoder //: ICoder, ISetDecoderProperties // ,System.IO.Stream
{
class LenDecoder
{
@@ -225,26 +225,33 @@ namespace SevenZip.Compression.LZMA
m_PosAlignDecoder.Init();
}
Base.State state;
uint rep0, rep1, rep2, rep3;
UInt64 nowPos64;
public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress)
Int64 inSize, Int64 outSize, ICodeProgress progress, bool noInit, bool isLast)
{
Init(inStream, outStream);
Base.State state = new Base.State();
state.Init();
uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
UInt64 nowPos64 = 0;
UInt64 outSize64 = (UInt64)outSize;
if (nowPos64 < outSize64)
{
if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
throw new DataErrorException();
state.UpdateChar();
byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
m_OutWindow.PutByte(b);
nowPos64++;
if (!noInit) {
Init(inStream, outStream);
state.Init();
rep0 = 0; rep1 = 0; rep2 = 0; rep3 = 0;
nowPos64 = 0;
if (nowPos64 < outSize64)
{
if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
throw new DataErrorException();
state.UpdateChar();
byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
m_OutWindow.PutByte(b);
nowPos64++;
}
} else {
m_RangeDecoder.Stream = inStream;
m_OutWindow._stream = outStream;
}
while (nowPos64 < outSize64)
{
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
@@ -339,9 +346,13 @@ namespace SevenZip.Compression.LZMA
}
}
}
m_OutWindow.Flush();
m_OutWindow.ReleaseStream();
m_RangeDecoder.ReleaseStream();
if (isLast) {
m_OutWindow.Flush();
m_OutWindow.ReleaseStream();
m_RangeDecoder.ReleaseStream();
} else
m_OutWindow.Flush(writeOnly: true, (int)(nowPos64 - outSize64));
}
public void SetDecoderProperties(byte[] properties)