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
| 891 | * If the two fingerprints are different it means that the user of the iterator |
| 892 | * performed forbidden operations against the dictionary while iterating. */ |
| 893 | long long dictFingerprint(dict *d) { |
| 894 | long long integers[6], hash = 0; |
| 895 | int j; |
| 896 | |
| 897 | integers[0] = (long) d->ht[0].table; |
| 898 | integers[1] = d->ht[0].size; |
| 899 | integers[2] = d->ht[0].used; |
| 900 | integers[3] = (long) d->ht[1].table; |
| 901 | integers[4] = d->ht[1].size; |
| 902 | integers[5] = d->ht[1].used; |
| 903 | |
| 904 | /* We hash N integers by summing every successive integer with the integer |
| 905 | * hashing of the previous sum. Basically: |
| 906 | * |
| 907 | * Result = hash(hash(hash(int1)+int2)+int3) ... |
| 908 | * |
| 909 | * This way the same set of integers in a different order will (likely) hash |
| 910 | * to a different number. */ |
| 911 | for (j = 0; j < 6; j++) { |
| 912 | hash += integers[j]; |
| 913 | /* For the hashing step we use Tomas Wang's 64 bit integer hash. */ |
| 914 | hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1; |
| 915 | hash = hash ^ (hash >> 24); |
| 916 | hash = (hash + (hash << 3)) + (hash << 8); // hash * 265 |
| 917 | hash = hash ^ (hash >> 14); |
| 918 | hash = (hash + (hash << 2)) + (hash << 4); // hash * 21 |
| 919 | hash = hash ^ (hash >> 28); |
| 920 | hash = hash + (hash << 31); |
| 921 | } |
| 922 | return hash; |
| 923 | } |
| 924 | |
| 925 | dictIterator *dictGetIterator(dict *d) |
| 926 | { |
no outgoing calls
no test coverage detected