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