Files
SabreTools/SabreTools.Library/External/Compress/SevenZip/Compress/LZ/LzOutWindow.cs
Matt Nadareski 916d2a3b51 Internal Fixes, etc. (#20)
* Start removing mixed usages

* Check for directories before opening

* Fix writing

* Kinda fix rebuild

* One more try

* Better internal handling

* Slighty fix a couple more things

* Update RVWorld Compress code to db7d750bba

* Fix build

Co-authored-by: Matt Nadareski <mnadareski@mparticle.com>
2020-04-03 13:19:21 -07:00

186 lines
4.7 KiB
C#

using Compress.SevenZip.Common;
namespace Compress.SevenZip.Compress.LZ
{
internal class OutWindow
{
byte[] _buffer = null;
int _windowSize = 0;
int _pos;
int _streamPos;
int _pendingLen;
int _pendingDist;
System.IO.Stream _stream;
public long Total;
public long Limit;
public void Create(int windowSize)
{
if (_windowSize != windowSize)
_buffer = new byte[windowSize];
else
_buffer[windowSize - 1] = 0;
_windowSize = windowSize;
_pos = 0;
_streamPos = 0;
_pendingLen = 0;
Total = 0;
Limit = 0;
}
public void Reset()
{
Create(_windowSize);
}
public void Init(System.IO.Stream stream)
{
ReleaseStream();
_stream = stream;
}
public void Train(System.IO.Stream stream)
{
long len = stream.Length;
int size = (len < _windowSize) ? (int)len : _windowSize;
stream.Position = len - size;
Total = 0;
Limit = size;
_pos = _windowSize - size;
CopyStream(stream, size);
if (_pos == _windowSize)
_pos = 0;
_streamPos = _pos;
}
public void ReleaseStream()
{
Flush();
_stream = null;
}
public void Flush()
{
if (_stream == null)
return;
int size = _pos - _streamPos;
if (size == 0)
return;
_stream.Write(_buffer, _streamPos, size);
if (_pos >= _windowSize)
_pos = 0;
_streamPos = _pos;
}
public void CopyBlock(int distance, int len)
{
int size = len;
int pos = _pos - distance - 1;
if (pos < 0)
pos += _windowSize;
for (; size > 0 && _pos < _windowSize && Total < Limit; size--)
{
if (pos >= _windowSize)
pos = 0;
_buffer[_pos++] = _buffer[pos++];
Total++;
if (_pos >= _windowSize)
Flush();
}
_pendingLen = size;
_pendingDist = distance;
}
public void PutByte(byte b)
{
_buffer[_pos++] = b;
Total++;
if (_pos >= _windowSize)
Flush();
}
public byte GetByte(int distance)
{
int pos = _pos - distance - 1;
if (pos < 0)
pos += _windowSize;
return _buffer[pos];
}
public int CopyStream(System.IO.Stream stream, int len)
{
int size = len;
while (size > 0 && _pos < _windowSize && Total < Limit)
{
int curSize = _windowSize - _pos;
if (curSize > Limit - Total)
curSize = (int)(Limit - Total);
if (curSize > size)
curSize = size;
int numReadBytes = stream.Read(_buffer, _pos, curSize);
if (numReadBytes == 0)
throw new DataErrorException();
size -= numReadBytes;
_pos += numReadBytes;
Total += numReadBytes;
if (_pos >= _windowSize)
Flush();
}
return len - size;
}
public void SetLimit(long size)
{
Limit = Total + size;
}
public bool HasSpace
{
get
{
return _pos < _windowSize && Total < Limit;
}
}
public bool HasPending
{
get
{
return _pendingLen > 0;
}
}
public int Read(byte[] buffer, int offset, int count)
{
if (_streamPos >= _pos)
return 0;
int size = _pos - _streamPos;
if (size > count)
size = count;
System.Buffer.BlockCopy(_buffer, _streamPos, buffer, offset, size);
_streamPos += size;
if (_streamPos >= _windowSize)
{
_pos = 0;
_streamPos = 0;
}
return size;
}
public void CopyPending()
{
if (_pendingLen > 0)
CopyBlock(_pendingDist, _pendingLen);
}
public int AvailableBytes
{
get
{
return _pos - _streamPos;
}
}
}
}