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