A fingerprint is a 64 bit number that represents the state of the dictionary * at a given time, it's just a few dict properties xored together. * When an unsafe iterator is initialized, we get the dict fingerprint, and check * the fingerprint again when the iterator is released. * If the two fingerprints are different it means that the user of the iterator * performed forbidden operations aga
| 707 | * If the two fingerprints are different it means that the user of the iterator |
| 708 | * performed forbidden operations against the dictionary while iterating. */ |
| 709 | unsigned long long HashTable_Fingerprint(dict *d) { |
| 710 | unsigned long long integers[6], hash = 0; |
| 711 | int j; |
| 712 | |
| 713 | integers[0] = (long) d->ht_table[0]; |
| 714 | integers[1] = d->ht_size_exp[0]; |
| 715 | integers[2] = d->ht_used[0]; |
| 716 | integers[3] = (long) d->ht_table[1]; |
| 717 | integers[4] = d->ht_size_exp[1]; |
| 718 | integers[5] = d->ht_used[1]; |
| 719 | |
| 720 | /* We hash N integers by summing every successive integer with the integer |
| 721 | * hashing of the previous sum. Basically: |
| 722 | * |
| 723 | * Result = hash(hash(hash(int1)+int2)+int3) ... |
| 724 | * |
| 725 | * This way the same set of integers in a different order will (likely) hash |
| 726 | * to a different number. */ |
| 727 | for (j = 0; j < 6; j++) { |
| 728 | hash += integers[j]; |
| 729 | /* For the hashing step we use Tomas Wang's 64 bit integer hash. */ |
| 730 | hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1; |
| 731 | hash = hash ^ (hash >> 24); |
| 732 | hash = (hash + (hash << 3)) + (hash << 8); // hash * 265 |
| 733 | hash = hash ^ (hash >> 14); |
| 734 | hash = (hash + (hash << 2)) + (hash << 4); // hash * 21 |
| 735 | hash = hash ^ (hash >> 28); |
| 736 | hash = hash + (hash << 31); |
| 737 | } |
| 738 | return hash; |
| 739 | } |
| 740 | |
| 741 | void HashTableInitIterator(dictIterator *iter, dict *d) |
| 742 | { |
no outgoing calls
no test coverage detected