1 | /* |
2 | +----------------------------------------------------------------------+ |
3 | | PHP Version 5 | |
4 | +----------------------------------------------------------------------+ |
5 | | Copyright (c) 1997-2015 The PHP Group | |
6 | +----------------------------------------------------------------------+ |
7 | | This source file is subject to version 3.01 of the PHP license, | |
8 | | that is bundled with this package in the file LICENSE, and is | |
9 | | available through the world-wide-web at the following url: | |
10 | | http://www.php.net/license/3_01.txt | |
11 | | If you did not receive a copy of the PHP license and are unable to | |
12 | | obtain it through the world-wide-web, please send a note to | |
13 | | license@php.net so we can mail you a copy immediately. | |
14 | +----------------------------------------------------------------------+ |
15 | | Author: Michael Maclean <mgdm@php.net> | |
16 | +----------------------------------------------------------------------+ |
17 | */ |
18 | |
19 | /* $Id$ */ |
20 | |
21 | /* Based on the public domain algorithm found at |
22 | http://www.isthe.com/chongo/tech/comp/fnv/index.html */ |
23 | |
24 | #include "php_hash.h" |
25 | #include "php_hash_fnv.h" |
26 | |
27 | const php_hash_ops php_hash_fnv132_ops = { |
28 | (php_hash_init_func_t) PHP_FNV132Init, |
29 | (php_hash_update_func_t) PHP_FNV132Update, |
30 | (php_hash_final_func_t) PHP_FNV132Final, |
31 | (php_hash_copy_func_t) php_hash_copy, |
32 | 4, |
33 | 4, |
34 | sizeof(PHP_FNV132_CTX) |
35 | }; |
36 | |
37 | const php_hash_ops php_hash_fnv1a32_ops = { |
38 | (php_hash_init_func_t) PHP_FNV132Init, |
39 | (php_hash_update_func_t) PHP_FNV1a32Update, |
40 | (php_hash_final_func_t) PHP_FNV132Final, |
41 | (php_hash_copy_func_t) php_hash_copy, |
42 | 4, |
43 | 4, |
44 | sizeof(PHP_FNV132_CTX) |
45 | }; |
46 | |
47 | const php_hash_ops php_hash_fnv164_ops = { |
48 | (php_hash_init_func_t) PHP_FNV164Init, |
49 | (php_hash_update_func_t) PHP_FNV164Update, |
50 | (php_hash_final_func_t) PHP_FNV164Final, |
51 | (php_hash_copy_func_t) php_hash_copy, |
52 | 8, |
53 | 4, |
54 | sizeof(PHP_FNV164_CTX) |
55 | }; |
56 | |
57 | const php_hash_ops php_hash_fnv1a64_ops = { |
58 | (php_hash_init_func_t) PHP_FNV164Init, |
59 | (php_hash_update_func_t) PHP_FNV1a64Update, |
60 | (php_hash_final_func_t) PHP_FNV164Final, |
61 | (php_hash_copy_func_t) php_hash_copy, |
62 | 8, |
63 | 4, |
64 | sizeof(PHP_FNV164_CTX) |
65 | }; |
66 | |
67 | /* {{{ PHP_FNV132Init |
68 | * 32-bit FNV-1 hash initialisation |
69 | */ |
70 | PHP_HASH_API void PHP_FNV132Init(PHP_FNV132_CTX *context) |
71 | { |
72 | context->state = PHP_FNV1_32_INIT; |
73 | } |
74 | /* }}} */ |
75 | |
76 | PHP_HASH_API void PHP_FNV132Update(PHP_FNV132_CTX *context, const unsigned char *input, |
77 | unsigned int inputLen) |
78 | { |
79 | context->state = fnv_32_buf((void *)input, inputLen, context->state, 0); |
80 | } |
81 | |
82 | PHP_HASH_API void PHP_FNV1a32Update(PHP_FNV132_CTX *context, const unsigned char *input, |
83 | unsigned int inputLen) |
84 | { |
85 | context->state = fnv_32_buf((void *)input, inputLen, context->state, 1); |
86 | } |
87 | |
88 | PHP_HASH_API void PHP_FNV132Final(unsigned char digest[4], PHP_FNV132_CTX * context) |
89 | { |
90 | #ifdef WORDS_BIGENDIAN |
91 | memcpy(digest, &context->state, 4); |
92 | #else |
93 | int i = 0; |
94 | unsigned char *c = (unsigned char *) &context->state; |
95 | |
96 | for (i = 0; i < 4; i++) { |
97 | digest[i] = c[3 - i]; |
98 | } |
99 | #endif |
100 | } |
101 | |
102 | /* {{{ PHP_FNV164Init |
103 | * 64-bit FNV-1 hash initialisation |
104 | */ |
105 | PHP_HASH_API void PHP_FNV164Init(PHP_FNV164_CTX *context) |
106 | { |
107 | context->state = PHP_FNV1_64_INIT; |
108 | } |
109 | /* }}} */ |
110 | |
111 | PHP_HASH_API void PHP_FNV164Update(PHP_FNV164_CTX *context, const unsigned char *input, |
112 | unsigned int inputLen) |
113 | { |
114 | context->state = fnv_64_buf((void *)input, inputLen, context->state, 0); |
115 | } |
116 | |
117 | PHP_HASH_API void PHP_FNV1a64Update(PHP_FNV164_CTX *context, const unsigned char *input, |
118 | unsigned int inputLen) |
119 | { |
120 | context->state = fnv_64_buf((void *)input, inputLen, context->state, 1); |
121 | } |
122 | |
123 | PHP_HASH_API void PHP_FNV164Final(unsigned char digest[8], PHP_FNV164_CTX * context) |
124 | { |
125 | #ifdef WORDS_BIGENDIAN |
126 | memcpy(digest, &context->state, 8); |
127 | #else |
128 | int i = 0; |
129 | unsigned char *c = (unsigned char *) &context->state; |
130 | |
131 | for (i = 0; i < 8; i++) { |
132 | digest[i] = c[7 - i]; |
133 | } |
134 | #endif |
135 | } |
136 | |
137 | |
138 | /* |
139 | * fnv_32_buf - perform a 32 bit Fowler/Noll/Vo hash on a buffer |
140 | * |
141 | * input: |
142 | * buf - start of buffer to hash |
143 | * len - length of buffer in octets |
144 | * hval - previous hash value or 0 if first call |
145 | * alternate - if > 0 use the alternate version |
146 | * |
147 | * returns: |
148 | * 32 bit hash as a static hash type |
149 | */ |
150 | static php_hash_uint32 |
151 | fnv_32_buf(void *buf, size_t len, php_hash_uint32 hval, int alternate) |
152 | { |
153 | unsigned char *bp = (unsigned char *)buf; /* start of buffer */ |
154 | unsigned char *be = bp + len; /* beyond end of buffer */ |
155 | |
156 | /* |
157 | * FNV-1 hash each octet in the buffer |
158 | */ |
159 | while (bp < be) { |
160 | |
161 | if (alternate == 0) { |
162 | /* multiply by the 32 bit FNV magic prime mod 2^32 */ |
163 | hval *= PHP_FNV_32_PRIME; |
164 | |
165 | /* xor the bottom with the current octet */ |
166 | hval ^= (php_hash_uint32)*bp++; |
167 | } else { |
168 | /* xor the bottom with the current octet */ |
169 | hval ^= (php_hash_uint32)*bp++; |
170 | |
171 | /* multiply by the 32 bit FNV magic prime mod 2^32 */ |
172 | hval *= PHP_FNV_32_PRIME; |
173 | } |
174 | } |
175 | |
176 | /* return our new hash value */ |
177 | return hval; |
178 | } |
179 | |
180 | /* |
181 | * fnv_64_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer |
182 | * |
183 | * input: |
184 | * buf - start of buffer to hash |
185 | * len - length of buffer in octets |
186 | * hval - previous hash value or 0 if first call |
187 | * alternate - if > 0 use the alternate version |
188 | * |
189 | * returns: |
190 | * 64 bit hash as a static hash type |
191 | */ |
192 | static php_hash_uint64 |
193 | fnv_64_buf(void *buf, size_t len, php_hash_uint64 hval, int alternate) |
194 | { |
195 | unsigned char *bp = (unsigned char *)buf; /* start of buffer */ |
196 | unsigned char *be = bp + len; /* beyond end of buffer */ |
197 | |
198 | /* |
199 | * FNV-1 hash each octet of the buffer |
200 | */ |
201 | while (bp < be) { |
202 | |
203 | if (alternate == 0) { |
204 | /* multiply by the 64 bit FNV magic prime mod 2^64 */ |
205 | hval *= PHP_FNV_64_PRIME; |
206 | |
207 | /* xor the bottom with the current octet */ |
208 | hval ^= (php_hash_uint64)*bp++; |
209 | } else { |
210 | /* xor the bottom with the current octet */ |
211 | hval ^= (php_hash_uint64)*bp++; |
212 | |
213 | /* multiply by the 64 bit FNV magic prime mod 2^64 */ |
214 | hval *= PHP_FNV_64_PRIME; |
215 | } |
216 | } |
217 | |
218 | /* return our new hash value */ |
219 | return hval; |
220 | } |
221 | |
222 | /* |
223 | * Local variables: |
224 | * tab-width: 4 |
225 | * c-basic-offset: 4 |
226 | * End: |
227 | * vim600: noet sw=4 ts=4 fdm=marker |
228 | * vim<600: noet sw=4 ts=4 |
229 | */ |
230 | |