1// LZ.InWindow
2
3package SevenZip.Compression.LZ;
4
5import java.io.IOException;
6
7public class InWindow
8{
9	public byte[] _bufferBase; // pointer to buffer with data
10	java.io.InputStream _stream;
11	int _posLimit;  // offset (from _buffer) of first byte when new block reading must be done
12	boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream
13
14	int _pointerToLastSafePosition;
15
16	public int _bufferOffset;
17
18	public int _blockSize;  // Size of Allocated memory block
19	public int _pos;             // offset (from _buffer) of curent byte
20	int _keepSizeBefore;  // how many BYTEs must be kept in buffer before _pos
21	int _keepSizeAfter;   // how many BYTEs must be kept buffer after _pos
22	public int _streamPos;   // offset (from _buffer) of first not read byte from Stream
23
24	public void MoveBlock()
25	{
26		int offset = _bufferOffset + _pos - _keepSizeBefore;
27		// we need one additional byte, since MovePos moves on 1 byte.
28		if (offset > 0)
29			offset--;
30
31		int numBytes = _bufferOffset + _streamPos - offset;
32
33		// check negative offset ????
34		for (int i = 0; i < numBytes; i++)
35			_bufferBase[i] = _bufferBase[offset + i];
36		_bufferOffset -= offset;
37	}
38
39	public void ReadBlock() throws IOException
40	{
41		if (_streamEndWasReached)
42			return;
43		while (true)
44		{
45			int size = (0 - _bufferOffset) + _blockSize - _streamPos;
46			if (size == 0)
47				return;
48			int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size);
49			if (numReadBytes == -1)
50			{
51				_posLimit = _streamPos;
52				int pointerToPostion = _bufferOffset + _posLimit;
53				if (pointerToPostion > _pointerToLastSafePosition)
54					_posLimit = _pointerToLastSafePosition - _bufferOffset;
55
56				_streamEndWasReached = true;
57				return;
58			}
59			_streamPos += numReadBytes;
60			if (_streamPos >= _pos + _keepSizeAfter)
61				_posLimit = _streamPos - _keepSizeAfter;
62		}
63	}
64
65	void Free() { _bufferBase = null; }
66
67	public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv)
68	{
69		_keepSizeBefore = keepSizeBefore;
70		_keepSizeAfter = keepSizeAfter;
71		int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
72		if (_bufferBase == null || _blockSize != blockSize)
73		{
74			Free();
75			_blockSize = blockSize;
76			_bufferBase = new byte[_blockSize];
77		}
78		_pointerToLastSafePosition = _blockSize - keepSizeAfter;
79	}
80
81	public void SetStream(java.io.InputStream stream) { _stream = stream; 	}
82	public void ReleaseStream() { _stream = null; }
83
84	public void Init() throws IOException
85	{
86		_bufferOffset = 0;
87		_pos = 0;
88		_streamPos = 0;
89		_streamEndWasReached = false;
90		ReadBlock();
91	}
92
93	public void MovePos() throws IOException
94	{
95		_pos++;
96		if (_pos > _posLimit)
97		{
98			int pointerToPostion = _bufferOffset + _pos;
99			if (pointerToPostion > _pointerToLastSafePosition)
100				MoveBlock();
101			ReadBlock();
102		}
103	}
104
105	public byte GetIndexByte(int index)	{ return _bufferBase[_bufferOffset + _pos + index]; }
106
107	// index + limit have not to exceed _keepSizeAfter;
108	public int GetMatchLen(int index, int distance, int limit)
109	{
110		if (_streamEndWasReached)
111			if ((_pos + index) + limit > _streamPos)
112				limit = _streamPos - (_pos + index);
113		distance++;
114		// Byte *pby = _buffer + (size_t)_pos + index;
115		int pby = _bufferOffset + _pos + index;
116
117		int i;
118		for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);
119		return i;
120	}
121
122	public int GetNumAvailableBytes()	{ return _streamPos - _pos; }
123
124	public void ReduceOffsets(int subValue)
125	{
126		_bufferOffset += subValue;
127		_posLimit -= subValue;
128		_pos -= subValue;
129		_streamPos -= subValue;
130	}
131}
132