package de.axone.equals; /** * Hash algorithm by Bob Jenkins, 1996. * * You may use this code any way you wish, private, educational, or commercial. It's free. * See: http://burtleburtle.net/bob/hash/doobs.html * * Use for hash table lookup, or anything where one collision in 2^^32 * is acceptable. Do NOT use for cryptographic purposes. * * Java port by Gray Watson http://256.com/gray/ * * Flo: inserted 'state' to make it threadsafe */ public class Jenkins96Backend { // max value to limit it to 4 bytes private static final long MAX_VALUE = 0xFFFFFFFFL; // internal variables used in the various calculations private static final class state { long a, b, c; } /** * Convert a byte into a long value without making it negative. */ private long byteToLong(byte b) { long val = b & 0x7F; if ((b & 0x80) != 0) { val += 128; } return val; } /** * Do addition and turn into 4 bytes. */ private long add(long val, long add) { return (val + add) & MAX_VALUE; } /** * Do subtraction and turn into 4 bytes. */ private long subtract(long val, long subtract) { return (val - subtract) & MAX_VALUE; } /** * Left shift val by shift bits and turn in 4 bytes. */ private long xor(long val, long xor) { return (val ^ xor) & MAX_VALUE; } /** * Left shift val by shift bits. Cut down to 4 bytes. */ private long leftShift(long val, int shift) { return (val << shift) & MAX_VALUE; } /** * Convert 4 bytes from the buffer at offset into a long value. */ private long fourByteToLong(byte[] bytes, int offset) { return (byteToLong(bytes[offset + 0]) + (byteToLong(bytes[offset + 1]) << 8) + (byteToLong(bytes[offset + 2]) << 16) + (byteToLong(bytes[offset + 3]) << 24)); } /** * Mix up the values in the hash function. */ private void hashMix( state s ) { long a=s.a, b=s.b, c=s.c; a = subtract(a, b); a = subtract(a, c); a = xor(a, c >> 13); b = subtract(b, c); b = subtract(b, a); b = xor(b, leftShift(a, 8)); c = subtract(c, a); c = subtract(c, b); c = xor(c, (b >> 13)); a = subtract(a, b); a = subtract(a, c); a = xor(a, (c >> 12)); b = subtract(b, c); b = subtract(b, a); b = xor(b, leftShift(a, 16)); c = subtract(c, a); c = subtract(c, b); c = xor(c, (b >> 5)); a = subtract(a, b); a = subtract(a, c); a = xor(a, (c >> 3)); b = subtract(b, c); b = subtract(b, a); b = xor(b, leftShift(a, 10)); c = subtract(c, a); c = subtract(c, b); c = xor(c, (b >> 15)); s.a=a; s.b=b; s.c=c; } /** * Hash a variable-length key into a 32-bit value. Every bit of the * key affects every bit of the return value. Every 1-bit and 2-bit * delta achieves avalanche. The best hash table sizes are powers of 2. * * @param buffer Byte array that we are hashing on. * @param initialValue Initial value of the hash if we are continuing from * a previous run. 0 if none. * @return Hash value for the buffer. */ @SuppressWarnings( "fallthrough" ) public long hash(byte[] buffer, long initialValue) { int len, pos; state s = new state(); // set up the internal state // the golden ratio; an arbitrary value s.a = 0x09e3779b9L; // the golden ratio; an arbitrary value s.b = 0x09e3779b9L; // the previous hash value s.c = initialValue; // handle most of the key pos = 0; for (len = buffer.length; len >=12; len -= 12) { s.a = add(s.a, fourByteToLong(buffer, pos)); s.b = add(s.b, fourByteToLong(buffer, pos + 4)); s.c = add(s.c, fourByteToLong(buffer, pos + 8)); hashMix( s ); pos += 12; } s.c += buffer.length; // all the case statements fall through to the next on purpose switch(len) { case 11: s.c = add(s.c, leftShift(byteToLong(buffer[pos + 10]), 24)); case 10: s.c = add(s.c, leftShift(byteToLong(buffer[pos + 9]), 16)); case 9: s.c = add(s.c, leftShift(byteToLong(buffer[pos + 8]), 8)); // the first byte of c is reserved for the length case 8: s.b = add(s.b, leftShift(byteToLong(buffer[pos + 7]), 24)); case 7: s.b = add(s.b, leftShift(byteToLong(buffer[pos + 6]), 16)); case 6: s.b = add(s.b, leftShift(byteToLong(buffer[pos + 5]), 8)); case 5: s.b = add(s.b, byteToLong(buffer[pos + 4])); case 4: s.a = add(s.a, leftShift(byteToLong(buffer[pos + 3]), 24)); case 3: s.a = add(s.a, leftShift(byteToLong(buffer[pos + 2]), 16)); case 2: s.a = add(s.a, leftShift(byteToLong(buffer[pos + 1]), 8)); case 1: s.a = add(s.a, byteToLong(buffer[pos + 0])); default: // case 0: nothing left to add } hashMix( s ); return s.c; } /** * See hash(byte[] buffer, long initialValue) * @param buffer Byte array that we are hashing on. * @return Hash value for the buffer. */ public long hash(byte[] buffer) { return hash(buffer, 0); } public long hash(String string ){ return hash( string.getBytes(), 0 ); } }