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