1370b324cSopenharmony_ci// LzInWindow.cs
2370b324cSopenharmony_ci
3370b324cSopenharmony_ciusing System;
4370b324cSopenharmony_ci
5370b324cSopenharmony_cinamespace SevenZip.Compression.LZ
6370b324cSopenharmony_ci{
7370b324cSopenharmony_ci	public class InWindow
8370b324cSopenharmony_ci	{
9370b324cSopenharmony_ci		public Byte[] _bufferBase = null; // pointer to buffer with data
10370b324cSopenharmony_ci		System.IO.Stream _stream;
11370b324cSopenharmony_ci		UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
12370b324cSopenharmony_ci		bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
13370b324cSopenharmony_ci
14370b324cSopenharmony_ci		UInt32 _pointerToLastSafePosition;
15370b324cSopenharmony_ci
16370b324cSopenharmony_ci		public UInt32 _bufferOffset;
17370b324cSopenharmony_ci
18370b324cSopenharmony_ci		public UInt32 _blockSize; // Size of Allocated memory block
19370b324cSopenharmony_ci		public UInt32 _pos; // offset (from _buffer) of curent byte
20370b324cSopenharmony_ci		UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
21370b324cSopenharmony_ci		UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
22370b324cSopenharmony_ci		public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
23370b324cSopenharmony_ci
24370b324cSopenharmony_ci		public void MoveBlock()
25370b324cSopenharmony_ci		{
26370b324cSopenharmony_ci			UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;
27370b324cSopenharmony_ci			// we need one additional byte, since MovePos moves on 1 byte.
28370b324cSopenharmony_ci			if (offset > 0)
29370b324cSopenharmony_ci				offset--;
30370b324cSopenharmony_ci
31370b324cSopenharmony_ci			UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;
32370b324cSopenharmony_ci
33370b324cSopenharmony_ci			// check negative offset ????
34370b324cSopenharmony_ci			for (UInt32 i = 0; i < numBytes; i++)
35370b324cSopenharmony_ci				_bufferBase[i] = _bufferBase[offset + i];
36370b324cSopenharmony_ci			_bufferOffset -= offset;
37370b324cSopenharmony_ci		}
38370b324cSopenharmony_ci
39370b324cSopenharmony_ci		public virtual void ReadBlock()
40370b324cSopenharmony_ci		{
41370b324cSopenharmony_ci			if (_streamEndWasReached)
42370b324cSopenharmony_ci				return;
43370b324cSopenharmony_ci			while (true)
44370b324cSopenharmony_ci			{
45370b324cSopenharmony_ci				int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);
46370b324cSopenharmony_ci				if (size == 0)
47370b324cSopenharmony_ci					return;
48370b324cSopenharmony_ci				int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
49370b324cSopenharmony_ci				if (numReadBytes == 0)
50370b324cSopenharmony_ci				{
51370b324cSopenharmony_ci					_posLimit = _streamPos;
52370b324cSopenharmony_ci					UInt32 pointerToPostion = _bufferOffset + _posLimit;
53370b324cSopenharmony_ci					if (pointerToPostion > _pointerToLastSafePosition)
54370b324cSopenharmony_ci						_posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);
55370b324cSopenharmony_ci
56370b324cSopenharmony_ci					_streamEndWasReached = true;
57370b324cSopenharmony_ci					return;
58370b324cSopenharmony_ci				}
59370b324cSopenharmony_ci				_streamPos += (UInt32)numReadBytes;
60370b324cSopenharmony_ci				if (_streamPos >= _pos + _keepSizeAfter)
61370b324cSopenharmony_ci					_posLimit = _streamPos - _keepSizeAfter;
62370b324cSopenharmony_ci			}
63370b324cSopenharmony_ci		}
64370b324cSopenharmony_ci
65370b324cSopenharmony_ci		void Free() { _bufferBase = null; }
66370b324cSopenharmony_ci
67370b324cSopenharmony_ci		public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
68370b324cSopenharmony_ci		{
69370b324cSopenharmony_ci			_keepSizeBefore = keepSizeBefore;
70370b324cSopenharmony_ci			_keepSizeAfter = keepSizeAfter;
71370b324cSopenharmony_ci			UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
72370b324cSopenharmony_ci			if (_bufferBase == null || _blockSize != blockSize)
73370b324cSopenharmony_ci			{
74370b324cSopenharmony_ci				Free();
75370b324cSopenharmony_ci				_blockSize = blockSize;
76370b324cSopenharmony_ci				_bufferBase = new Byte[_blockSize];
77370b324cSopenharmony_ci			}
78370b324cSopenharmony_ci			_pointerToLastSafePosition = _blockSize - keepSizeAfter;
79370b324cSopenharmony_ci		}
80370b324cSopenharmony_ci
81370b324cSopenharmony_ci		public void SetStream(System.IO.Stream stream) { _stream = stream; }
82370b324cSopenharmony_ci		public void ReleaseStream() { _stream = null; }
83370b324cSopenharmony_ci
84370b324cSopenharmony_ci		public void Init()
85370b324cSopenharmony_ci		{
86370b324cSopenharmony_ci			_bufferOffset = 0;
87370b324cSopenharmony_ci			_pos = 0;
88370b324cSopenharmony_ci			_streamPos = 0;
89370b324cSopenharmony_ci			_streamEndWasReached = false;
90370b324cSopenharmony_ci			ReadBlock();
91370b324cSopenharmony_ci		}
92370b324cSopenharmony_ci
93370b324cSopenharmony_ci		public void MovePos()
94370b324cSopenharmony_ci		{
95370b324cSopenharmony_ci			_pos++;
96370b324cSopenharmony_ci			if (_pos > _posLimit)
97370b324cSopenharmony_ci			{
98370b324cSopenharmony_ci				UInt32 pointerToPostion = _bufferOffset + _pos;
99370b324cSopenharmony_ci				if (pointerToPostion > _pointerToLastSafePosition)
100370b324cSopenharmony_ci					MoveBlock();
101370b324cSopenharmony_ci				ReadBlock();
102370b324cSopenharmony_ci			}
103370b324cSopenharmony_ci		}
104370b324cSopenharmony_ci
105370b324cSopenharmony_ci		public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
106370b324cSopenharmony_ci
107370b324cSopenharmony_ci		// index + limit have not to exceed _keepSizeAfter;
108370b324cSopenharmony_ci		public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
109370b324cSopenharmony_ci		{
110370b324cSopenharmony_ci			if (_streamEndWasReached)
111370b324cSopenharmony_ci				if ((_pos + index) + limit > _streamPos)
112370b324cSopenharmony_ci					limit = _streamPos - (UInt32)(_pos + index);
113370b324cSopenharmony_ci			distance++;
114370b324cSopenharmony_ci			// Byte *pby = _buffer + (size_t)_pos + index;
115370b324cSopenharmony_ci			UInt32 pby = _bufferOffset + _pos + (UInt32)index;
116370b324cSopenharmony_ci
117370b324cSopenharmony_ci			UInt32 i;
118370b324cSopenharmony_ci			for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);
119370b324cSopenharmony_ci			return i;
120370b324cSopenharmony_ci		}
121370b324cSopenharmony_ci
122370b324cSopenharmony_ci		public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
123370b324cSopenharmony_ci
124370b324cSopenharmony_ci		public void ReduceOffsets(Int32 subValue)
125370b324cSopenharmony_ci		{
126370b324cSopenharmony_ci			_bufferOffset += (UInt32)subValue;
127370b324cSopenharmony_ci			_posLimit -= (UInt32)subValue;
128370b324cSopenharmony_ci			_pos -= (UInt32)subValue;
129370b324cSopenharmony_ci			_streamPos -= (UInt32)subValue;
130370b324cSopenharmony_ci		}
131370b324cSopenharmony_ci	}
132370b324cSopenharmony_ci}
133