1 |
|
|
/* $OpenBSD: lhash.c,v 1.18 2016/11/08 20:20:06 miod Exp $ */ |
2 |
|
|
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 |
|
|
* All rights reserved. |
4 |
|
|
* |
5 |
|
|
* This package is an SSL implementation written |
6 |
|
|
* by Eric Young (eay@cryptsoft.com). |
7 |
|
|
* The implementation was written so as to conform with Netscapes SSL. |
8 |
|
|
* |
9 |
|
|
* This library is free for commercial and non-commercial use as long as |
10 |
|
|
* the following conditions are aheared to. The following conditions |
11 |
|
|
* apply to all code found in this distribution, be it the RC4, RSA, |
12 |
|
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 |
|
|
* included with this distribution is covered by the same copyright terms |
14 |
|
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 |
|
|
* |
16 |
|
|
* Copyright remains Eric Young's, and as such any Copyright notices in |
17 |
|
|
* the code are not to be removed. |
18 |
|
|
* If this package is used in a product, Eric Young should be given attribution |
19 |
|
|
* as the author of the parts of the library used. |
20 |
|
|
* This can be in the form of a textual message at program startup or |
21 |
|
|
* in documentation (online or textual) provided with the package. |
22 |
|
|
* |
23 |
|
|
* Redistribution and use in source and binary forms, with or without |
24 |
|
|
* modification, are permitted provided that the following conditions |
25 |
|
|
* are met: |
26 |
|
|
* 1. Redistributions of source code must retain the copyright |
27 |
|
|
* notice, this list of conditions and the following disclaimer. |
28 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
29 |
|
|
* notice, this list of conditions and the following disclaimer in the |
30 |
|
|
* documentation and/or other materials provided with the distribution. |
31 |
|
|
* 3. All advertising materials mentioning features or use of this software |
32 |
|
|
* must display the following acknowledgement: |
33 |
|
|
* "This product includes cryptographic software written by |
34 |
|
|
* Eric Young (eay@cryptsoft.com)" |
35 |
|
|
* The word 'cryptographic' can be left out if the rouines from the library |
36 |
|
|
* being used are not cryptographic related :-). |
37 |
|
|
* 4. If you include any Windows specific code (or a derivative thereof) from |
38 |
|
|
* the apps directory (application code) you must include an acknowledgement: |
39 |
|
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 |
|
|
* |
41 |
|
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 |
|
|
* SUCH DAMAGE. |
52 |
|
|
* |
53 |
|
|
* The licence and distribution terms for any publically available version or |
54 |
|
|
* derivative of this code cannot be changed. i.e. this code cannot simply be |
55 |
|
|
* copied and put under another distribution licence |
56 |
|
|
* [including the GNU Public Licence.] |
57 |
|
|
*/ |
58 |
|
|
|
59 |
|
|
/* Code for dynamic hash table routines |
60 |
|
|
* Author - Eric Young v 2.0 |
61 |
|
|
* |
62 |
|
|
* 2.2 eay - added #include "crypto.h" so the memory leak checking code is |
63 |
|
|
* present. eay 18-Jun-98 |
64 |
|
|
* |
65 |
|
|
* 2.1 eay - Added an 'error in last operation' flag. eay 6-May-98 |
66 |
|
|
* |
67 |
|
|
* 2.0 eay - Fixed a bug that occurred when using lh_delete |
68 |
|
|
* from inside lh_doall(). As entries were deleted, |
69 |
|
|
* the 'table' was 'contract()ed', making some entries |
70 |
|
|
* jump from the end of the table to the start, there by |
71 |
|
|
* skipping the lh_doall() processing. eay - 4/12/95 |
72 |
|
|
* |
73 |
|
|
* 1.9 eay - Fixed a memory leak in lh_free, the LHASH_NODEs |
74 |
|
|
* were not being free()ed. 21/11/95 |
75 |
|
|
* |
76 |
|
|
* 1.8 eay - Put the stats routines into a separate file, lh_stats.c |
77 |
|
|
* 19/09/95 |
78 |
|
|
* |
79 |
|
|
* 1.7 eay - Removed the fputs() for realloc failures - the code |
80 |
|
|
* should silently tolerate them. I have also fixed things |
81 |
|
|
* lint complained about 04/05/95 |
82 |
|
|
* |
83 |
|
|
* 1.6 eay - Fixed an invalid pointers in contract/expand 27/07/92 |
84 |
|
|
* |
85 |
|
|
* 1.5 eay - Fixed a misuse of realloc in expand 02/03/1992 |
86 |
|
|
* |
87 |
|
|
* 1.4 eay - Fixed lh_doall so the function can call lh_delete 28/05/91 |
88 |
|
|
* |
89 |
|
|
* 1.3 eay - Fixed a few lint problems 19/3/1991 |
90 |
|
|
* |
91 |
|
|
* 1.2 eay - Fixed lh_doall problem 13/3/1991 |
92 |
|
|
* |
93 |
|
|
* 1.1 eay - Added lh_doall |
94 |
|
|
* |
95 |
|
|
* 1.0 eay - First version |
96 |
|
|
*/ |
97 |
|
|
#include <stdio.h> |
98 |
|
|
#include <string.h> |
99 |
|
|
#include <stdlib.h> |
100 |
|
|
|
101 |
|
|
#include <openssl/opensslconf.h> |
102 |
|
|
|
103 |
|
|
#include <openssl/crypto.h> |
104 |
|
|
#include <openssl/lhash.h> |
105 |
|
|
|
106 |
|
|
#undef MIN_NODES |
107 |
|
|
#define MIN_NODES 16 |
108 |
|
|
#define UP_LOAD (2*LH_LOAD_MULT) /* load times 256 (default 2) */ |
109 |
|
|
#define DOWN_LOAD (LH_LOAD_MULT) /* load times 256 (default 1) */ |
110 |
|
|
|
111 |
|
|
static void expand(_LHASH *lh); |
112 |
|
|
static void contract(_LHASH *lh); |
113 |
|
|
static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash); |
114 |
|
|
|
115 |
|
|
_LHASH * |
116 |
|
|
lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c) |
117 |
|
|
{ |
118 |
|
|
_LHASH *ret; |
119 |
|
|
int i; |
120 |
|
|
|
121 |
✓✗ |
31286 |
if ((ret = malloc(sizeof(_LHASH))) == NULL) |
122 |
|
|
goto err0; |
123 |
✓✗ |
15643 |
if ((ret->b = reallocarray(NULL, MIN_NODES, sizeof(LHASH_NODE *))) == NULL) |
124 |
|
|
goto err1; |
125 |
✓✓ |
531862 |
for (i = 0; i < MIN_NODES; i++) |
126 |
|
250288 |
ret->b[i] = NULL; |
127 |
|
15643 |
ret->comp = ((c == NULL) ? (LHASH_COMP_FN_TYPE)strcmp : c); |
128 |
|
15643 |
ret->hash = ((h == NULL) ? (LHASH_HASH_FN_TYPE)lh_strhash : h); |
129 |
|
15643 |
ret->num_nodes = MIN_NODES / 2; |
130 |
|
15643 |
ret->num_alloc_nodes = MIN_NODES; |
131 |
|
15643 |
ret->p = 0; |
132 |
|
15643 |
ret->pmax = MIN_NODES / 2; |
133 |
|
15643 |
ret->up_load = UP_LOAD; |
134 |
|
15643 |
ret->down_load = DOWN_LOAD; |
135 |
|
15643 |
ret->num_items = 0; |
136 |
|
|
|
137 |
|
15643 |
ret->num_expands = 0; |
138 |
|
15643 |
ret->num_expand_reallocs = 0; |
139 |
|
15643 |
ret->num_contracts = 0; |
140 |
|
15643 |
ret->num_contract_reallocs = 0; |
141 |
|
15643 |
ret->num_hash_calls = 0; |
142 |
|
15643 |
ret->num_comp_calls = 0; |
143 |
|
15643 |
ret->num_insert = 0; |
144 |
|
15643 |
ret->num_replace = 0; |
145 |
|
15643 |
ret->num_delete = 0; |
146 |
|
15643 |
ret->num_no_delete = 0; |
147 |
|
15643 |
ret->num_retrieve = 0; |
148 |
|
15643 |
ret->num_retrieve_miss = 0; |
149 |
|
15643 |
ret->num_hash_comps = 0; |
150 |
|
|
|
151 |
|
15643 |
ret->error = 0; |
152 |
|
15643 |
return (ret); |
153 |
|
|
|
154 |
|
|
err1: |
155 |
|
|
free(ret); |
156 |
|
|
err0: |
157 |
|
|
return (NULL); |
158 |
|
15643 |
} |
159 |
|
|
|
160 |
|
|
void |
161 |
|
|
lh_free(_LHASH *lh) |
162 |
|
|
{ |
163 |
|
|
unsigned int i; |
164 |
|
|
LHASH_NODE *n, *nn; |
165 |
|
|
|
166 |
✗✓ |
19808 |
if (lh == NULL) |
167 |
|
|
return; |
168 |
|
|
|
169 |
✓✓ |
2996986 |
for (i = 0; i < lh->num_nodes; i++) { |
170 |
|
1488589 |
n = lh->b[i]; |
171 |
✓✓ |
8004420 |
while (n != NULL) { |
172 |
|
2513621 |
nn = n->next; |
173 |
|
2513621 |
free(n); |
174 |
|
|
n = nn; |
175 |
|
|
} |
176 |
|
|
} |
177 |
|
9904 |
free(lh->b); |
178 |
|
9904 |
free(lh); |
179 |
|
19808 |
} |
180 |
|
|
|
181 |
|
|
void * |
182 |
|
|
lh_insert(_LHASH *lh, void *data) |
183 |
|
|
{ |
184 |
|
73251100 |
unsigned long hash; |
185 |
|
|
LHASH_NODE *nn, **rn; |
186 |
|
|
void *ret; |
187 |
|
|
|
188 |
|
36625550 |
lh->error = 0; |
189 |
✓✓ |
36625550 |
if (lh->up_load <= (lh->num_items * LH_LOAD_MULT / lh->num_nodes)) |
190 |
|
2450603 |
expand(lh); |
191 |
|
|
|
192 |
|
36625550 |
rn = getrn(lh, data, &hash); |
193 |
|
|
|
194 |
✓✓ |
36625550 |
if (*rn == NULL) { |
195 |
✗✓ |
5029898 |
if ((nn = malloc(sizeof(LHASH_NODE))) == NULL) { |
196 |
|
|
lh->error++; |
197 |
|
|
return (NULL); |
198 |
|
|
} |
199 |
|
5029898 |
nn->data = data; |
200 |
|
5029898 |
nn->next = NULL; |
201 |
|
|
#ifndef OPENSSL_NO_HASH_COMP |
202 |
|
5029898 |
nn->hash = hash; |
203 |
|
|
#endif |
204 |
|
5029898 |
*rn = nn; |
205 |
|
|
ret = NULL; |
206 |
|
5029898 |
lh->num_insert++; |
207 |
|
|
lh->num_items++; |
208 |
|
5029898 |
} |
209 |
|
|
else /* replace same key */ |
210 |
|
|
{ |
211 |
|
31595652 |
ret = (*rn)->data; |
212 |
|
31595652 |
(*rn)->data = data; |
213 |
|
31595652 |
lh->num_replace++; |
214 |
|
|
} |
215 |
|
36625550 |
return (ret); |
216 |
|
36625550 |
} |
217 |
|
|
|
218 |
|
|
void * |
219 |
|
|
lh_delete(_LHASH *lh, const void *data) |
220 |
|
|
{ |
221 |
|
783042 |
unsigned long hash; |
222 |
|
|
LHASH_NODE *nn, **rn; |
223 |
|
|
void *ret; |
224 |
|
|
|
225 |
|
391521 |
lh->error = 0; |
226 |
|
391521 |
rn = getrn(lh, data, &hash); |
227 |
|
|
|
228 |
✗✓ |
391521 |
if (*rn == NULL) { |
229 |
|
|
lh->num_no_delete++; |
230 |
|
|
return (NULL); |
231 |
|
|
} else { |
232 |
|
|
nn= *rn; |
233 |
|
391521 |
*rn = nn->next; |
234 |
|
391521 |
ret = nn->data; |
235 |
|
391521 |
free(nn); |
236 |
|
391521 |
lh->num_delete++; |
237 |
|
|
} |
238 |
|
|
|
239 |
|
391521 |
lh->num_items--; |
240 |
✓✓✓✓
|
774198 |
if ((lh->num_nodes > MIN_NODES) && |
241 |
|
382677 |
(lh->down_load >= (lh->num_items * LH_LOAD_MULT / lh->num_nodes))) |
242 |
|
1568 |
contract(lh); |
243 |
|
|
|
244 |
|
391521 |
return (ret); |
245 |
|
391521 |
} |
246 |
|
|
|
247 |
|
|
void * |
248 |
|
|
lh_retrieve(_LHASH *lh, const void *data) |
249 |
|
|
{ |
250 |
|
729018 |
unsigned long hash; |
251 |
|
|
LHASH_NODE **rn; |
252 |
|
|
void *ret; |
253 |
|
|
|
254 |
|
364509 |
lh->error = 0; |
255 |
|
364509 |
rn = getrn(lh, data, &hash); |
256 |
|
|
|
257 |
✓✓ |
364509 |
if (*rn == NULL) { |
258 |
|
93923 |
lh->num_retrieve_miss++; |
259 |
|
93923 |
return (NULL); |
260 |
|
|
} else { |
261 |
|
270586 |
ret = (*rn)->data; |
262 |
|
270586 |
lh->num_retrieve++; |
263 |
|
|
} |
264 |
|
270586 |
return (ret); |
265 |
|
364509 |
} |
266 |
|
|
|
267 |
|
|
static void |
268 |
|
|
doall_util_fn(_LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func, |
269 |
|
|
LHASH_DOALL_ARG_FN_TYPE func_arg, void *arg) |
270 |
|
|
{ |
271 |
|
|
int i; |
272 |
|
|
LHASH_NODE *a, *n; |
273 |
|
|
|
274 |
✓✓ |
20174 |
if (lh == NULL) |
275 |
|
28 |
return; |
276 |
|
|
|
277 |
|
|
/* reverse the order so we search from 'top to bottom' |
278 |
|
|
* We were having memory leaks otherwise */ |
279 |
✓✓ |
1261474 |
for (i = lh->num_nodes - 1; i >= 0; i--) { |
280 |
|
620678 |
a = lh->b[i]; |
281 |
✓✓ |
2234776 |
while (a != NULL) { |
282 |
|
|
/* 28/05/91 - eay - n added so items can be deleted |
283 |
|
|
* via lh_doall */ |
284 |
|
|
/* 22/05/08 - ben - eh? since a is not passed, |
285 |
|
|
* this should not be needed */ |
286 |
|
496710 |
n = a->next; |
287 |
✓✓ |
496710 |
if (use_arg) |
288 |
|
20974 |
func_arg(a->data, arg); |
289 |
|
|
else |
290 |
|
475736 |
func(a->data); |
291 |
|
|
a = n; |
292 |
|
|
} |
293 |
|
|
} |
294 |
|
20146 |
} |
295 |
|
|
|
296 |
|
|
void |
297 |
|
|
lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func) |
298 |
|
|
{ |
299 |
|
15696 |
doall_util_fn(lh, 0, func, (LHASH_DOALL_ARG_FN_TYPE)0, NULL); |
300 |
|
7848 |
} |
301 |
|
|
|
302 |
|
|
void |
303 |
|
|
lh_doall_arg(_LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg) |
304 |
|
|
{ |
305 |
|
4478 |
doall_util_fn(lh, 1, (LHASH_DOALL_FN_TYPE)0, func, arg); |
306 |
|
2239 |
} |
307 |
|
|
|
308 |
|
|
static void |
309 |
|
|
expand(_LHASH *lh) |
310 |
|
|
{ |
311 |
|
|
LHASH_NODE **n, **n1, **n2, *np; |
312 |
|
|
unsigned int p, i, j; |
313 |
|
|
unsigned long hash, nni; |
314 |
|
|
|
315 |
|
4901206 |
lh->num_nodes++; |
316 |
|
2450603 |
lh->num_expands++; |
317 |
|
2450603 |
p = (int)lh->p++; |
318 |
|
2450603 |
n1 = &(lh->b[p]); |
319 |
|
2450603 |
n2 = &(lh->b[p + (int)lh->pmax]); |
320 |
|
2450603 |
*n2 = NULL; /* 27/07/92 - eay - undefined pointer bug */ |
321 |
|
2450603 |
nni = lh->num_alloc_nodes; |
322 |
|
|
|
323 |
✓✓ |
21949368 |
for (np = *n1; np != NULL; ) { |
324 |
|
|
#ifndef OPENSSL_NO_HASH_COMP |
325 |
|
8524081 |
hash = np->hash; |
326 |
|
|
#else |
327 |
|
|
hash = lh->hash(np->data); |
328 |
|
|
lh->num_hash_calls++; |
329 |
|
|
#endif |
330 |
✓✓ |
8524081 |
if ((hash % nni) != p) { /* move it */ |
331 |
|
1525686 |
*n1 = (*n1)->next; |
332 |
|
1525686 |
np->next= *n2; |
333 |
|
1525686 |
*n2 = np; |
334 |
|
1525686 |
} else |
335 |
|
|
n1 = &((*n1)->next); |
336 |
|
8524081 |
np= *n1; |
337 |
|
|
} |
338 |
|
|
|
339 |
✓✓ |
2450603 |
if ((lh->p) >= lh->pmax) { |
340 |
|
28874 |
j = (int)lh->num_alloc_nodes * 2; |
341 |
|
28874 |
n = reallocarray(lh->b, j, sizeof(LHASH_NODE *)); |
342 |
✗✓ |
28874 |
if (n == NULL) { |
343 |
|
|
/* fputs("realloc error in lhash", stderr); */ |
344 |
|
|
lh->error++; |
345 |
|
|
lh->p = 0; |
346 |
|
|
return; |
347 |
|
|
} |
348 |
|
|
/* else */ |
349 |
✓✓ |
6832948 |
for (i = (int)lh->num_alloc_nodes; i < j; i++)/* 26/02/92 eay */ |
350 |
|
3387600 |
n[i] = NULL; /* 02/03/92 eay */ |
351 |
|
28874 |
lh->pmax = lh->num_alloc_nodes; |
352 |
|
28874 |
lh->num_alloc_nodes = j; |
353 |
|
28874 |
lh->num_expand_reallocs++; |
354 |
|
28874 |
lh->p = 0; |
355 |
|
28874 |
lh->b = n; |
356 |
|
28874 |
} |
357 |
|
4901206 |
} |
358 |
|
|
|
359 |
|
|
static void |
360 |
|
|
contract(_LHASH *lh) |
361 |
|
|
{ |
362 |
|
|
LHASH_NODE **n, *n1, *np; |
363 |
|
|
|
364 |
|
3136 |
np = lh->b[lh->p + lh->pmax - 1]; |
365 |
|
1568 |
lh->b[lh->p+lh->pmax - 1] = NULL; /* 24/07-92 - eay - weird but :-( */ |
366 |
✗✓ |
1568 |
if (lh->p == 0) { |
367 |
|
|
n = reallocarray(lh->b, lh->pmax, sizeof(LHASH_NODE *)); |
368 |
|
|
if (n == NULL) { |
369 |
|
|
/* fputs("realloc error in lhash", stderr); */ |
370 |
|
|
lh->error++; |
371 |
|
|
return; |
372 |
|
|
} |
373 |
|
|
lh->num_contract_reallocs++; |
374 |
|
|
lh->num_alloc_nodes /= 2; |
375 |
|
|
lh->pmax /= 2; |
376 |
|
|
lh->p = lh->pmax - 1; |
377 |
|
|
lh->b = n; |
378 |
|
|
} else |
379 |
|
1568 |
lh->p--; |
380 |
|
|
|
381 |
|
1568 |
lh->num_nodes--; |
382 |
|
1568 |
lh->num_contracts++; |
383 |
|
|
|
384 |
|
1568 |
n1 = lh->b[(int)lh->p]; |
385 |
✓✗ |
1568 |
if (n1 == NULL) |
386 |
|
1568 |
lh->b[(int)lh->p] = np; |
387 |
|
|
else { |
388 |
|
|
while (n1->next != NULL) |
389 |
|
|
n1 = n1->next; |
390 |
|
|
n1->next = np; |
391 |
|
|
} |
392 |
|
3136 |
} |
393 |
|
|
|
394 |
|
|
static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash) |
395 |
|
|
{ |
396 |
|
|
LHASH_NODE **ret, *n1; |
397 |
|
|
unsigned long hash, nn; |
398 |
|
|
LHASH_COMP_FN_TYPE cf; |
399 |
|
|
|
400 |
|
74763160 |
hash = (*(lh->hash))(data); |
401 |
|
37381580 |
lh->num_hash_calls++; |
402 |
|
37381580 |
*rhash = hash; |
403 |
|
|
|
404 |
|
37381580 |
nn = hash % lh->pmax; |
405 |
✓✓ |
37381580 |
if (nn < lh->p) |
406 |
|
16141570 |
nn = hash % lh->num_alloc_nodes; |
407 |
|
|
|
408 |
|
37381580 |
cf = lh->comp; |
409 |
|
37381580 |
ret = &(lh->b[(int)nn]); |
410 |
✓✓ |
142659248 |
for (n1 = *ret; n1 != NULL; n1 = n1->next) { |
411 |
|
|
#ifndef OPENSSL_NO_HASH_COMP |
412 |
|
66205803 |
lh->num_hash_comps++; |
413 |
✓✓ |
66205803 |
if (n1->hash != hash) { |
414 |
|
31842301 |
ret = &(n1->next); |
415 |
|
31842301 |
continue; |
416 |
|
|
} |
417 |
|
|
#endif |
418 |
|
34363502 |
lh->num_comp_calls++; |
419 |
✓✓ |
34363502 |
if (cf(n1->data, data) == 0) |
420 |
|
|
break; |
421 |
|
2105743 |
ret = &(n1->next); |
422 |
|
2105743 |
} |
423 |
|
37381580 |
return (ret); |
424 |
|
|
} |
425 |
|
|
|
426 |
|
|
/* The following hash seems to work very well on normal text strings |
427 |
|
|
* no collisions on /usr/dict/words and it distributes on %2^n quite |
428 |
|
|
* well, not as good as MD5, but still good. |
429 |
|
|
*/ |
430 |
|
|
unsigned long |
431 |
|
|
lh_strhash(const char *c) |
432 |
|
|
{ |
433 |
|
|
unsigned long ret = 0; |
434 |
|
|
unsigned long n, v; |
435 |
|
|
unsigned int r; |
436 |
|
|
|
437 |
✓✓✗✓
|
3969692 |
if (c == NULL || *c == '\0') |
438 |
|
6511 |
return ret; |
439 |
|
|
|
440 |
|
|
n = 0x100; |
441 |
✓✓ |
30028542 |
while (*c) { |
442 |
|
13695381 |
v = n | *c; |
443 |
|
13695381 |
n += 0x100; |
444 |
✓✓ |
13695381 |
if ((r = ((v >> 2) ^ v) & 0x0f) != 0) |
445 |
|
13693167 |
ret = (ret << r) | (ret >> (32 - r)); |
446 |
|
13695381 |
ret &= 0xFFFFFFFFUL; |
447 |
|
13695381 |
ret ^= v * v; |
448 |
|
13695381 |
c++; |
449 |
|
|
} |
450 |
|
1318890 |
return (ret >> 16) ^ ret; |
451 |
|
1325401 |
} |
452 |
|
|
|
453 |
|
|
unsigned long |
454 |
|
|
lh_num_items(const _LHASH *lh) |
455 |
|
|
{ |
456 |
✓✗ |
6288 |
return lh ? lh->num_items : 0; |
457 |
|
|
} |