diff --git a/src/dict.c b/src/dict.c index a967be46c9b82c2658b6f6a57b140c59ca5989be..3c1061f347d7f47da8a88667b1824646628ae721 100644 --- a/src/dict.c +++ b/src/dict.c @@ -512,15 +512,35 @@ void *dictFetchValue(dict *d, const void *key) { * If the two fingerprints are different it means that the user of the iterator * performed forbidden operations against the dictionary while iterating. */ long long dictFingerprint(dict *d) { - long long fingerprint = 0; - - fingerprint ^= (long long) d->ht[0].table; - fingerprint ^= (long long) d->ht[0].size; - fingerprint ^= (long long) d->ht[0].used; - fingerprint ^= (long long) d->ht[1].table; - fingerprint ^= (long long) d->ht[1].size; - fingerprint ^= (long long) d->ht[1].used; - return fingerprint; + long long integers[6], hash = 0; + int j; + + integers[0] = (long long) d->ht[0].table; + integers[1] = d->ht[0].size; + integers[2] = d->ht[0].used; + integers[3] = (long long) d->ht[1].table; + integers[4] = d->ht[1].size; + integers[5] = d->ht[1].used; + + /* We hash N integers by summing every successive integer with the integer + * hashing of the previous sum. Basically: + * + * Result = hash(hash(hash(int1)+int2)+int3) ... + * + * This way the same set of integers in a different order will (likely) hash + * to a different number. */ + for (j = 0; j < 6; j++) { + hash += integers[j]; + /* For the hashing step we use Tomas Wang's 64 bit integer hash. */ + hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1; + hash = hash ^ (hash >> 24); + hash = (hash + (hash << 3)) + (hash << 8); // hash * 265 + hash = hash ^ (hash >> 14); + hash = (hash + (hash << 2)) + (hash << 4); // hash * 21 + hash = hash ^ (hash >> 28); + hash = hash + (hash << 31); + } + return hash; } dictIterator *dictGetIterator(dict *d)