// LzOutWindow.cs | |
namespace SevenZip.Compression.LZ | |
{ | |
public class OutWindow | |
{ | |
byte[] _buffer = null; | |
uint _pos; | |
uint _windowSize = 0; | |
uint _streamPos; | |
System.IO.Stream _stream; | |
public uint TrainSize = 0; | |
public void Create(uint windowSize) | |
{ | |
if (_windowSize != windowSize) | |
{ | |
// System.GC.Collect(); | |
_buffer = new byte[windowSize]; | |
} | |
_windowSize = windowSize; | |
_pos = 0; | |
_streamPos = 0; | |
} | |
public void Init(System.IO.Stream stream, bool solid) | |
{ | |
ReleaseStream(); | |
_stream = stream; | |
if (!solid) | |
{ | |
_streamPos = 0; | |
_pos = 0; | |
TrainSize = 0; | |
} | |
} | |
public bool Train(System.IO.Stream stream) | |
{ | |
long len = stream.Length; | |
uint size = (len < _windowSize) ? (uint)len : _windowSize; | |
TrainSize = size; | |
stream.Position = len - size; | |
_streamPos = _pos = 0; | |
while (size > 0) | |
{ | |
uint curSize = _windowSize - _pos; | |
if (size < curSize) | |
curSize = size; | |
int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); | |
if (numReadBytes == 0) | |
return false; | |
size -= (uint)numReadBytes; | |
_pos += (uint)numReadBytes; | |
_streamPos += (uint)numReadBytes; | |
if (_pos == _windowSize) | |
_streamPos = _pos = 0; | |
} | |
return true; | |
} | |
public void ReleaseStream() | |
{ | |
Flush(); | |
_stream = null; | |
} | |
public void Flush() | |
{ | |
uint size = _pos - _streamPos; | |
if (size == 0) | |
return; | |
_stream.Write(_buffer, (int)_streamPos, (int)size); | |
if (_pos >= _windowSize) | |
_pos = 0; | |
_streamPos = _pos; | |
} | |
public void CopyBlock(uint distance, uint len) | |
{ | |
uint pos = _pos - distance - 1; | |
if (pos >= _windowSize) | |
pos += _windowSize; | |
for (; len > 0; len--) | |
{ | |
if (pos >= _windowSize) | |
pos = 0; | |
_buffer[_pos++] = _buffer[pos++]; | |
if (_pos >= _windowSize) | |
Flush(); | |
} | |
} | |
public void PutByte(byte b) | |
{ | |
_buffer[_pos++] = b; | |
if (_pos >= _windowSize) | |
Flush(); | |
} | |
public byte GetByte(uint distance) | |
{ | |
uint pos = _pos - distance - 1; | |
if (pos >= _windowSize) | |
pos += _windowSize; | |
return _buffer[pos]; | |
} | |
} | |
} |