OLD | NEW |
1 /* crypto/lhash/lhash.c */ | 1 /* crypto/lhash/lhash.c */ |
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 * All rights reserved. | 3 * All rights reserved. |
4 * | 4 * |
5 * This package is an SSL implementation written | 5 * This package is an SSL implementation written |
6 * by Eric Young (eay@cryptsoft.com). | 6 * by Eric Young (eay@cryptsoft.com). |
7 * The implementation was written so as to conform with Netscapes SSL. | 7 * The implementation was written so as to conform with Netscapes SSL. |
8 * | 8 * |
9 * This library is free for commercial and non-commercial use as long as | 9 * This library is free for commercial and non-commercial use as long as |
10 * the following conditions are aheared to. The following conditions | 10 * the following conditions are aheared to. The following conditions |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 #include <openssl/crypto.h> | 100 #include <openssl/crypto.h> |
101 #include <openssl/lhash.h> | 101 #include <openssl/lhash.h> |
102 | 102 |
103 const char lh_version[]="lhash" OPENSSL_VERSION_PTEXT; | 103 const char lh_version[]="lhash" OPENSSL_VERSION_PTEXT; |
104 | 104 |
105 #undef MIN_NODES | 105 #undef MIN_NODES |
106 #define MIN_NODES 16 | 106 #define MIN_NODES 16 |
107 #define UP_LOAD (2*LH_LOAD_MULT) /* load times 256 (default 2) */ | 107 #define UP_LOAD (2*LH_LOAD_MULT) /* load times 256 (default 2) */ |
108 #define DOWN_LOAD (LH_LOAD_MULT) /* load times 256 (default 1) */ | 108 #define DOWN_LOAD (LH_LOAD_MULT) /* load times 256 (default 1) */ |
109 | 109 |
110 static void expand(LHASH *lh); | 110 static void expand(_LHASH *lh); |
111 static void contract(LHASH *lh); | 111 static void contract(_LHASH *lh); |
112 static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash); | 112 static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash); |
113 | 113 |
114 LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c) | 114 _LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c) |
115 { | 115 { |
116 » LHASH *ret; | 116 » _LHASH *ret; |
117 int i; | 117 int i; |
118 | 118 |
119 » if ((ret=(LHASH *)OPENSSL_malloc(sizeof(LHASH))) == NULL) | 119 » if ((ret=OPENSSL_malloc(sizeof(_LHASH))) == NULL) |
120 goto err0; | 120 goto err0; |
121 » if ((ret->b=(LHASH_NODE **)OPENSSL_malloc(sizeof(LHASH_NODE *)*MIN_NODES
)) == NULL) | 121 » if ((ret->b=OPENSSL_malloc(sizeof(LHASH_NODE *)*MIN_NODES)) == NULL) |
122 goto err1; | 122 goto err1; |
123 for (i=0; i<MIN_NODES; i++) | 123 for (i=0; i<MIN_NODES; i++) |
124 ret->b[i]=NULL; | 124 ret->b[i]=NULL; |
125 ret->comp=((c == NULL)?(LHASH_COMP_FN_TYPE)strcmp:c); | 125 ret->comp=((c == NULL)?(LHASH_COMP_FN_TYPE)strcmp:c); |
126 ret->hash=((h == NULL)?(LHASH_HASH_FN_TYPE)lh_strhash:h); | 126 ret->hash=((h == NULL)?(LHASH_HASH_FN_TYPE)lh_strhash:h); |
127 ret->num_nodes=MIN_NODES/2; | 127 ret->num_nodes=MIN_NODES/2; |
128 ret->num_alloc_nodes=MIN_NODES; | 128 ret->num_alloc_nodes=MIN_NODES; |
129 ret->p=0; | 129 ret->p=0; |
130 ret->pmax=MIN_NODES/2; | 130 ret->pmax=MIN_NODES/2; |
131 ret->up_load=UP_LOAD; | 131 ret->up_load=UP_LOAD; |
(...skipping 15 matching lines...) Expand all Loading... |
147 ret->num_hash_comps=0; | 147 ret->num_hash_comps=0; |
148 | 148 |
149 ret->error=0; | 149 ret->error=0; |
150 return(ret); | 150 return(ret); |
151 err1: | 151 err1: |
152 OPENSSL_free(ret); | 152 OPENSSL_free(ret); |
153 err0: | 153 err0: |
154 return(NULL); | 154 return(NULL); |
155 } | 155 } |
156 | 156 |
157 void lh_free(LHASH *lh) | 157 void lh_free(_LHASH *lh) |
158 { | 158 { |
159 unsigned int i; | 159 unsigned int i; |
160 LHASH_NODE *n,*nn; | 160 LHASH_NODE *n,*nn; |
161 | 161 |
162 if (lh == NULL) | 162 if (lh == NULL) |
163 return; | 163 return; |
164 | 164 |
165 for (i=0; i<lh->num_nodes; i++) | 165 for (i=0; i<lh->num_nodes; i++) |
166 { | 166 { |
167 n=lh->b[i]; | 167 n=lh->b[i]; |
168 while (n != NULL) | 168 while (n != NULL) |
169 { | 169 { |
170 nn=n->next; | 170 nn=n->next; |
171 OPENSSL_free(n); | 171 OPENSSL_free(n); |
172 n=nn; | 172 n=nn; |
173 } | 173 } |
174 } | 174 } |
175 OPENSSL_free(lh->b); | 175 OPENSSL_free(lh->b); |
176 OPENSSL_free(lh); | 176 OPENSSL_free(lh); |
177 } | 177 } |
178 | 178 |
179 void *lh_insert(LHASH *lh, void *data) | 179 void *lh_insert(_LHASH *lh, void *data) |
180 { | 180 { |
181 unsigned long hash; | 181 unsigned long hash; |
182 LHASH_NODE *nn,**rn; | 182 LHASH_NODE *nn,**rn; |
183 void *ret; | 183 void *ret; |
184 | 184 |
185 lh->error=0; | 185 lh->error=0; |
186 if (lh->up_load <= (lh->num_items*LH_LOAD_MULT/lh->num_nodes)) | 186 if (lh->up_load <= (lh->num_items*LH_LOAD_MULT/lh->num_nodes)) |
187 expand(lh); | 187 expand(lh); |
188 | 188 |
189 rn=getrn(lh,data,&hash); | 189 rn=getrn(lh,data,&hash); |
(...skipping 17 matching lines...) Expand all Loading... |
207 } | 207 } |
208 else /* replace same key */ | 208 else /* replace same key */ |
209 { | 209 { |
210 ret= (*rn)->data; | 210 ret= (*rn)->data; |
211 (*rn)->data=data; | 211 (*rn)->data=data; |
212 lh->num_replace++; | 212 lh->num_replace++; |
213 } | 213 } |
214 return(ret); | 214 return(ret); |
215 } | 215 } |
216 | 216 |
217 void *lh_delete(LHASH *lh, const void *data) | 217 void *lh_delete(_LHASH *lh, const void *data) |
218 { | 218 { |
219 unsigned long hash; | 219 unsigned long hash; |
220 LHASH_NODE *nn,**rn; | 220 LHASH_NODE *nn,**rn; |
221 void *ret; | 221 void *ret; |
222 | 222 |
223 lh->error=0; | 223 lh->error=0; |
224 rn=getrn(lh,data,&hash); | 224 rn=getrn(lh,data,&hash); |
225 | 225 |
226 if (*rn == NULL) | 226 if (*rn == NULL) |
227 { | 227 { |
(...skipping 10 matching lines...) Expand all Loading... |
238 } | 238 } |
239 | 239 |
240 lh->num_items--; | 240 lh->num_items--; |
241 if ((lh->num_nodes > MIN_NODES) && | 241 if ((lh->num_nodes > MIN_NODES) && |
242 (lh->down_load >= (lh->num_items*LH_LOAD_MULT/lh->num_nodes))) | 242 (lh->down_load >= (lh->num_items*LH_LOAD_MULT/lh->num_nodes))) |
243 contract(lh); | 243 contract(lh); |
244 | 244 |
245 return(ret); | 245 return(ret); |
246 } | 246 } |
247 | 247 |
248 void *lh_retrieve(LHASH *lh, const void *data) | 248 void *lh_retrieve(_LHASH *lh, const void *data) |
249 { | 249 { |
250 unsigned long hash; | 250 unsigned long hash; |
251 LHASH_NODE **rn; | 251 LHASH_NODE **rn; |
252 void *ret; | 252 void *ret; |
253 | 253 |
254 lh->error=0; | 254 lh->error=0; |
255 rn=getrn(lh,data,&hash); | 255 rn=getrn(lh,data,&hash); |
256 | 256 |
257 if (*rn == NULL) | 257 if (*rn == NULL) |
258 { | 258 { |
259 lh->num_retrieve_miss++; | 259 lh->num_retrieve_miss++; |
260 return(NULL); | 260 return(NULL); |
261 } | 261 } |
262 else | 262 else |
263 { | 263 { |
264 ret= (*rn)->data; | 264 ret= (*rn)->data; |
265 lh->num_retrieve++; | 265 lh->num_retrieve++; |
266 } | 266 } |
267 return(ret); | 267 return(ret); |
268 } | 268 } |
269 | 269 |
270 static void doall_util_fn(LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func, | 270 static void doall_util_fn(_LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func, |
271 LHASH_DOALL_ARG_FN_TYPE func_arg, void *arg) | 271 LHASH_DOALL_ARG_FN_TYPE func_arg, void *arg) |
272 { | 272 { |
273 int i; | 273 int i; |
274 LHASH_NODE *a,*n; | 274 LHASH_NODE *a,*n; |
275 | 275 |
| 276 if (lh == NULL) |
| 277 return; |
| 278 |
276 /* reverse the order so we search from 'top to bottom' | 279 /* reverse the order so we search from 'top to bottom' |
277 * We were having memory leaks otherwise */ | 280 * We were having memory leaks otherwise */ |
278 for (i=lh->num_nodes-1; i>=0; i--) | 281 for (i=lh->num_nodes-1; i>=0; i--) |
279 { | 282 { |
280 a=lh->b[i]; | 283 a=lh->b[i]; |
281 while (a != NULL) | 284 while (a != NULL) |
282 { | 285 { |
283 /* 28/05/91 - eay - n added so items can be deleted | 286 /* 28/05/91 - eay - n added so items can be deleted |
284 * via lh_doall */ | 287 * via lh_doall */ |
| 288 /* 22/05/08 - ben - eh? since a is not passed, |
| 289 * this should not be needed */ |
285 n=a->next; | 290 n=a->next; |
286 if(use_arg) | 291 if(use_arg) |
287 func_arg(a->data,arg); | 292 func_arg(a->data,arg); |
288 else | 293 else |
289 func(a->data); | 294 func(a->data); |
290 a=n; | 295 a=n; |
291 } | 296 } |
292 } | 297 } |
293 } | 298 } |
294 | 299 |
295 void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func) | 300 void lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func) |
296 { | 301 { |
297 doall_util_fn(lh, 0, func, (LHASH_DOALL_ARG_FN_TYPE)0, NULL); | 302 doall_util_fn(lh, 0, func, (LHASH_DOALL_ARG_FN_TYPE)0, NULL); |
298 } | 303 } |
299 | 304 |
300 void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg) | 305 void lh_doall_arg(_LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg) |
301 { | 306 { |
302 doall_util_fn(lh, 1, (LHASH_DOALL_FN_TYPE)0, func, arg); | 307 doall_util_fn(lh, 1, (LHASH_DOALL_FN_TYPE)0, func, arg); |
303 } | 308 } |
304 | 309 |
305 static void expand(LHASH *lh) | 310 static void expand(_LHASH *lh) |
306 { | 311 { |
307 LHASH_NODE **n,**n1,**n2,*np; | 312 LHASH_NODE **n,**n1,**n2,*np; |
308 » unsigned int p,i,j,pmax; | 313 » unsigned int p,i,j; |
309 unsigned long hash,nni; | 314 unsigned long hash,nni; |
310 | 315 |
311 p=(int)lh->p++; | |
312 nni=lh->num_alloc_nodes; | |
313 pmax=lh->pmax; | |
314 | |
315 if ((lh->p) >= lh->pmax) | |
316 { | |
317 j=(int)lh->num_alloc_nodes*2; | |
318 n=(LHASH_NODE **)OPENSSL_realloc(lh->b, | |
319 (int)sizeof(LHASH_NODE *)*j); | |
320 if (n == NULL) | |
321 { | |
322 /* fputs("realloc error in lhash",stderr); */ | |
323 lh->error++; | |
324 lh->p=0; | |
325 return; | |
326 } | |
327 /* else */ | |
328 for (i=(int)lh->num_alloc_nodes; i<j; i++)/* 26/02/92 eay */ | |
329 n[i]=NULL; /* 02/03/92 eay */ | |
330 lh->pmax=lh->num_alloc_nodes; | |
331 lh->num_alloc_nodes=j; | |
332 lh->num_expand_reallocs++; | |
333 lh->p=0; | |
334 lh->b=n; | |
335 } | |
336 | |
337 lh->num_nodes++; | 316 lh->num_nodes++; |
338 lh->num_expands++; | 317 lh->num_expands++; |
| 318 p=(int)lh->p++; |
339 n1= &(lh->b[p]); | 319 n1= &(lh->b[p]); |
340 » n2= &(lh->b[p+pmax]); | 320 » n2= &(lh->b[p+(int)lh->pmax]); |
341 *n2=NULL; /* 27/07/92 - eay - undefined pointer bug */ | 321 *n2=NULL; /* 27/07/92 - eay - undefined pointer bug */ |
| 322 nni=lh->num_alloc_nodes; |
342 | 323 |
343 for (np= *n1; np != NULL; ) | 324 for (np= *n1; np != NULL; ) |
344 { | 325 { |
345 #ifndef OPENSSL_NO_HASH_COMP | 326 #ifndef OPENSSL_NO_HASH_COMP |
346 hash=np->hash; | 327 hash=np->hash; |
347 #else | 328 #else |
348 hash=lh->hash(np->data); | 329 hash=lh->hash(np->data); |
349 lh->num_hash_calls++; | 330 lh->num_hash_calls++; |
350 #endif | 331 #endif |
351 if ((hash%nni) != p) | 332 if ((hash%nni) != p) |
352 { /* move it */ | 333 { /* move it */ |
353 *n1= (*n1)->next; | 334 *n1= (*n1)->next; |
354 np->next= *n2; | 335 np->next= *n2; |
355 *n2=np; | 336 *n2=np; |
356 } | 337 } |
357 else | 338 else |
358 n1= &((*n1)->next); | 339 n1= &((*n1)->next); |
359 np= *n1; | 340 np= *n1; |
360 } | 341 } |
361 | 342 |
| 343 if ((lh->p) >= lh->pmax) |
| 344 { |
| 345 j=(int)lh->num_alloc_nodes*2; |
| 346 n=(LHASH_NODE **)OPENSSL_realloc(lh->b, |
| 347 (int)(sizeof(LHASH_NODE *)*j)); |
| 348 if (n == NULL) |
| 349 { |
| 350 /* fputs("realloc error in lhash",stderr); */ |
| 351 lh->error++; |
| 352 lh->p=0; |
| 353 return; |
| 354 } |
| 355 /* else */ |
| 356 for (i=(int)lh->num_alloc_nodes; i<j; i++)/* 26/02/92 eay */ |
| 357 n[i]=NULL; /* 02/03/92 eay */ |
| 358 lh->pmax=lh->num_alloc_nodes; |
| 359 lh->num_alloc_nodes=j; |
| 360 lh->num_expand_reallocs++; |
| 361 lh->p=0; |
| 362 lh->b=n; |
| 363 } |
362 } | 364 } |
363 | 365 |
364 static void contract(LHASH *lh) | 366 static void contract(_LHASH *lh) |
365 { | 367 { |
366 LHASH_NODE **n,*n1,*np; | 368 LHASH_NODE **n,*n1,*np; |
367 int idx = lh->p+lh->pmax-1; | |
368 | 369 |
369 » np=lh->b[idx]; | 370 » np=lh->b[lh->p+lh->pmax-1]; |
| 371 » lh->b[lh->p+lh->pmax-1]=NULL; /* 24/07-92 - eay - weird but :-( */ |
370 if (lh->p == 0) | 372 if (lh->p == 0) |
371 { | 373 { |
372 n=(LHASH_NODE **)OPENSSL_realloc(lh->b, | 374 n=(LHASH_NODE **)OPENSSL_realloc(lh->b, |
373 (unsigned int)(sizeof(LHASH_NODE *)*lh->pmax)); | 375 (unsigned int)(sizeof(LHASH_NODE *)*lh->pmax)); |
374 if (n == NULL) | 376 if (n == NULL) |
375 { | 377 { |
376 /* fputs("realloc error in lhash",stderr); */ | 378 /* fputs("realloc error in lhash",stderr); */ |
377 lh->error++; | 379 lh->error++; |
378 return; | 380 return; |
379 } | 381 } |
380 lh->num_contract_reallocs++; | 382 lh->num_contract_reallocs++; |
381 lh->num_alloc_nodes/=2; | 383 lh->num_alloc_nodes/=2; |
382 lh->pmax/=2; | 384 lh->pmax/=2; |
383 lh->p=lh->pmax-1; | 385 lh->p=lh->pmax-1; |
384 lh->b=n; | 386 lh->b=n; |
385 } | 387 } |
386 else | 388 else |
387 lh->p--; | 389 lh->p--; |
388 | 390 |
389 lh->b[idx] = NULL; | |
390 lh->num_nodes--; | 391 lh->num_nodes--; |
391 lh->num_contracts++; | 392 lh->num_contracts++; |
392 | 393 |
393 n1=lh->b[(int)lh->p]; | 394 n1=lh->b[(int)lh->p]; |
394 if (n1 == NULL) | 395 if (n1 == NULL) |
395 lh->b[(int)lh->p]=np; | 396 lh->b[(int)lh->p]=np; |
396 else | 397 else |
397 { | 398 { |
398 while (n1->next != NULL) | 399 while (n1->next != NULL) |
399 n1=n1->next; | 400 n1=n1->next; |
400 n1->next=np; | 401 n1->next=np; |
401 } | 402 } |
402 } | 403 } |
403 | 404 |
404 static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash) | 405 static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash) |
405 { | 406 { |
406 LHASH_NODE **ret,*n1; | 407 LHASH_NODE **ret,*n1; |
407 unsigned long hash,nn; | 408 unsigned long hash,nn; |
408 LHASH_COMP_FN_TYPE cf; | 409 LHASH_COMP_FN_TYPE cf; |
409 | 410 |
410 hash=(*(lh->hash))(data); | 411 hash=(*(lh->hash))(data); |
411 lh->num_hash_calls++; | 412 lh->num_hash_calls++; |
412 *rhash=hash; | 413 *rhash=hash; |
413 | 414 |
414 nn=hash%lh->pmax; | 415 nn=hash%lh->pmax; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 n+=0x100; | 462 n+=0x100; |
462 r= (int)((v>>2)^v)&0x0f; | 463 r= (int)((v>>2)^v)&0x0f; |
463 ret=(ret<<r)|(ret>>(32-r)); | 464 ret=(ret<<r)|(ret>>(32-r)); |
464 ret&=0xFFFFFFFFL; | 465 ret&=0xFFFFFFFFL; |
465 ret^=v*v; | 466 ret^=v*v; |
466 c++; | 467 c++; |
467 } | 468 } |
468 return((ret>>16)^ret); | 469 return((ret>>16)^ret); |
469 } | 470 } |
470 | 471 |
471 unsigned long lh_num_items(const LHASH *lh) | 472 unsigned long lh_num_items(const _LHASH *lh) |
472 { | 473 { |
473 return lh ? lh->num_items : 0; | 474 return lh ? lh->num_items : 0; |
474 } | 475 } |
OLD | NEW |