1 package SevenZip
.Compression
.LZ
;
2 import java
.io
.IOException
;
4 public class BinTree
extends InWindow
19 boolean HASH_ARRAY
= true;
20 boolean HASH_BIG
= false;
22 static final int kHash3Size
= 1 << 18;
24 static final int kBT2HashSize
= 1 << 16;
25 static final int kBT4Hash2Size
= 1 << 10;
26 static final int kBT4Hash4Size
= 1 << 20;
27 static final int kBT4bHash4Size
= 1 << 23;
28 static final int kBT2NumHashDirectBytes
= 2;
29 static final int kBT4NumHashDirectBytes
= 0;
31 int kHash2Size
= kBT4Hash2Size
;
32 int kNumHashDirectBytes
= kBT4NumHashDirectBytes
;
33 int kNumHashBytes
= 4;
34 int kHashSize
= kBT4Hash4Size
;
36 private static final int[] CrcTable
= new int[256];
40 for (int i
= 0; i
< 256; i
++)
43 for (int j
= 0; j
< 8; j
++)
45 r
= (r
>>> 1) ^
0xEDB88320;
52 public void SetType(int numHashBytes
, boolean big
)
54 HASH_ARRAY
= numHashBytes
> 2;
58 kHash2Size
= kBT4Hash2Size
;
59 kNumHashDirectBytes
= kBT4NumHashDirectBytes
;
61 kHashSize
= (HASH_BIG ? kBT4bHash4Size
: kBT4Hash4Size
);
65 kNumHashDirectBytes
= kBT2NumHashDirectBytes
;
67 kHashSize
= kBT2HashSize
;
71 static final int kEmptyHashValue
= 0;
73 static final int kMaxValForNormalize
= ((int)1 << 30) - 1;
76 public void Init() throws IOException
80 for (i
= 0; i
< kHashSize
; i
++)
81 _hash
[i
] = kEmptyHashValue
;
84 for (i
= 0; i
< kHash2Size
; i
++)
85 _hash2
[i
] = kEmptyHashValue
;
86 for (i
= 0; i
< kHash3Size
; i
++)
87 _hash3
[i
] = kEmptyHashValue
;
93 public void MovePos() throws IOException
95 if (++_cyclicBufferPos
>= _cyclicBufferSize
)
98 if (_pos
== kMaxValForNormalize
)
102 public boolean Create(int historySize
, int keepAddBufferBefore
,
103 int matchMaxLen
, int keepAddBufferAfter
)
105 int windowReservSize
= (historySize
+ keepAddBufferBefore
+
106 matchMaxLen
+ keepAddBufferAfter
) / 2 + 256;
113 super.Create(historySize
+ keepAddBufferBefore
, matchMaxLen
+ keepAddBufferAfter
, windowReservSize
);
115 if (_blockSize
+ 256 > kMaxValForNormalize
)
118 _historySize
= historySize
;
119 _matchMaxLen
= matchMaxLen
;
121 _cyclicBufferSize
= historySize
+ 1;
122 _son
= new int[_cyclicBufferSize
* 2];
124 _hash
= new int[kHashSize
];
127 _hash2
= new int[kHash2Size
];
128 _hash3
= new int[kHash3Size
];
133 public int GetLongestMatch(int[] distances
)
136 if (_pos
+ _matchMaxLen
<= _streamPos
)
137 lenLimit
= _matchMaxLen
;
140 lenLimit
= _streamPos
- _pos
;
141 if (lenLimit
< kNumHashBytes
)
145 int matchMinPos
= (_pos
> _historySize
) ?
(_pos
- _historySize
) : 1;
147 int cur
= _bufferOffset
+ _pos
;
149 int matchHashLenMax
= 0;
151 int hashValue
, hash2Value
= 0, hash3Value
= 0;
155 int temp
= CrcTable
[_bufferBase
[cur
] & 0xFF] ^
(_bufferBase
[cur
+ 1] & 0xFF);
156 hash2Value
= temp
& (kHash2Size
- 1);
157 temp ^
= ((int)(_bufferBase
[cur
+ 2] & 0xFF) << 8);
158 hash3Value
= temp
& (kHash3Size
- 1);
159 hashValue
= (temp ^
(CrcTable
[_bufferBase
[cur
+ 3] & 0xFF] << 5)) & (kHashSize
- 1);
162 hashValue
= ((_bufferBase
[cur
] & 0xFF) ^
((int)(_bufferBase
[cur
+ 1] & 0xFF) << 8)) & (kHashSize
- 1);
164 int curMatch
= _hash
[hashValue
];
165 int curMatch2
= 0, curMatch3
= 0;
166 int len2Distance
= 0;
167 int len3Distance
= 0;
168 boolean matchLen2Exist
= false;
169 boolean matchLen3Exist
= false;
172 curMatch2
= _hash2
[hash2Value
];
173 curMatch3
= _hash3
[hash3Value
];
174 _hash2
[hash2Value
] = _pos
;
175 if (curMatch2
>= matchMinPos
)
177 if (_bufferBase
[_bufferOffset
+ curMatch2
] == _bufferBase
[cur
])
179 len2Distance
= _pos
- curMatch2
- 1;
181 matchLen2Exist
= true;
185 _hash3
[hash3Value
] = _pos
;
186 if (curMatch3
>= matchMinPos
)
188 if (_bufferBase
[_bufferOffset
+ curMatch3
] == _bufferBase
[cur
])
190 len3Distance
= _pos
- curMatch3
- 1;
192 matchLen3Exist
= true;
195 if (len3Distance
< len2Distance
)
196 len2Distance
= len3Distance
;
200 len2Distance
= len3Distance
;
201 matchLen2Exist
= true;
208 _hash
[hashValue
] = _pos
;
210 if (curMatch
< matchMinPos
)
212 _son
[(_cyclicBufferPos
<< 1)] = kEmptyHashValue
;
213 _son
[(_cyclicBufferPos
<< 1) + 1] = kEmptyHashValue
;
217 distances
[2] = len2Distance
;
218 distances
[3] = len3Distance
;
220 return matchHashLenMax
;
222 int ptrLeft
= (_cyclicBufferPos
<< 1) + 1;
223 int ptrRight
= (_cyclicBufferPos
<< 1);
225 int maxLen
, minLeft
, minRight
;
226 maxLen
= minLeft
= minRight
= kNumHashDirectBytes
;
228 distances
[maxLen
] = _pos
- curMatch
- 1;
230 for (int count
= _cutValue
; count
!= 0; count
--)
232 int pby1
= _bufferOffset
+ curMatch
;
233 int currentLen
= Math
.min(minLeft
, minRight
);
234 for (; currentLen
< lenLimit
; currentLen
++)
235 if (_bufferBase
[pby1
+ currentLen
] != _bufferBase
[cur
+ currentLen
])
237 int delta
= _pos
- curMatch
;
238 while (currentLen
> maxLen
)
239 distances
[++maxLen
] = delta
- 1;
241 int cyclicPos
= ((delta
<= _cyclicBufferPos
) ?
242 (_cyclicBufferPos
- delta
) :
243 (_cyclicBufferPos
- delta
+ _cyclicBufferSize
)) << 1;
245 if (currentLen
!= lenLimit
)
247 if ((_bufferBase
[pby1
+ currentLen
] & 0xFF) < (_bufferBase
[cur
+ currentLen
] & 0xFF))
249 _son
[ptrRight
] = curMatch
;
250 ptrRight
= cyclicPos
+ 1;
251 curMatch
= _son
[ptrRight
];
252 if (currentLen
> minLeft
)
253 minLeft
= currentLen
;
257 _son
[ptrLeft
] = curMatch
;
259 curMatch
= _son
[ptrLeft
];
260 if (currentLen
> minRight
)
261 minRight
= currentLen
;
266 if (currentLen
< _matchMaxLen
)
268 _son
[ptrLeft
] = curMatch
;
270 curMatch
= _son
[ptrLeft
];
271 if (currentLen
> minRight
)
272 minRight
= currentLen
;
276 _son
[ptrLeft
] = _son
[cyclicPos
+ 1];
277 _son
[ptrRight
] = _son
[cyclicPos
];
281 if (matchLen2Exist
&& len2Distance
< distances
[2])
282 distances
[2] = len2Distance
;
283 if (matchLen3Exist
&& len3Distance
< distances
[3])
284 distances
[3] = len3Distance
;
289 if (curMatch
< matchMinPos
)
292 _son
[ptrLeft
] = kEmptyHashValue
;
293 _son
[ptrRight
] = kEmptyHashValue
;
301 distances
[2] = len2Distance
;
304 else if (len2Distance
< distances
[2])
305 distances
[2] = len2Distance
;
312 distances
[3] = len3Distance
;
315 else if (len3Distance
< distances
[3])
316 distances
[3] = len3Distance
;
323 public void DummyLongestMatch()
325 // GetLongestMatch(_dummy);
328 if (_pos
+ _matchMaxLen
<= _streamPos
)
329 lenLimit
= _matchMaxLen
;
332 lenLimit
= _streamPos
- _pos
;
333 if (lenLimit
< kNumHashBytes
)
337 int matchMinPos
= (_pos
> _historySize
) ?
(_pos
- _historySize
) : 1;
339 int cur
= _bufferOffset
+ _pos
;
341 int hashValue
, hash2Value
= 0, hash3Value
= 0;
345 int temp
= CrcTable
[_bufferBase
[cur
] & 0xFF] ^
(_bufferBase
[cur
+ 1] & 0xFF);
346 hash2Value
= temp
& (kHash2Size
- 1);
347 temp ^
= ((int)(_bufferBase
[cur
+ 2] & 0xFF) << 8);
348 hash3Value
= temp
& (kHash3Size
- 1);
349 hashValue
= (temp ^
(CrcTable
[_bufferBase
[cur
+ 3] & 0xFF] << 5)) & (kHashSize
- 1);
352 hashValue
= ((_bufferBase
[cur
] & 0xFF) ^
((int)(_bufferBase
[cur
+ 1] & 0xFF) << 8)) & (kHashSize
- 1);
354 int curMatch
= _hash
[hashValue
];
355 int curMatch2
= 0, curMatch3
= 0;
358 curMatch2
= _hash2
[hash2Value
];
359 curMatch3
= _hash3
[hash3Value
];
360 _hash2
[hash2Value
] = _pos
;
361 _hash3
[hash3Value
] = _pos
;
363 _hash
[hashValue
] = _pos
;
365 if (curMatch
< matchMinPos
)
367 _son
[(_cyclicBufferPos
<< 1)] = kEmptyHashValue
;
368 _son
[(_cyclicBufferPos
<< 1) + 1] = kEmptyHashValue
;
371 int ptrLeft
= (_cyclicBufferPos
<< 1) + 1;
372 int ptrRight
= (_cyclicBufferPos
<< 1);
374 int minLeft
, minRight
;
375 minLeft
= minRight
= kNumHashDirectBytes
;
377 for (int count
= _cutValue
; count
!= 0; count
--)
379 int pby1
= _bufferOffset
+ curMatch
;
380 int currentLen
= Math
.min(minLeft
, minRight
);
381 for (; currentLen
< lenLimit
; currentLen
++)
382 if (_bufferBase
[pby1
+ currentLen
] != _bufferBase
[cur
+ currentLen
])
384 int delta
= _pos
- curMatch
;
386 int cyclicPos
= ((delta
<= _cyclicBufferPos
) ?
387 (_cyclicBufferPos
- delta
) :
388 (_cyclicBufferPos
- delta
+ _cyclicBufferSize
)) << 1;
390 if (currentLen
!= lenLimit
)
392 if ((_bufferBase
[pby1
+ currentLen
] & 0xFF) < (_bufferBase
[cur
+ currentLen
] & 0xFF))
394 _son
[ptrRight
] = curMatch
;
395 ptrRight
= cyclicPos
+ 1;
396 curMatch
= _son
[ptrRight
];
397 if (currentLen
> minLeft
)
398 minLeft
= currentLen
;
402 _son
[ptrLeft
] = curMatch
;
404 curMatch
= _son
[ptrLeft
];
405 if (currentLen
> minRight
)
406 minRight
= currentLen
;
411 if (currentLen
< _matchMaxLen
)
413 _son
[ptrLeft
] = curMatch
;
415 curMatch
= _son
[ptrLeft
];
416 if (currentLen
> minRight
)
417 minRight
= currentLen
;
421 _son
[ptrLeft
] = _son
[cyclicPos
+ 1];
422 _son
[ptrRight
] = _son
[cyclicPos
];
426 if (curMatch
< matchMinPos
)
429 _son
[ptrLeft
] = kEmptyHashValue
;
430 _son
[ptrRight
] = kEmptyHashValue
;
433 void NormalizeLinks(int[] items
, int numItems
, int subValue
)
435 for (int i
= 0; i
< numItems
; i
++)
437 int value
= items
[i
];
438 if (value
<= subValue
)
439 value
= kEmptyHashValue
;
448 int startItem
= _pos
- _historySize
;
449 int subValue
= startItem
- 1;
450 NormalizeLinks(_son
, _cyclicBufferSize
* 2, subValue
);
452 NormalizeLinks(_hash
, kHashSize
, subValue
);
456 NormalizeLinks(_hash2
, kHash2Size
, subValue
);
457 NormalizeLinks(_hash3
, kHash3Size
, subValue
);
459 ReduceOffsets(subValue
);
462 public void SetCutValue(int cutValue
)
463 { _cutValue
= cutValue
; }