in src/main/java/org/apache/commons/codec/digest/MurmurHash3.java [178:247]
public final void add(final byte[] data, final int offset, final int length) {
if (length <= 0) {
// Nothing to add
return;
}
totalLen += length;
// Process the bytes in blocks of 4.
// New bytes must be added to any current unprocessed bytes,
// then processed in blocks of 4 and the remaining bytes saved:
//
// |--|---------------------------|--|
// unprocessed
// main block
// remaining
// Check if the unprocessed bytes and new bytes can fill a block of 4.
// Make this overflow safe in the event that length is Integer.MAX_VALUE.
// Equivalent to: (unprocessedLength + length < BLOCK_SIZE)
if (unprocessedLength + length - BLOCK_SIZE < 0) {
// Not enough so add to the unprocessed bytes
System.arraycopy(data, offset, unprocessed, unprocessedLength, length);
unprocessedLength += length;
return;
}
// Combine unprocessed bytes with new bytes.
final int newOffset;
final int newLength;
if (unprocessedLength > 0) {
int k = -1;
switch (unprocessedLength) {
case 1:
k = orBytes(unprocessed[0], data[offset], data[offset + 1], data[offset + 2]);
break;
case 2:
k = orBytes(unprocessed[0], unprocessed[1], data[offset], data[offset + 1]);
break;
case 3:
k = orBytes(unprocessed[0], unprocessed[1], unprocessed[2], data[offset]);
break;
default:
throw new IllegalStateException("Unprocessed length should be 1, 2, or 3: " + unprocessedLength);
}
hash = mix32(k, hash);
// Update the offset and length
final int consumed = BLOCK_SIZE - unprocessedLength;
newOffset = offset + consumed;
newLength = length - consumed;
} else {
newOffset = offset;
newLength = length;
}
// Main processing of blocks of 4 bytes
final int nblocks = newLength >> 2;
for (int i = 0; i < nblocks; i++) {
final int index = newOffset + (i << 2);
final int k = getLittleEndianInt(data, index);
hash = mix32(k, hash);
}
// Save left-over unprocessed bytes
final int consumed = nblocks << 2;
unprocessedLength = newLength - consumed;
if (unprocessedLength != 0) {
System.arraycopy(data, newOffset + consumed, unprocessed, 0, unprocessedLength);
}
}