1 // LzOutWindow.cs 2 3 namespace SevenZip.Compression.LZ 4 { 5 public class OutWindow 6 { 7 byte[] _buffer = null; 8 uint _pos; 9 uint _windowSize = 0; 10 uint _streamPos; 11 System.IO.Stream _stream; 12 13 public uint TrainSize = 0; 14 Create(uint windowSize)15 public void Create(uint windowSize) 16 { 17 if (_windowSize != windowSize) 18 { 19 // System.GC.Collect(); 20 _buffer = new byte[windowSize]; 21 } 22 _windowSize = windowSize; 23 _pos = 0; 24 _streamPos = 0; 25 } 26 Init(System.IO.Stream stream, bool solid)27 public void Init(System.IO.Stream stream, bool solid) 28 { 29 ReleaseStream(); 30 _stream = stream; 31 if (!solid) 32 { 33 _streamPos = 0; 34 _pos = 0; 35 TrainSize = 0; 36 } 37 } 38 Train(System.IO.Stream stream)39 public bool Train(System.IO.Stream stream) 40 { 41 long len = stream.Length; 42 uint size = (len < _windowSize) ? (uint)len : _windowSize; 43 TrainSize = size; 44 stream.Position = len - size; 45 _streamPos = _pos = 0; 46 while (size > 0) 47 { 48 uint curSize = _windowSize - _pos; 49 if (size < curSize) 50 curSize = size; 51 int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); 52 if (numReadBytes == 0) 53 return false; 54 size -= (uint)numReadBytes; 55 _pos += (uint)numReadBytes; 56 _streamPos += (uint)numReadBytes; 57 if (_pos == _windowSize) 58 _streamPos = _pos = 0; 59 } 60 return true; 61 } 62 ReleaseStream()63 public void ReleaseStream() 64 { 65 Flush(); 66 _stream = null; 67 } 68 Flush()69 public void Flush() 70 { 71 uint size = _pos - _streamPos; 72 if (size == 0) 73 return; 74 _stream.Write(_buffer, (int)_streamPos, (int)size); 75 if (_pos >= _windowSize) 76 _pos = 0; 77 _streamPos = _pos; 78 } 79 CopyBlock(uint distance, uint len)80 public void CopyBlock(uint distance, uint len) 81 { 82 uint pos = _pos - distance - 1; 83 if (pos >= _windowSize) 84 pos += _windowSize; 85 for (; len > 0; len--) 86 { 87 if (pos >= _windowSize) 88 pos = 0; 89 _buffer[_pos++] = _buffer[pos++]; 90 if (_pos >= _windowSize) 91 Flush(); 92 } 93 } 94 PutByte(byte b)95 public void PutByte(byte b) 96 { 97 _buffer[_pos++] = b; 98 if (_pos >= _windowSize) 99 Flush(); 100 } 101 GetByte(uint distance)102 public byte GetByte(uint distance) 103 { 104 uint pos = _pos - distance - 1; 105 if (pos >= _windowSize) 106 pos += _windowSize; 107 return _buffer[pos]; 108 } 109 } 110 } 111