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