private void updateModel(int index) { byte c = buf[index]; if (index > 0) { HashNode hNode = new HashNode(); byte prevC = buf[index - 1]; int pos = ((prevC & 0xff) << 8) | (c & 0xff); hNode.index = index - 1; hNode.next = hashTable[pos]; hashTable[pos] = hNode; } }
// consider refactoring signature to return PotentialMatch object with fields set... int findMatch(int index, int[] distOut, int[] gainOut, int[] costPerByteOut) { final int maxCostCacheLength = 32; int[] literalCostCache = new int[maxCostCacheLength + 1]; int maxIndexMinusIndex = buf.length - index; int bestLength = 0; int bestDist = 0; int bestGain = 0; int bestCopyCost = 0; int maxComputedLength = 0; if (maxIndexMinusIndex > 1) { int pos = ((buf[index] & 0xff) << 8) | (buf[index + 1] & 0xff); HashNode prevNode = null; int hNodeCount = 0; for (HashNode hNode = hashTable[pos]; hNode != null; prevNode = hNode, hNode = hNode.next) { int i = hNode.index; int dist = index - i; hNodeCount++; if (hNodeCount > 256 || dist > maxCopyDist) { if (hashTable[pos] == hNode) { hashTable[pos] = null; } else { prevNode.next = null; } break; } int maxLen = index - i; if (maxIndexMinusIndex < maxLen) { maxLen = maxIndexMinusIndex; } if (maxLen < LEN_MIN) { continue; } i += 2; int length = 2; for (length = 2; length < maxLen && buf[i] == buf[index + length]; length++) { i++; } if (length < LEN_MIN) { continue; } dist = dist - length + 1; if (dist > distMax || (length == 2 && dist >= MAX_2BYTE_DIST)) { continue; } if (length <= bestLength && dist > bestDist) { if (length <= bestLength - 2) { continue; } if (dist > (bestDist << DIST_WIDTH)) { if (length < bestLength || dist > (bestDist << (DIST_WIDTH + 1))) { continue; } } } int literalCost = 0; if (length > maxComputedLength) { int limit = length; if (limit > maxCostCacheLength) limit = maxCostCacheLength; for (i = maxComputedLength; i < limit; i++) { byte c = buf[index + i]; literalCostCache[i + 1] = literalCostCache[i] + symEncoder.writeSymbolCost(c & 0xff); } maxComputedLength = limit; if (length > maxCostCacheLength) { literalCost = literalCostCache[maxCostCacheLength]; literalCost += literalCost / maxCostCacheLength * (length - maxCostCacheLength); } else { literalCost = literalCostCache[length]; } } else { literalCost = literalCostCache[length]; } if (literalCost > bestGain) { int distRanges = getNumDistRanges(dist); int copyCost = encodeLengthCost(length, dist, distRanges); if (literalCost - copyCost - (distRanges << 16) > bestGain) { copyCost += encodeDistance2Cost(dist, distRanges); int gain = literalCost - copyCost; if (gain > bestGain) { bestGain = gain; bestLength = length; bestDist = dist; bestCopyCost = copyCost; } } } } } costPerByteOut[0] = bestLength > 0 ? bestCopyCost / bestLength : 0; distOut[0] = bestDist; gainOut[0] = bestGain; return bestLength; }