annotate jansson/src/lookup3.h @ 57:82b832e1875d

vera: import 1.3.0, closes #728
author David Demelier <markand@malikania.fr>
date Tue, 21 Nov 2017 12:19:28 +0100
parents 0047655db1aa
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 -------------------------------------------------------------------------------
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 lookup3.c, by Bob Jenkins, May 2006, Public Domain.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
4
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 These are functions for producing 32-bit hashes for hash table lookup.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 are externally useful functions. Routines to test the hash are included
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 if SELF_TEST is defined. You can use this free for any purpose. It's in
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 the public domain. It has no warranty.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
10
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 You probably want to use hashlittle(). hashlittle() and hashbig()
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 hash byte arrays. hashlittle() is is faster than hashbig() on
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 little-endian machines. Intel and AMD are little-endian machines.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 On second thought, you probably want hashlittle2(), which is identical to
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
15 hashlittle() except it returns two 32-bit hashes for the price of one.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 You could implement hashbig2() if you wanted but I haven't bothered here.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
17
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
18 If you want to find a hash of, say, exactly 7 integers, do
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
19 a = i1; b = i2; c = i3;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
20 mix(a,b,c);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
21 a += i4; b += i5; c += i6;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 mix(a,b,c);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 a += i7;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 final(a,b,c);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
25 then use c as the hash value. If you have a variable length array of
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 4-byte integers to hash, use hashword(). If you have a byte array (like
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
27 a character string), use hashlittle(). If you have several byte arrays, or
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 a mix of things, see the comments above hashlittle().
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
29
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
30 Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
31 then mix those integers. This is fast (you can do a lot more thorough
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
32 mixing with 12*3 instructions on 3 integers than you can with 3 instructions
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
33 on 1 byte), but shoehorning those bytes into integers efficiently is messy.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
34 -------------------------------------------------------------------------------
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
35 */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
36
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 #include <stdlib.h>
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
38
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
39 #ifdef HAVE_CONFIG_H
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
40 #include <jansson_private_config.h>
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
41 #endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
42
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
43 #ifdef HAVE_STDINT_H
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
44 #include <stdint.h> /* defines uint32_t etc */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
45 #endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
46
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
47 #ifdef HAVE_SYS_PARAM_H
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
48 #include <sys/param.h> /* attempt to define endianness */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
49 #endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
50
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
51 #ifdef HAVE_ENDIAN_H
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
52 # include <endian.h> /* attempt to define endianness */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
53 #endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
54
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
55 /*
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
56 * My best guess at if you are big-endian or little-endian. This may
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
57 * need adjustment.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
59 #if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
60 __BYTE_ORDER == __LITTLE_ENDIAN) || \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
61 (defined(i386) || defined(__i386__) || defined(__i486__) || \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
62 defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
63 # define HASH_LITTLE_ENDIAN 1
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 # define HASH_BIG_ENDIAN 0
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
65 #elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
66 __BYTE_ORDER == __BIG_ENDIAN) || \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
67 (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
68 # define HASH_LITTLE_ENDIAN 0
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 # define HASH_BIG_ENDIAN 1
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
70 #else
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
71 # define HASH_LITTLE_ENDIAN 0
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
72 # define HASH_BIG_ENDIAN 0
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 #endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
74
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 #define hashsize(n) ((uint32_t)1<<(n))
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
76 #define hashmask(n) (hashsize(n)-1)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
78
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
79 /*
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 -------------------------------------------------------------------------------
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 mix -- mix 3 32-bit values reversibly.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
82
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
83 This is reversible, so any information in (a,b,c) before mix() is
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
84 still in (a,b,c) after mix().
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
85
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
86 If four pairs of (a,b,c) inputs are run through mix(), or through
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
87 mix() in reverse, there are at least 32 bits of the output that
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
88 are sometimes the same for one pair and different for another pair.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
89 This was tested for:
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
90 * pairs that differed by one bit, by two bits, in any combination
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 of top bits of (a,b,c), or in any combination of bottom bits of
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
92 (a,b,c).
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
93 * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
95 is commonly produced by subtraction) look like a single 1-bit
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 difference.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
97 * the base values were pseudorandom, all zero but one bit set, or
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
98 all zero plus a counter that starts at zero.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
99
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
100 Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
101 satisfy this are
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
102 4 6 8 16 19 4
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
103 9 15 3 18 27 15
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
104 14 9 3 7 17 3
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
105 Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
106 for "differ" defined as + with a one-bit base and a two-bit delta. I
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
107 used http://burtleburtle.net/bob/hash/avalanche.html to choose
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 the operations, constants, and arrangements of the variables.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
109
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 This does not achieve avalanche. There are input bits of (a,b,c)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
111 that fail to affect some output bits of (a,b,c), especially of a. The
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
112 most thoroughly mixed value is c, but it doesn't really even achieve
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
113 avalanche in c.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
114
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
115 This allows some parallelism. Read-after-writes are good at doubling
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
116 the number of bits affected, so the goal of mixing pulls in the opposite
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
117 direction as the goal of parallelism. I did what I could. Rotates
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
118 seem to cost as much as shifts on every machine I could lay my hands
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 on, and rotates are much kinder to the top and bottom bits, so I used
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
120 rotates.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
121 -------------------------------------------------------------------------------
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
122 */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
123 #define mix(a,b,c) \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
124 { \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
125 a -= c; a ^= rot(c, 4); c += b; \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
126 b -= a; b ^= rot(a, 6); a += c; \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
127 c -= b; c ^= rot(b, 8); b += a; \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
128 a -= c; a ^= rot(c,16); c += b; \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
129 b -= a; b ^= rot(a,19); a += c; \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
130 c -= b; c ^= rot(b, 4); b += a; \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
132
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
133 /*
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 -------------------------------------------------------------------------------
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
135 final -- final mixing of 3 32-bit values (a,b,c) into c
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
136
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
137 Pairs of (a,b,c) values differing in only a few bits will usually
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
138 produce values of c that look totally different. This was tested for
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
139 * pairs that differed by one bit, by two bits, in any combination
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
140 of top bits of (a,b,c), or in any combination of bottom bits of
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
141 (a,b,c).
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
142 * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
143 the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
144 is commonly produced by subtraction) look like a single 1-bit
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
145 difference.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
146 * the base values were pseudorandom, all zero but one bit set, or
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
147 all zero plus a counter that starts at zero.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
148
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
149 These constants passed:
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
150 14 11 25 16 4 14 24
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
151 12 14 25 16 4 14 24
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
152 and these came close:
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
153 4 8 15 26 3 22 24
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
154 10 8 15 26 3 22 24
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
155 11 8 15 26 3 22 24
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
156 -------------------------------------------------------------------------------
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
157 */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
158 #define final(a,b,c) \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
159 { \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
160 c ^= b; c -= rot(b,14); \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
161 a ^= c; a -= rot(c,11); \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
162 b ^= a; b -= rot(a,25); \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
163 c ^= b; c -= rot(b,16); \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
164 a ^= c; a -= rot(c,4); \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
165 b ^= a; b -= rot(a,14); \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
166 c ^= b; c -= rot(b,24); \
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
167 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
168
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
169 /*
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
170 -------------------------------------------------------------------------------
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
171 hashlittle() -- hash a variable-length key into a 32-bit value
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
172 k : the key (the unaligned variable-length array of bytes)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
173 length : the length of the key, counting by bytes
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
174 initval : can be any 4-byte value
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
175 Returns a 32-bit value. Every bit of the key affects every bit of
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
176 the return value. Two keys differing by one or two bits will have
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
177 totally different hash values.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
178
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
179 The best hash table sizes are powers of 2. There is no need to do
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
180 mod a prime (mod is sooo slow!). If you need less than 32 bits,
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
181 use a bitmask. For example, if you need only 10 bits, do
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
182 h = (h & hashmask(10));
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
183 In which case, the hash table should have hashsize(10) elements.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
184
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
185 If you are hashing n strings (uint8_t **)k, do it like this:
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
186 for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
187
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
188 By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
189 code any way you wish, private, educational, or commercial. It's free.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
190
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
191 Use for hash table lookup, or anything where one collision in 2^^32 is
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
192 acceptable. Do NOT use for cryptographic purposes.
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
193 -------------------------------------------------------------------------------
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
194 */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
195
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
196 static uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
197 {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
198 uint32_t a,b,c; /* internal state */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
199 union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
200
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
201 /* Set up the internal state */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
202 a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
203
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
204 u.ptr = key;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
205 if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
206 const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
207
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
208 /* Detect Valgrind or AddressSanitizer */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
209 #ifdef VALGRIND
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
210 # define NO_MASKING_TRICK 1
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
211 #else
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
212 # if defined(__has_feature) /* Clang */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
213 # if __has_feature(address_sanitizer) /* is ASAN enabled? */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
214 # define NO_MASKING_TRICK 1
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
215 # endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
216 # else
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
217 # if defined(__SANITIZE_ADDRESS__) /* GCC 4.8.x, is ASAN enabled? */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
218 # define NO_MASKING_TRICK 1
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
219 # endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
220 # endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
221 #endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
222
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
223 #ifdef NO_MASKING_TRICK
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
224 const uint8_t *k8;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
225 #endif
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
226
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
227 /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
228 while (length > 12)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
229 {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
230 a += k[0];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
231 b += k[1];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
232 c += k[2];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
233 mix(a,b,c);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
234 length -= 12;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
235 k += 3;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
236 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
237
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
238 /*----------------------------- handle the last (probably partial) block */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
239 /*
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
240 * "k[2]&0xffffff" actually reads beyond the end of the string, but
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
241 * then masks off the part it's not allowed to read. Because the
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
242 * string is aligned, the masked-off tail is in the same word as the
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
243 * rest of the string. Every machine with memory protection I've seen
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
244 * does it on word boundaries, so is OK with this. But VALGRIND will
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
245 * still catch it and complain. The masking trick does make the hash
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
246 * noticably faster for short strings (like English words).
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
247 */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
248 #ifndef NO_MASKING_TRICK
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
249
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
250 switch(length)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
251 {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
252 case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
253 case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
254 case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
255 case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
256 case 8 : b+=k[1]; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
257 case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
258 case 6 : b+=k[1]&0xffff; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
259 case 5 : b+=k[1]&0xff; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
260 case 4 : a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
261 case 3 : a+=k[0]&0xffffff; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
262 case 2 : a+=k[0]&0xffff; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
263 case 1 : a+=k[0]&0xff; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
264 case 0 : return c; /* zero length strings require no mixing */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
265 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
266
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
267 #else /* make valgrind happy */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
268
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
269 k8 = (const uint8_t *)k;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
270 switch(length)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
271 {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
272 case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
273 case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
274 case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
275 case 9 : c+=k8[8]; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
276 case 8 : b+=k[1]; a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
277 case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
278 case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
279 case 5 : b+=k8[4]; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
280 case 4 : a+=k[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
281 case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
282 case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
283 case 1 : a+=k8[0]; break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
284 case 0 : return c;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
285 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
286
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
287 #endif /* !valgrind */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
288
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
289 } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
290 const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
291 const uint8_t *k8;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
292
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
293 /*--------------- all but last block: aligned reads and different mixing */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
294 while (length > 12)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
295 {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
296 a += k[0] + (((uint32_t)k[1])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
297 b += k[2] + (((uint32_t)k[3])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
298 c += k[4] + (((uint32_t)k[5])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
299 mix(a,b,c);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
300 length -= 12;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
301 k += 6;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
302 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
303
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
304 /*----------------------------- handle the last (probably partial) block */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
305 k8 = (const uint8_t *)k;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
306 switch(length)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
307 {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
308 case 12: c+=k[4]+(((uint32_t)k[5])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
309 b+=k[2]+(((uint32_t)k[3])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
310 a+=k[0]+(((uint32_t)k[1])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
311 break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
312 case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
313 case 10: c+=k[4];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
314 b+=k[2]+(((uint32_t)k[3])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
315 a+=k[0]+(((uint32_t)k[1])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
316 break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
317 case 9 : c+=k8[8]; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
318 case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
319 a+=k[0]+(((uint32_t)k[1])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
320 break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
321 case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
322 case 6 : b+=k[2];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
323 a+=k[0]+(((uint32_t)k[1])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
324 break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
325 case 5 : b+=k8[4]; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
326 case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
327 break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
328 case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
329 case 2 : a+=k[0];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
330 break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
331 case 1 : a+=k8[0];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
332 break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
333 case 0 : return c; /* zero length requires no mixing */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
334 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
335
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
336 } else { /* need to read the key one byte at a time */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
337 const uint8_t *k = (const uint8_t *)key;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
338
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
339 /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
340 while (length > 12)
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
341 {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
342 a += k[0];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
343 a += ((uint32_t)k[1])<<8;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
344 a += ((uint32_t)k[2])<<16;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
345 a += ((uint32_t)k[3])<<24;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
346 b += k[4];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
347 b += ((uint32_t)k[5])<<8;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
348 b += ((uint32_t)k[6])<<16;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
349 b += ((uint32_t)k[7])<<24;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
350 c += k[8];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
351 c += ((uint32_t)k[9])<<8;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
352 c += ((uint32_t)k[10])<<16;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
353 c += ((uint32_t)k[11])<<24;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
354 mix(a,b,c);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
355 length -= 12;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
356 k += 12;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
357 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
358
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
359 /*-------------------------------- last block: affect all 32 bits of (c) */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
360 switch(length) /* all the case statements fall through */
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
361 {
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
362 case 12: c+=((uint32_t)k[11])<<24;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
363 case 11: c+=((uint32_t)k[10])<<16;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
364 case 10: c+=((uint32_t)k[9])<<8;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
365 case 9 : c+=k[8];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
366 case 8 : b+=((uint32_t)k[7])<<24;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
367 case 7 : b+=((uint32_t)k[6])<<16;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
368 case 6 : b+=((uint32_t)k[5])<<8;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
369 case 5 : b+=k[4];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
370 case 4 : a+=((uint32_t)k[3])<<24;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
371 case 3 : a+=((uint32_t)k[2])<<16;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
372 case 2 : a+=((uint32_t)k[1])<<8;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
373 case 1 : a+=k[0];
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
374 break;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
375 case 0 : return c;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
376 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
377 }
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
378
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
379 final(a,b,c);
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
380 return c;
0047655db1aa jansson: import 2.7
David Demelier <markand@malikania.fr>
parents:
diff changeset
381 }