1 #ifndef Py_INTERNAL_PYHASH_H 2 #define Py_INTERNAL_PYHASH_H 3 4 #ifndef Py_BUILD_CORE 5 # error "this header requires Py_BUILD_CORE define" 6 #endif 7 8 // Similar to Py_HashPointer(), but don't replace -1 with -2. 9 static inline Py_hash_t _Py_HashPointerRaw(const void * ptr)10_Py_HashPointerRaw(const void *ptr) 11 { 12 uintptr_t x = (uintptr_t)ptr; 13 Py_BUILD_ASSERT(sizeof(x) == sizeof(ptr)); 14 15 // Bottom 3 or 4 bits are likely to be 0; rotate x by 4 to the right 16 // to avoid excessive hash collisions for dicts and sets. 17 x = (x >> 4) | (x << (8 * sizeof(uintptr_t) - 4)); 18 19 Py_BUILD_ASSERT(sizeof(x) == sizeof(Py_hash_t)); 20 return (Py_hash_t)x; 21 } 22 23 // Export for '_datetime' shared extension 24 PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void*, Py_ssize_t); 25 26 /* Hash secret 27 * 28 * memory layout on 64 bit systems 29 * cccccccc cccccccc cccccccc uc -- unsigned char[24] 30 * pppppppp ssssssss ........ fnv -- two Py_hash_t 31 * k0k0k0k0 k1k1k1k1 ........ siphash -- two uint64_t 32 * ........ ........ ssssssss djbx33a -- 16 bytes padding + one Py_hash_t 33 * ........ ........ eeeeeeee pyexpat XML hash salt 34 * 35 * memory layout on 32 bit systems 36 * cccccccc cccccccc cccccccc uc 37 * ppppssss ........ ........ fnv -- two Py_hash_t 38 * k0k0k0k0 k1k1k1k1 ........ siphash -- two uint64_t (*) 39 * ........ ........ ssss.... djbx33a -- 16 bytes padding + one Py_hash_t 40 * ........ ........ eeee.... pyexpat XML hash salt 41 * 42 * (*) The siphash member may not be available on 32 bit platforms without 43 * an unsigned int64 data type. 44 */ 45 typedef union { 46 /* ensure 24 bytes */ 47 unsigned char uc[24]; 48 /* two Py_hash_t for FNV */ 49 struct { 50 Py_hash_t prefix; 51 Py_hash_t suffix; 52 } fnv; 53 /* two uint64 for SipHash24 */ 54 struct { 55 uint64_t k0; 56 uint64_t k1; 57 } siphash; 58 /* a different (!) Py_hash_t for small string optimization */ 59 struct { 60 unsigned char padding[16]; 61 Py_hash_t suffix; 62 } djbx33a; 63 struct { 64 unsigned char padding[16]; 65 Py_hash_t hashsalt; 66 } expat; 67 } _Py_HashSecret_t; 68 69 // Export for '_elementtree' shared extension 70 PyAPI_DATA(_Py_HashSecret_t) _Py_HashSecret; 71 72 #ifdef Py_DEBUG 73 extern int _Py_HashSecret_Initialized; 74 #endif 75 76 77 struct pyhash_runtime_state { 78 struct { 79 #ifndef MS_WINDOWS 80 int fd; 81 dev_t st_dev; 82 ino_t st_ino; 83 #else 84 // This is a placeholder so the struct isn't empty on Windows. 85 int _not_used; 86 #endif 87 } urandom_cache; 88 }; 89 90 #ifndef MS_WINDOWS 91 # define _py_urandom_cache_INIT \ 92 { \ 93 .fd = -1, \ 94 } 95 #else 96 # define _py_urandom_cache_INIT {0} 97 #endif 98 99 #define pyhash_state_INIT \ 100 { \ 101 .urandom_cache = _py_urandom_cache_INIT, \ 102 } 103 104 105 extern uint64_t _Py_KeyedHash(uint64_t key, const void *src, Py_ssize_t src_sz); 106 107 #endif // !Py_INTERNAL_PYHASH_H 108