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

View File

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