1370b324cSopenharmony_ci// LZ.BinTree 2370b324cSopenharmony_ci 3370b324cSopenharmony_cipackage SevenZip.Compression.LZ; 4370b324cSopenharmony_ciimport java.io.IOException; 5370b324cSopenharmony_ci 6370b324cSopenharmony_ci 7370b324cSopenharmony_cipublic class BinTree extends InWindow 8370b324cSopenharmony_ci{ 9370b324cSopenharmony_ci int _cyclicBufferPos; 10370b324cSopenharmony_ci int _cyclicBufferSize = 0; 11370b324cSopenharmony_ci int _matchMaxLen; 12370b324cSopenharmony_ci 13370b324cSopenharmony_ci int[] _son; 14370b324cSopenharmony_ci int[] _hash; 15370b324cSopenharmony_ci 16370b324cSopenharmony_ci int _cutValue = 0xFF; 17370b324cSopenharmony_ci int _hashMask; 18370b324cSopenharmony_ci int _hashSizeSum = 0; 19370b324cSopenharmony_ci 20370b324cSopenharmony_ci boolean HASH_ARRAY = true; 21370b324cSopenharmony_ci 22370b324cSopenharmony_ci static final int kHash2Size = 1 << 10; 23370b324cSopenharmony_ci static final int kHash3Size = 1 << 16; 24370b324cSopenharmony_ci static final int kBT2HashSize = 1 << 16; 25370b324cSopenharmony_ci static final int kStartMaxLen = 1; 26370b324cSopenharmony_ci static final int kHash3Offset = kHash2Size; 27370b324cSopenharmony_ci static final int kEmptyHashValue = 0; 28370b324cSopenharmony_ci static final int kMaxValForNormalize = (1 << 30) - 1; 29370b324cSopenharmony_ci 30370b324cSopenharmony_ci int kNumHashDirectBytes = 0; 31370b324cSopenharmony_ci int kMinMatchCheck = 4; 32370b324cSopenharmony_ci int kFixHashSize = kHash2Size + kHash3Size; 33370b324cSopenharmony_ci 34370b324cSopenharmony_ci public void SetType(int numHashBytes) 35370b324cSopenharmony_ci { 36370b324cSopenharmony_ci HASH_ARRAY = (numHashBytes > 2); 37370b324cSopenharmony_ci if (HASH_ARRAY) 38370b324cSopenharmony_ci { 39370b324cSopenharmony_ci kNumHashDirectBytes = 0; 40370b324cSopenharmony_ci kMinMatchCheck = 4; 41370b324cSopenharmony_ci kFixHashSize = kHash2Size + kHash3Size; 42370b324cSopenharmony_ci } 43370b324cSopenharmony_ci else 44370b324cSopenharmony_ci { 45370b324cSopenharmony_ci kNumHashDirectBytes = 2; 46370b324cSopenharmony_ci kMinMatchCheck = 2 + 1; 47370b324cSopenharmony_ci kFixHashSize = 0; 48370b324cSopenharmony_ci } 49370b324cSopenharmony_ci } 50370b324cSopenharmony_ci 51370b324cSopenharmony_ci 52370b324cSopenharmony_ci 53370b324cSopenharmony_ci 54370b324cSopenharmony_ci public void Init() throws IOException 55370b324cSopenharmony_ci { 56370b324cSopenharmony_ci super.Init(); 57370b324cSopenharmony_ci for (int i = 0; i < _hashSizeSum; i++) 58370b324cSopenharmony_ci _hash[i] = kEmptyHashValue; 59370b324cSopenharmony_ci _cyclicBufferPos = 0; 60370b324cSopenharmony_ci ReduceOffsets(-1); 61370b324cSopenharmony_ci } 62370b324cSopenharmony_ci 63370b324cSopenharmony_ci public void MovePos() throws IOException 64370b324cSopenharmony_ci { 65370b324cSopenharmony_ci if (++_cyclicBufferPos >= _cyclicBufferSize) 66370b324cSopenharmony_ci _cyclicBufferPos = 0; 67370b324cSopenharmony_ci super.MovePos(); 68370b324cSopenharmony_ci if (_pos == kMaxValForNormalize) 69370b324cSopenharmony_ci Normalize(); 70370b324cSopenharmony_ci } 71370b324cSopenharmony_ci 72370b324cSopenharmony_ci 73370b324cSopenharmony_ci 74370b324cSopenharmony_ci 75370b324cSopenharmony_ci 76370b324cSopenharmony_ci 77370b324cSopenharmony_ci 78370b324cSopenharmony_ci 79370b324cSopenharmony_ci public boolean Create(int historySize, int keepAddBufferBefore, 80370b324cSopenharmony_ci int matchMaxLen, int keepAddBufferAfter) 81370b324cSopenharmony_ci { 82370b324cSopenharmony_ci if (historySize > kMaxValForNormalize - 256) 83370b324cSopenharmony_ci return false; 84370b324cSopenharmony_ci _cutValue = 16 + (matchMaxLen >> 1); 85370b324cSopenharmony_ci 86370b324cSopenharmony_ci int windowReservSize = (historySize + keepAddBufferBefore + 87370b324cSopenharmony_ci matchMaxLen + keepAddBufferAfter) / 2 + 256; 88370b324cSopenharmony_ci 89370b324cSopenharmony_ci super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); 90370b324cSopenharmony_ci 91370b324cSopenharmony_ci _matchMaxLen = matchMaxLen; 92370b324cSopenharmony_ci 93370b324cSopenharmony_ci int cyclicBufferSize = historySize + 1; 94370b324cSopenharmony_ci if (_cyclicBufferSize != cyclicBufferSize) 95370b324cSopenharmony_ci _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; 96370b324cSopenharmony_ci 97370b324cSopenharmony_ci int hs = kBT2HashSize; 98370b324cSopenharmony_ci 99370b324cSopenharmony_ci if (HASH_ARRAY) 100370b324cSopenharmony_ci { 101370b324cSopenharmony_ci hs = historySize - 1; 102370b324cSopenharmony_ci hs |= (hs >> 1); 103370b324cSopenharmony_ci hs |= (hs >> 2); 104370b324cSopenharmony_ci hs |= (hs >> 4); 105370b324cSopenharmony_ci hs |= (hs >> 8); 106370b324cSopenharmony_ci hs >>= 1; 107370b324cSopenharmony_ci hs |= 0xFFFF; 108370b324cSopenharmony_ci if (hs > (1 << 24)) 109370b324cSopenharmony_ci hs >>= 1; 110370b324cSopenharmony_ci _hashMask = hs; 111370b324cSopenharmony_ci hs++; 112370b324cSopenharmony_ci hs += kFixHashSize; 113370b324cSopenharmony_ci } 114370b324cSopenharmony_ci if (hs != _hashSizeSum) 115370b324cSopenharmony_ci _hash = new int [_hashSizeSum = hs]; 116370b324cSopenharmony_ci return true; 117370b324cSopenharmony_ci } 118370b324cSopenharmony_ci public int GetMatches(int[] distances) throws IOException 119370b324cSopenharmony_ci { 120370b324cSopenharmony_ci int lenLimit; 121370b324cSopenharmony_ci if (_pos + _matchMaxLen <= _streamPos) 122370b324cSopenharmony_ci lenLimit = _matchMaxLen; 123370b324cSopenharmony_ci else 124370b324cSopenharmony_ci { 125370b324cSopenharmony_ci lenLimit = _streamPos - _pos; 126370b324cSopenharmony_ci if (lenLimit < kMinMatchCheck) 127370b324cSopenharmony_ci { 128370b324cSopenharmony_ci MovePos(); 129370b324cSopenharmony_ci return 0; 130370b324cSopenharmony_ci } 131370b324cSopenharmony_ci } 132370b324cSopenharmony_ci 133370b324cSopenharmony_ci int offset = 0; 134370b324cSopenharmony_ci int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; 135370b324cSopenharmony_ci int cur = _bufferOffset + _pos; 136370b324cSopenharmony_ci int maxLen = kStartMaxLen; // to avoid items for len < hashSize; 137370b324cSopenharmony_ci int hashValue, hash2Value = 0, hash3Value = 0; 138370b324cSopenharmony_ci 139370b324cSopenharmony_ci if (HASH_ARRAY) 140370b324cSopenharmony_ci { 141370b324cSopenharmony_ci int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); 142370b324cSopenharmony_ci hash2Value = temp & (kHash2Size - 1); 143370b324cSopenharmony_ci temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); 144370b324cSopenharmony_ci hash3Value = temp & (kHash3Size - 1); 145370b324cSopenharmony_ci hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; 146370b324cSopenharmony_ci } 147370b324cSopenharmony_ci else 148370b324cSopenharmony_ci hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); 149370b324cSopenharmony_ci 150370b324cSopenharmony_ci int curMatch = _hash[kFixHashSize + hashValue]; 151370b324cSopenharmony_ci if (HASH_ARRAY) 152370b324cSopenharmony_ci { 153370b324cSopenharmony_ci int curMatch2 = _hash[hash2Value]; 154370b324cSopenharmony_ci int curMatch3 = _hash[kHash3Offset + hash3Value]; 155370b324cSopenharmony_ci _hash[hash2Value] = _pos; 156370b324cSopenharmony_ci _hash[kHash3Offset + hash3Value] = _pos; 157370b324cSopenharmony_ci if (curMatch2 > matchMinPos) 158370b324cSopenharmony_ci if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) 159370b324cSopenharmony_ci { 160370b324cSopenharmony_ci distances[offset++] = maxLen = 2; 161370b324cSopenharmony_ci distances[offset++] = _pos - curMatch2 - 1; 162370b324cSopenharmony_ci } 163370b324cSopenharmony_ci if (curMatch3 > matchMinPos) 164370b324cSopenharmony_ci if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) 165370b324cSopenharmony_ci { 166370b324cSopenharmony_ci if (curMatch3 == curMatch2) 167370b324cSopenharmony_ci offset -= 2; 168370b324cSopenharmony_ci distances[offset++] = maxLen = 3; 169370b324cSopenharmony_ci distances[offset++] = _pos - curMatch3 - 1; 170370b324cSopenharmony_ci curMatch2 = curMatch3; 171370b324cSopenharmony_ci } 172370b324cSopenharmony_ci if (offset != 0 && curMatch2 == curMatch) 173370b324cSopenharmony_ci { 174370b324cSopenharmony_ci offset -= 2; 175370b324cSopenharmony_ci maxLen = kStartMaxLen; 176370b324cSopenharmony_ci } 177370b324cSopenharmony_ci } 178370b324cSopenharmony_ci 179370b324cSopenharmony_ci _hash[kFixHashSize + hashValue] = _pos; 180370b324cSopenharmony_ci 181370b324cSopenharmony_ci int ptr0 = (_cyclicBufferPos << 1) + 1; 182370b324cSopenharmony_ci int ptr1 = (_cyclicBufferPos << 1); 183370b324cSopenharmony_ci 184370b324cSopenharmony_ci int len0, len1; 185370b324cSopenharmony_ci len0 = len1 = kNumHashDirectBytes; 186370b324cSopenharmony_ci 187370b324cSopenharmony_ci if (kNumHashDirectBytes != 0) 188370b324cSopenharmony_ci { 189370b324cSopenharmony_ci if (curMatch > matchMinPos) 190370b324cSopenharmony_ci { 191370b324cSopenharmony_ci if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != 192370b324cSopenharmony_ci _bufferBase[cur + kNumHashDirectBytes]) 193370b324cSopenharmony_ci { 194370b324cSopenharmony_ci distances[offset++] = maxLen = kNumHashDirectBytes; 195370b324cSopenharmony_ci distances[offset++] = _pos - curMatch - 1; 196370b324cSopenharmony_ci } 197370b324cSopenharmony_ci } 198370b324cSopenharmony_ci } 199370b324cSopenharmony_ci 200370b324cSopenharmony_ci int count = _cutValue; 201370b324cSopenharmony_ci 202370b324cSopenharmony_ci while (true) 203370b324cSopenharmony_ci { 204370b324cSopenharmony_ci if (curMatch <= matchMinPos || count-- == 0) 205370b324cSopenharmony_ci { 206370b324cSopenharmony_ci _son[ptr0] = _son[ptr1] = kEmptyHashValue; 207370b324cSopenharmony_ci break; 208370b324cSopenharmony_ci } 209370b324cSopenharmony_ci int delta = _pos - curMatch; 210370b324cSopenharmony_ci int cyclicPos = ((delta <= _cyclicBufferPos) ? 211370b324cSopenharmony_ci (_cyclicBufferPos - delta) : 212370b324cSopenharmony_ci (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; 213370b324cSopenharmony_ci 214370b324cSopenharmony_ci int pby1 = _bufferOffset + curMatch; 215370b324cSopenharmony_ci int len = Math.min(len0, len1); 216370b324cSopenharmony_ci if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) 217370b324cSopenharmony_ci { 218370b324cSopenharmony_ci while(++len != lenLimit) 219370b324cSopenharmony_ci if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) 220370b324cSopenharmony_ci break; 221370b324cSopenharmony_ci if (maxLen < len) 222370b324cSopenharmony_ci { 223370b324cSopenharmony_ci distances[offset++] = maxLen = len; 224370b324cSopenharmony_ci distances[offset++] = delta - 1; 225370b324cSopenharmony_ci if (len == lenLimit) 226370b324cSopenharmony_ci { 227370b324cSopenharmony_ci _son[ptr1] = _son[cyclicPos]; 228370b324cSopenharmony_ci _son[ptr0] = _son[cyclicPos + 1]; 229370b324cSopenharmony_ci break; 230370b324cSopenharmony_ci } 231370b324cSopenharmony_ci } 232370b324cSopenharmony_ci } 233370b324cSopenharmony_ci if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) 234370b324cSopenharmony_ci { 235370b324cSopenharmony_ci _son[ptr1] = curMatch; 236370b324cSopenharmony_ci ptr1 = cyclicPos + 1; 237370b324cSopenharmony_ci curMatch = _son[ptr1]; 238370b324cSopenharmony_ci len1 = len; 239370b324cSopenharmony_ci } 240370b324cSopenharmony_ci else 241370b324cSopenharmony_ci { 242370b324cSopenharmony_ci _son[ptr0] = curMatch; 243370b324cSopenharmony_ci ptr0 = cyclicPos; 244370b324cSopenharmony_ci curMatch = _son[ptr0]; 245370b324cSopenharmony_ci len0 = len; 246370b324cSopenharmony_ci } 247370b324cSopenharmony_ci } 248370b324cSopenharmony_ci MovePos(); 249370b324cSopenharmony_ci return offset; 250370b324cSopenharmony_ci } 251370b324cSopenharmony_ci 252370b324cSopenharmony_ci public void Skip(int num) throws IOException 253370b324cSopenharmony_ci { 254370b324cSopenharmony_ci do 255370b324cSopenharmony_ci { 256370b324cSopenharmony_ci int lenLimit; 257370b324cSopenharmony_ci if (_pos + _matchMaxLen <= _streamPos) 258370b324cSopenharmony_ci lenLimit = _matchMaxLen; 259370b324cSopenharmony_ci else 260370b324cSopenharmony_ci { 261370b324cSopenharmony_ci lenLimit = _streamPos - _pos; 262370b324cSopenharmony_ci if (lenLimit < kMinMatchCheck) 263370b324cSopenharmony_ci { 264370b324cSopenharmony_ci MovePos(); 265370b324cSopenharmony_ci continue; 266370b324cSopenharmony_ci } 267370b324cSopenharmony_ci } 268370b324cSopenharmony_ci 269370b324cSopenharmony_ci int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; 270370b324cSopenharmony_ci int cur = _bufferOffset + _pos; 271370b324cSopenharmony_ci 272370b324cSopenharmony_ci int hashValue; 273370b324cSopenharmony_ci 274370b324cSopenharmony_ci if (HASH_ARRAY) 275370b324cSopenharmony_ci { 276370b324cSopenharmony_ci int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); 277370b324cSopenharmony_ci int hash2Value = temp & (kHash2Size - 1); 278370b324cSopenharmony_ci _hash[hash2Value] = _pos; 279370b324cSopenharmony_ci temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); 280370b324cSopenharmony_ci int hash3Value = temp & (kHash3Size - 1); 281370b324cSopenharmony_ci _hash[kHash3Offset + hash3Value] = _pos; 282370b324cSopenharmony_ci hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; 283370b324cSopenharmony_ci } 284370b324cSopenharmony_ci else 285370b324cSopenharmony_ci hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); 286370b324cSopenharmony_ci 287370b324cSopenharmony_ci int curMatch = _hash[kFixHashSize + hashValue]; 288370b324cSopenharmony_ci _hash[kFixHashSize + hashValue] = _pos; 289370b324cSopenharmony_ci 290370b324cSopenharmony_ci int ptr0 = (_cyclicBufferPos << 1) + 1; 291370b324cSopenharmony_ci int ptr1 = (_cyclicBufferPos << 1); 292370b324cSopenharmony_ci 293370b324cSopenharmony_ci int len0, len1; 294370b324cSopenharmony_ci len0 = len1 = kNumHashDirectBytes; 295370b324cSopenharmony_ci 296370b324cSopenharmony_ci int count = _cutValue; 297370b324cSopenharmony_ci while (true) 298370b324cSopenharmony_ci { 299370b324cSopenharmony_ci if (curMatch <= matchMinPos || count-- == 0) 300370b324cSopenharmony_ci { 301370b324cSopenharmony_ci _son[ptr0] = _son[ptr1] = kEmptyHashValue; 302370b324cSopenharmony_ci break; 303370b324cSopenharmony_ci } 304370b324cSopenharmony_ci 305370b324cSopenharmony_ci int delta = _pos - curMatch; 306370b324cSopenharmony_ci int cyclicPos = ((delta <= _cyclicBufferPos) ? 307370b324cSopenharmony_ci (_cyclicBufferPos - delta) : 308370b324cSopenharmony_ci (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; 309370b324cSopenharmony_ci 310370b324cSopenharmony_ci int pby1 = _bufferOffset + curMatch; 311370b324cSopenharmony_ci int len = Math.min(len0, len1); 312370b324cSopenharmony_ci if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) 313370b324cSopenharmony_ci { 314370b324cSopenharmony_ci while (++len != lenLimit) 315370b324cSopenharmony_ci if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) 316370b324cSopenharmony_ci break; 317370b324cSopenharmony_ci if (len == lenLimit) 318370b324cSopenharmony_ci { 319370b324cSopenharmony_ci _son[ptr1] = _son[cyclicPos]; 320370b324cSopenharmony_ci _son[ptr0] = _son[cyclicPos + 1]; 321370b324cSopenharmony_ci break; 322370b324cSopenharmony_ci } 323370b324cSopenharmony_ci } 324370b324cSopenharmony_ci if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) 325370b324cSopenharmony_ci { 326370b324cSopenharmony_ci _son[ptr1] = curMatch; 327370b324cSopenharmony_ci ptr1 = cyclicPos + 1; 328370b324cSopenharmony_ci curMatch = _son[ptr1]; 329370b324cSopenharmony_ci len1 = len; 330370b324cSopenharmony_ci } 331370b324cSopenharmony_ci else 332370b324cSopenharmony_ci { 333370b324cSopenharmony_ci _son[ptr0] = curMatch; 334370b324cSopenharmony_ci ptr0 = cyclicPos; 335370b324cSopenharmony_ci curMatch = _son[ptr0]; 336370b324cSopenharmony_ci len0 = len; 337370b324cSopenharmony_ci } 338370b324cSopenharmony_ci } 339370b324cSopenharmony_ci MovePos(); 340370b324cSopenharmony_ci } 341370b324cSopenharmony_ci while (--num != 0); 342370b324cSopenharmony_ci } 343370b324cSopenharmony_ci 344370b324cSopenharmony_ci void NormalizeLinks(int[] items, int numItems, int subValue) 345370b324cSopenharmony_ci { 346370b324cSopenharmony_ci for (int i = 0; i < numItems; i++) 347370b324cSopenharmony_ci { 348370b324cSopenharmony_ci int value = items[i]; 349370b324cSopenharmony_ci if (value <= subValue) 350370b324cSopenharmony_ci value = kEmptyHashValue; 351370b324cSopenharmony_ci else 352370b324cSopenharmony_ci value -= subValue; 353370b324cSopenharmony_ci items[i] = value; 354370b324cSopenharmony_ci } 355370b324cSopenharmony_ci } 356370b324cSopenharmony_ci 357370b324cSopenharmony_ci void Normalize() 358370b324cSopenharmony_ci { 359370b324cSopenharmony_ci int subValue = _pos - _cyclicBufferSize; 360370b324cSopenharmony_ci NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); 361370b324cSopenharmony_ci NormalizeLinks(_hash, _hashSizeSum, subValue); 362370b324cSopenharmony_ci ReduceOffsets(subValue); 363370b324cSopenharmony_ci } 364370b324cSopenharmony_ci 365370b324cSopenharmony_ci public void SetCutValue(int cutValue) { _cutValue = cutValue; } 366370b324cSopenharmony_ci 367370b324cSopenharmony_ci private static final int[] CrcTable = new int[256]; 368370b324cSopenharmony_ci 369370b324cSopenharmony_ci static 370370b324cSopenharmony_ci { 371370b324cSopenharmony_ci for (int i = 0; i < 256; i++) 372370b324cSopenharmony_ci { 373370b324cSopenharmony_ci int r = i; 374370b324cSopenharmony_ci for (int j = 0; j < 8; j++) 375370b324cSopenharmony_ci if ((r & 1) != 0) 376370b324cSopenharmony_ci r = (r >>> 1) ^ 0xEDB88320; 377370b324cSopenharmony_ci else 378370b324cSopenharmony_ci r >>>= 1; 379370b324cSopenharmony_ci CrcTable[i] = r; 380370b324cSopenharmony_ci } 381370b324cSopenharmony_ci } 382370b324cSopenharmony_ci} 383