jpayne@69
|
1 #ifndef Py_HASH_H
|
jpayne@69
|
2
|
jpayne@69
|
3 #define Py_HASH_H
|
jpayne@69
|
4 #ifdef __cplusplus
|
jpayne@69
|
5 extern "C" {
|
jpayne@69
|
6 #endif
|
jpayne@69
|
7
|
jpayne@69
|
8 /* Helpers for hash functions */
|
jpayne@69
|
9 #ifndef Py_LIMITED_API
|
jpayne@69
|
10 PyAPI_FUNC(Py_hash_t) _Py_HashDouble(double);
|
jpayne@69
|
11 PyAPI_FUNC(Py_hash_t) _Py_HashPointer(void*);
|
jpayne@69
|
12 PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void*, Py_ssize_t);
|
jpayne@69
|
13 #endif
|
jpayne@69
|
14
|
jpayne@69
|
15 /* Prime multiplier used in string and various other hashes. */
|
jpayne@69
|
16 #define _PyHASH_MULTIPLIER 1000003UL /* 0xf4243 */
|
jpayne@69
|
17
|
jpayne@69
|
18 /* Parameters used for the numeric hash implementation. See notes for
|
jpayne@69
|
19 _Py_HashDouble in Python/pyhash.c. Numeric hashes are based on
|
jpayne@69
|
20 reduction modulo the prime 2**_PyHASH_BITS - 1. */
|
jpayne@69
|
21
|
jpayne@69
|
22 #if SIZEOF_VOID_P >= 8
|
jpayne@69
|
23 # define _PyHASH_BITS 61
|
jpayne@69
|
24 #else
|
jpayne@69
|
25 # define _PyHASH_BITS 31
|
jpayne@69
|
26 #endif
|
jpayne@69
|
27
|
jpayne@69
|
28 #define _PyHASH_MODULUS (((size_t)1 << _PyHASH_BITS) - 1)
|
jpayne@69
|
29 #define _PyHASH_INF 314159
|
jpayne@69
|
30 #define _PyHASH_NAN 0
|
jpayne@69
|
31 #define _PyHASH_IMAG _PyHASH_MULTIPLIER
|
jpayne@69
|
32
|
jpayne@69
|
33
|
jpayne@69
|
34 /* hash secret
|
jpayne@69
|
35 *
|
jpayne@69
|
36 * memory layout on 64 bit systems
|
jpayne@69
|
37 * cccccccc cccccccc cccccccc uc -- unsigned char[24]
|
jpayne@69
|
38 * pppppppp ssssssss ........ fnv -- two Py_hash_t
|
jpayne@69
|
39 * k0k0k0k0 k1k1k1k1 ........ siphash -- two uint64_t
|
jpayne@69
|
40 * ........ ........ ssssssss djbx33a -- 16 bytes padding + one Py_hash_t
|
jpayne@69
|
41 * ........ ........ eeeeeeee pyexpat XML hash salt
|
jpayne@69
|
42 *
|
jpayne@69
|
43 * memory layout on 32 bit systems
|
jpayne@69
|
44 * cccccccc cccccccc cccccccc uc
|
jpayne@69
|
45 * ppppssss ........ ........ fnv -- two Py_hash_t
|
jpayne@69
|
46 * k0k0k0k0 k1k1k1k1 ........ siphash -- two uint64_t (*)
|
jpayne@69
|
47 * ........ ........ ssss.... djbx33a -- 16 bytes padding + one Py_hash_t
|
jpayne@69
|
48 * ........ ........ eeee.... pyexpat XML hash salt
|
jpayne@69
|
49 *
|
jpayne@69
|
50 * (*) The siphash member may not be available on 32 bit platforms without
|
jpayne@69
|
51 * an unsigned int64 data type.
|
jpayne@69
|
52 */
|
jpayne@69
|
53 #ifndef Py_LIMITED_API
|
jpayne@69
|
54 typedef union {
|
jpayne@69
|
55 /* ensure 24 bytes */
|
jpayne@69
|
56 unsigned char uc[24];
|
jpayne@69
|
57 /* two Py_hash_t for FNV */
|
jpayne@69
|
58 struct {
|
jpayne@69
|
59 Py_hash_t prefix;
|
jpayne@69
|
60 Py_hash_t suffix;
|
jpayne@69
|
61 } fnv;
|
jpayne@69
|
62 /* two uint64 for SipHash24 */
|
jpayne@69
|
63 struct {
|
jpayne@69
|
64 uint64_t k0;
|
jpayne@69
|
65 uint64_t k1;
|
jpayne@69
|
66 } siphash;
|
jpayne@69
|
67 /* a different (!) Py_hash_t for small string optimization */
|
jpayne@69
|
68 struct {
|
jpayne@69
|
69 unsigned char padding[16];
|
jpayne@69
|
70 Py_hash_t suffix;
|
jpayne@69
|
71 } djbx33a;
|
jpayne@69
|
72 struct {
|
jpayne@69
|
73 unsigned char padding[16];
|
jpayne@69
|
74 Py_hash_t hashsalt;
|
jpayne@69
|
75 } expat;
|
jpayne@69
|
76 } _Py_HashSecret_t;
|
jpayne@69
|
77 PyAPI_DATA(_Py_HashSecret_t) _Py_HashSecret;
|
jpayne@69
|
78 #endif
|
jpayne@69
|
79
|
jpayne@69
|
80 #ifdef Py_DEBUG
|
jpayne@69
|
81 PyAPI_DATA(int) _Py_HashSecret_Initialized;
|
jpayne@69
|
82 #endif
|
jpayne@69
|
83
|
jpayne@69
|
84
|
jpayne@69
|
85 /* hash function definition */
|
jpayne@69
|
86 #ifndef Py_LIMITED_API
|
jpayne@69
|
87 typedef struct {
|
jpayne@69
|
88 Py_hash_t (*const hash)(const void *, Py_ssize_t);
|
jpayne@69
|
89 const char *name;
|
jpayne@69
|
90 const int hash_bits;
|
jpayne@69
|
91 const int seed_bits;
|
jpayne@69
|
92 } PyHash_FuncDef;
|
jpayne@69
|
93
|
jpayne@69
|
94 PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void);
|
jpayne@69
|
95 #endif
|
jpayne@69
|
96
|
jpayne@69
|
97
|
jpayne@69
|
98 /* cutoff for small string DJBX33A optimization in range [1, cutoff).
|
jpayne@69
|
99 *
|
jpayne@69
|
100 * About 50% of the strings in a typical Python application are smaller than
|
jpayne@69
|
101 * 6 to 7 chars. However DJBX33A is vulnerable to hash collision attacks.
|
jpayne@69
|
102 * NEVER use DJBX33A for long strings!
|
jpayne@69
|
103 *
|
jpayne@69
|
104 * A Py_HASH_CUTOFF of 0 disables small string optimization. 32 bit platforms
|
jpayne@69
|
105 * should use a smaller cutoff because it is easier to create colliding
|
jpayne@69
|
106 * strings. A cutoff of 7 on 64bit platforms and 5 on 32bit platforms should
|
jpayne@69
|
107 * provide a decent safety margin.
|
jpayne@69
|
108 */
|
jpayne@69
|
109 #ifndef Py_HASH_CUTOFF
|
jpayne@69
|
110 # define Py_HASH_CUTOFF 0
|
jpayne@69
|
111 #elif (Py_HASH_CUTOFF > 7 || Py_HASH_CUTOFF < 0)
|
jpayne@69
|
112 # error Py_HASH_CUTOFF must in range 0...7.
|
jpayne@69
|
113 #endif /* Py_HASH_CUTOFF */
|
jpayne@69
|
114
|
jpayne@69
|
115
|
jpayne@69
|
116 /* hash algorithm selection
|
jpayne@69
|
117 *
|
jpayne@69
|
118 * The values for Py_HASH_SIPHASH24 and Py_HASH_FNV are hard-coded in the
|
jpayne@69
|
119 * configure script.
|
jpayne@69
|
120 *
|
jpayne@69
|
121 * - FNV is available on all platforms and architectures.
|
jpayne@69
|
122 * - SIPHASH24 only works on platforms that don't require aligned memory for integers.
|
jpayne@69
|
123 * - With EXTERNAL embedders can provide an alternative implementation with::
|
jpayne@69
|
124 *
|
jpayne@69
|
125 * PyHash_FuncDef PyHash_Func = {...};
|
jpayne@69
|
126 *
|
jpayne@69
|
127 * XXX: Figure out __declspec() for extern PyHash_FuncDef.
|
jpayne@69
|
128 */
|
jpayne@69
|
129 #define Py_HASH_EXTERNAL 0
|
jpayne@69
|
130 #define Py_HASH_SIPHASH24 1
|
jpayne@69
|
131 #define Py_HASH_FNV 2
|
jpayne@69
|
132
|
jpayne@69
|
133 #ifndef Py_HASH_ALGORITHM
|
jpayne@69
|
134 # ifndef HAVE_ALIGNED_REQUIRED
|
jpayne@69
|
135 # define Py_HASH_ALGORITHM Py_HASH_SIPHASH24
|
jpayne@69
|
136 # else
|
jpayne@69
|
137 # define Py_HASH_ALGORITHM Py_HASH_FNV
|
jpayne@69
|
138 # endif /* uint64_t && uint32_t && aligned */
|
jpayne@69
|
139 #endif /* Py_HASH_ALGORITHM */
|
jpayne@69
|
140
|
jpayne@69
|
141 #ifdef __cplusplus
|
jpayne@69
|
142 }
|
jpayne@69
|
143 #endif
|
jpayne@69
|
144
|
jpayne@69
|
145 #endif /* !Py_HASH_H */
|