📄 bintree.java
字号:
package SevenZip.Compression.LZ;
import java.io.IOException;
public class BinTree extends InWindow
{
int _cyclicBufferPos;
int _cyclicBufferSize;
int _historySize;
int _matchMaxLen;
int[] _son;
int[] _hash;
int[] _hash2;
int[] _hash3;
int _cutValue = 0xFF;
boolean HASH_ARRAY = true;
boolean HASH_BIG = false;
static final int kHash3Size = 1 << 18;
static final int kBT2HashSize = 1 << 16;
static final int kBT4Hash2Size = 1 << 10;
static final int kBT4Hash4Size = 1 << 20;
static final int kBT4bHash4Size = 1 << 23;
static final int kBT2NumHashDirectBytes = 2;
static final int kBT4NumHashDirectBytes = 0;
int kHash2Size = kBT4Hash2Size;
int kNumHashDirectBytes = kBT4NumHashDirectBytes;
int kNumHashBytes = 4;
int kHashSize = kBT4Hash4Size;
private static final int[] CrcTable = new int[256];
static
{
for (int i = 0; i < 256; i++)
{
int r = i;
for (int j = 0; j < 8; j++)
if ((r & 1) != 0)
r = (r >>> 1) ^ 0xEDB88320;
else
r >>>= 1;
CrcTable[i] = r;
}
}
public void SetType(int numHashBytes, boolean big)
{
HASH_ARRAY = numHashBytes > 2;
HASH_BIG = big;
if (HASH_ARRAY)
{
kHash2Size = kBT4Hash2Size;
kNumHashDirectBytes = kBT4NumHashDirectBytes;
kNumHashBytes = 4;
kHashSize = (HASH_BIG ? kBT4bHash4Size : kBT4Hash4Size);
}
else
{
kNumHashDirectBytes = kBT2NumHashDirectBytes;
kNumHashBytes = 2;
kHashSize = kBT2HashSize;
}
}
static final int kEmptyHashValue = 0;
static final int kMaxValForNormalize = ((int)1 << 30) - 1;
public void Init() throws IOException
{
super.Init();
int i;
for (i = 0; i < kHashSize; i++)
_hash[i] = kEmptyHashValue;
if (HASH_ARRAY)
{
for (i = 0; i < kHash2Size; i++)
_hash2[i] = kEmptyHashValue;
for (i = 0; i < kHash3Size; i++)
_hash3[i] = kEmptyHashValue;
}
_cyclicBufferPos = 0;
ReduceOffsets(-1);
}
public void MovePos() throws IOException
{
if (++_cyclicBufferPos >= _cyclicBufferSize)
_cyclicBufferPos = 0;
super.MovePos();
if (_pos == kMaxValForNormalize)
Normalize();
}
public boolean Create(int historySize, int keepAddBufferBefore,
int matchMaxLen, int keepAddBufferAfter)
{
int windowReservSize = (historySize + keepAddBufferBefore +
matchMaxLen + keepAddBufferAfter) / 2 + 256;
_son = null;
_hash = null;
_hash2 = null;
_hash3 = null;
super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
if (_blockSize + 256 > kMaxValForNormalize)
return false;
_historySize = historySize;
_matchMaxLen = matchMaxLen;
_cyclicBufferSize = historySize + 1;
_son = new int[_cyclicBufferSize * 2];
_hash = new int[kHashSize];
if (HASH_ARRAY)
{
_hash2 = new int[kHash2Size];
_hash3 = new int[kHash3Size];
}
return true;
}
public int GetLongestMatch(int[] distances)
{
int lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
lenLimit = _matchMaxLen;
else
{
lenLimit = _streamPos - _pos;
if (lenLimit < kNumHashBytes)
return 0;
}
int matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1;
int cur = _bufferOffset + _pos;
int matchHashLenMax = 0;
int hashValue, hash2Value = 0, hash3Value = 0;
if (HASH_ARRAY)
{
int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF);
hash2Value = temp & (kHash2Size - 1);
temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8);
hash3Value = temp & (kHash3Size - 1);
hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & (kHashSize - 1);
}
else
hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)) & (kHashSize - 1);
int curMatch = _hash[hashValue];
int curMatch2 = 0, curMatch3 = 0;
int len2Distance = 0;
int len3Distance = 0;
boolean matchLen2Exist = false;
boolean matchLen3Exist = false;
if (HASH_ARRAY)
{
curMatch2 = _hash2[hash2Value];
curMatch3 = _hash3[hash3Value];
_hash2[hash2Value] = _pos;
if (curMatch2 >= matchMinPos)
{
if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
{
len2Distance = _pos - curMatch2 - 1;
matchHashLenMax = 2;
matchLen2Exist = true;
}
}
{
_hash3[hash3Value] = _pos;
if (curMatch3 >= matchMinPos)
{
if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
{
len3Distance = _pos - curMatch3 - 1;
matchHashLenMax = 3;
matchLen3Exist = true;
if (matchLen2Exist)
{
if (len3Distance < len2Distance)
len2Distance = len3Distance;
}
else
{
len2Distance = len3Distance;
matchLen2Exist = true;
}
}
}
}
}
_hash[hashValue] = _pos;
if (curMatch < matchMinPos)
{
_son[(_cyclicBufferPos << 1)] = kEmptyHashValue;
_son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue;
if (HASH_ARRAY)
{
distances[2] = len2Distance;
distances[3] = len3Distance;
}
return matchHashLenMax;
}
int ptrLeft = (_cyclicBufferPos << 1) + 1;
int ptrRight = (_cyclicBufferPos << 1);
int maxLen, minLeft, minRight;
maxLen = minLeft = minRight = kNumHashDirectBytes;
distances[maxLen] = _pos - curMatch - 1;
for (int count = _cutValue; count != 0; count--)
{
int pby1 = _bufferOffset + curMatch;
int currentLen = Math.min(minLeft, minRight);
for (; currentLen < lenLimit; currentLen++)
if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen])
break;
int delta = _pos - curMatch;
while (currentLen > maxLen)
distances[++maxLen] = delta - 1;
int cyclicPos = ((delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta) :
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
if (currentLen != lenLimit)
{
if ((_bufferBase[pby1 + currentLen] & 0xFF) < (_bufferBase[cur + currentLen] & 0xFF))
{
_son[ptrRight] = curMatch;
ptrRight = cyclicPos + 1;
curMatch = _son[ptrRight];
if (currentLen > minLeft)
minLeft = currentLen;
}
else
{
_son[ptrLeft] = curMatch;
ptrLeft = cyclicPos;
curMatch = _son[ptrLeft];
if (currentLen > minRight)
minRight = currentLen;
}
}
else
{
if (currentLen < _matchMaxLen)
{
_son[ptrLeft] = curMatch;
ptrLeft = cyclicPos;
curMatch = _son[ptrLeft];
if (currentLen > minRight)
minRight = currentLen;
}
else
{
_son[ptrLeft] = _son[cyclicPos + 1];
_son[ptrRight] = _son[cyclicPos];
if (HASH_ARRAY)
{
if (matchLen2Exist && len2Distance < distances[2])
distances[2] = len2Distance;
if (matchLen3Exist && len3Distance < distances[3])
distances[3] = len3Distance;
}
return maxLen;
}
}
if (curMatch < matchMinPos)
break;
}
_son[ptrLeft] = kEmptyHashValue;
_son[ptrRight] = kEmptyHashValue;
if (HASH_ARRAY)
{
if (matchLen2Exist)
{
if (maxLen < 2)
{
distances[2] = len2Distance;
maxLen = 2;
}
else if (len2Distance < distances[2])
distances[2] = len2Distance;
}
{
if (matchLen3Exist)
{
if (maxLen < 3)
{
distances[3] = len3Distance;
maxLen = 3;
}
else if (len3Distance < distances[3])
distances[3] = len3Distance;
}
}
}
return maxLen;
}
public void DummyLongestMatch()
{
// GetLongestMatch(_dummy);
int lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
lenLimit = _matchMaxLen;
else
{
lenLimit = _streamPos - _pos;
if (lenLimit < kNumHashBytes)
return;
}
int matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1;
int cur = _bufferOffset + _pos;
int hashValue, hash2Value = 0, hash3Value = 0;
if (HASH_ARRAY)
{
int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF);
hash2Value = temp & (kHash2Size - 1);
temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8);
hash3Value = temp & (kHash3Size - 1);
hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & (kHashSize - 1);
}
else
hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)) & (kHashSize - 1);
int curMatch = _hash[hashValue];
int curMatch2 = 0, curMatch3 = 0;
if (HASH_ARRAY)
{
curMatch2 = _hash2[hash2Value];
curMatch3 = _hash3[hash3Value];
_hash2[hash2Value] = _pos;
_hash3[hash3Value] = _pos;
}
_hash[hashValue] = _pos;
if (curMatch < matchMinPos)
{
_son[(_cyclicBufferPos << 1)] = kEmptyHashValue;
_son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue;
return;
}
int ptrLeft = (_cyclicBufferPos << 1) + 1;
int ptrRight = (_cyclicBufferPos << 1);
int minLeft, minRight;
minLeft = minRight = kNumHashDirectBytes;
for (int count = _cutValue; count != 0; count--)
{
int pby1 = _bufferOffset + curMatch;
int currentLen = Math.min(minLeft, minRight);
for (; currentLen < lenLimit; currentLen++)
if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen])
break;
int delta = _pos - curMatch;
int cyclicPos = ((delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta) :
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
if (currentLen != lenLimit)
{
if ((_bufferBase[pby1 + currentLen] & 0xFF) < (_bufferBase[cur + currentLen] & 0xFF))
{
_son[ptrRight] = curMatch;
ptrRight = cyclicPos + 1;
curMatch = _son[ptrRight];
if (currentLen > minLeft)
minLeft = currentLen;
}
else
{
_son[ptrLeft] = curMatch;
ptrLeft = cyclicPos;
curMatch = _son[ptrLeft];
if (currentLen > minRight)
minRight = currentLen;
}
}
else
{
if (currentLen < _matchMaxLen)
{
_son[ptrLeft] = curMatch;
ptrLeft = cyclicPos;
curMatch = _son[ptrLeft];
if (currentLen > minRight)
minRight = currentLen;
}
else
{
_son[ptrLeft] = _son[cyclicPos + 1];
_son[ptrRight] = _son[cyclicPos];
return;
}
}
if (curMatch < matchMinPos)
break;
}
_son[ptrLeft] = kEmptyHashValue;
_son[ptrRight] = kEmptyHashValue;
}
void NormalizeLinks(int[] items, int numItems, int subValue)
{
for (int i = 0; i < numItems; i++)
{
int value = items[i];
if (value <= subValue)
value = kEmptyHashValue;
else
value -= subValue;
items[i] = value;
}
}
void Normalize()
{
int startItem = _pos - _historySize;
int subValue = startItem - 1;
NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
NormalizeLinks(_hash, kHashSize, subValue);
if (HASH_ARRAY)
{
NormalizeLinks(_hash2, kHash2Size, subValue);
NormalizeLinks(_hash3, kHash3Size, subValue);
}
ReduceOffsets(subValue);
}
public void SetCutValue(int cutValue)
{ _cutValue = cutValue; }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -