123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- using System;
- using System.IO;
- namespace SharpCompress.Compressors.LZMA.LZ
- {
- internal class OutWindow
- {
- private byte[] _buffer;
- private int _windowSize;
- private int _pos;
- private int _streamPos;
- private int _pendingLen;
- private int _pendingDist;
- private 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(Stream stream)
- {
- ReleaseStream();
- _stream = stream;
- }
- public void Train(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(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 => _pos < _windowSize && _total < _limit;
- public bool HasPending => _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;
- }
- 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 => _pos - _streamPos;
- }
- }
|