10Sstevel@tonic-gate /* crypto/lhash/lhash.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate * All rights reserved.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * This package is an SSL implementation written
60Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate * the following conditions are aheared to. The following conditions
110Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation
130Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate *
160Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate * the code are not to be removed.
180Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate * as the author of the parts of the library used.
200Sstevel@tonic-gate * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate *
230Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate * are met:
260Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate * must display the following acknowledgement:
330Sstevel@tonic-gate * "This product includes cryptographic software written by
340Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate * being used are not cryptographic related :-).
370Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate *
410Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate * SUCH DAMAGE.
520Sstevel@tonic-gate *
530Sstevel@tonic-gate * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be
550Sstevel@tonic-gate * copied and put under another distribution licence
560Sstevel@tonic-gate * [including the GNU Public Licence.]
570Sstevel@tonic-gate */
580Sstevel@tonic-gate
590Sstevel@tonic-gate /* Code for dynamic hash table routines
600Sstevel@tonic-gate * Author - Eric Young v 2.0
610Sstevel@tonic-gate *
620Sstevel@tonic-gate * 2.2 eay - added #include "crypto.h" so the memory leak checking code is
630Sstevel@tonic-gate * present. eay 18-Jun-98
640Sstevel@tonic-gate *
650Sstevel@tonic-gate * 2.1 eay - Added an 'error in last operation' flag. eay 6-May-98
660Sstevel@tonic-gate *
670Sstevel@tonic-gate * 2.0 eay - Fixed a bug that occurred when using lh_delete
680Sstevel@tonic-gate * from inside lh_doall(). As entries were deleted,
690Sstevel@tonic-gate * the 'table' was 'contract()ed', making some entries
700Sstevel@tonic-gate * jump from the end of the table to the start, there by
710Sstevel@tonic-gate * skipping the lh_doall() processing. eay - 4/12/95
720Sstevel@tonic-gate *
730Sstevel@tonic-gate * 1.9 eay - Fixed a memory leak in lh_free, the LHASH_NODEs
740Sstevel@tonic-gate * were not being free()ed. 21/11/95
750Sstevel@tonic-gate *
760Sstevel@tonic-gate * 1.8 eay - Put the stats routines into a separate file, lh_stats.c
770Sstevel@tonic-gate * 19/09/95
780Sstevel@tonic-gate *
790Sstevel@tonic-gate * 1.7 eay - Removed the fputs() for realloc failures - the code
800Sstevel@tonic-gate * should silently tolerate them. I have also fixed things
810Sstevel@tonic-gate * lint complained about 04/05/95
820Sstevel@tonic-gate *
830Sstevel@tonic-gate * 1.6 eay - Fixed an invalid pointers in contract/expand 27/07/92
840Sstevel@tonic-gate *
850Sstevel@tonic-gate * 1.5 eay - Fixed a misuse of realloc in expand 02/03/1992
860Sstevel@tonic-gate *
870Sstevel@tonic-gate * 1.4 eay - Fixed lh_doall so the function can call lh_delete 28/05/91
880Sstevel@tonic-gate *
890Sstevel@tonic-gate * 1.3 eay - Fixed a few lint problems 19/3/1991
900Sstevel@tonic-gate *
910Sstevel@tonic-gate * 1.2 eay - Fixed lh_doall problem 13/3/1991
920Sstevel@tonic-gate *
930Sstevel@tonic-gate * 1.1 eay - Added lh_doall
940Sstevel@tonic-gate *
950Sstevel@tonic-gate * 1.0 eay - First version
960Sstevel@tonic-gate */
970Sstevel@tonic-gate #include <stdio.h>
980Sstevel@tonic-gate #include <string.h>
990Sstevel@tonic-gate #include <stdlib.h>
1000Sstevel@tonic-gate #include <openssl/crypto.h>
1010Sstevel@tonic-gate #include <openssl/lhash.h>
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate const char *lh_version="lhash" OPENSSL_VERSION_PTEXT;
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate #undef MIN_NODES
1060Sstevel@tonic-gate #define MIN_NODES 16
1070Sstevel@tonic-gate #define UP_LOAD (2*LH_LOAD_MULT) /* load times 256 (default 2) */
1080Sstevel@tonic-gate #define DOWN_LOAD (LH_LOAD_MULT) /* load times 256 (default 1) */
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate static void expand(LHASH *lh);
1110Sstevel@tonic-gate static void contract(LHASH *lh);
1120Sstevel@tonic-gate static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash);
1130Sstevel@tonic-gate
lh_new(LHASH_HASH_FN_TYPE h,LHASH_COMP_FN_TYPE c)1140Sstevel@tonic-gate LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c)
1150Sstevel@tonic-gate {
1160Sstevel@tonic-gate LHASH *ret;
1170Sstevel@tonic-gate int i;
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate if ((ret=(LHASH *)OPENSSL_malloc(sizeof(LHASH))) == NULL)
1200Sstevel@tonic-gate goto err0;
1210Sstevel@tonic-gate if ((ret->b=(LHASH_NODE **)OPENSSL_malloc(sizeof(LHASH_NODE *)*MIN_NODES)) == NULL)
1220Sstevel@tonic-gate goto err1;
1230Sstevel@tonic-gate for (i=0; i<MIN_NODES; i++)
1240Sstevel@tonic-gate ret->b[i]=NULL;
1250Sstevel@tonic-gate ret->comp=((c == NULL)?(LHASH_COMP_FN_TYPE)strcmp:c);
1260Sstevel@tonic-gate ret->hash=((h == NULL)?(LHASH_HASH_FN_TYPE)lh_strhash:h);
1270Sstevel@tonic-gate ret->num_nodes=MIN_NODES/2;
1280Sstevel@tonic-gate ret->num_alloc_nodes=MIN_NODES;
1290Sstevel@tonic-gate ret->p=0;
1300Sstevel@tonic-gate ret->pmax=MIN_NODES/2;
1310Sstevel@tonic-gate ret->up_load=UP_LOAD;
1320Sstevel@tonic-gate ret->down_load=DOWN_LOAD;
1330Sstevel@tonic-gate ret->num_items=0;
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate ret->num_expands=0;
1360Sstevel@tonic-gate ret->num_expand_reallocs=0;
1370Sstevel@tonic-gate ret->num_contracts=0;
1380Sstevel@tonic-gate ret->num_contract_reallocs=0;
1390Sstevel@tonic-gate ret->num_hash_calls=0;
1400Sstevel@tonic-gate ret->num_comp_calls=0;
1410Sstevel@tonic-gate ret->num_insert=0;
1420Sstevel@tonic-gate ret->num_replace=0;
1430Sstevel@tonic-gate ret->num_delete=0;
1440Sstevel@tonic-gate ret->num_no_delete=0;
1450Sstevel@tonic-gate ret->num_retrieve=0;
1460Sstevel@tonic-gate ret->num_retrieve_miss=0;
1470Sstevel@tonic-gate ret->num_hash_comps=0;
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate ret->error=0;
1500Sstevel@tonic-gate return(ret);
1510Sstevel@tonic-gate err1:
1520Sstevel@tonic-gate OPENSSL_free(ret);
1530Sstevel@tonic-gate err0:
1540Sstevel@tonic-gate return(NULL);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate
lh_free(LHASH * lh)1570Sstevel@tonic-gate void lh_free(LHASH *lh)
1580Sstevel@tonic-gate {
1590Sstevel@tonic-gate unsigned int i;
1600Sstevel@tonic-gate LHASH_NODE *n,*nn;
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate if (lh == NULL)
1630Sstevel@tonic-gate return;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate for (i=0; i<lh->num_nodes; i++)
1660Sstevel@tonic-gate {
1670Sstevel@tonic-gate n=lh->b[i];
1680Sstevel@tonic-gate while (n != NULL)
1690Sstevel@tonic-gate {
1700Sstevel@tonic-gate nn=n->next;
1710Sstevel@tonic-gate OPENSSL_free(n);
1720Sstevel@tonic-gate n=nn;
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate OPENSSL_free(lh->b);
1760Sstevel@tonic-gate OPENSSL_free(lh);
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate
lh_insert(LHASH * lh,void * data)179*2139Sjp161948 void *lh_insert(LHASH *lh, void *data)
1800Sstevel@tonic-gate {
1810Sstevel@tonic-gate unsigned long hash;
1820Sstevel@tonic-gate LHASH_NODE *nn,**rn;
183*2139Sjp161948 void *ret;
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate lh->error=0;
1860Sstevel@tonic-gate if (lh->up_load <= (lh->num_items*LH_LOAD_MULT/lh->num_nodes))
1870Sstevel@tonic-gate expand(lh);
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate rn=getrn(lh,data,&hash);
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate if (*rn == NULL)
1920Sstevel@tonic-gate {
1930Sstevel@tonic-gate if ((nn=(LHASH_NODE *)OPENSSL_malloc(sizeof(LHASH_NODE))) == NULL)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate lh->error++;
1960Sstevel@tonic-gate return(NULL);
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate nn->data=data;
1990Sstevel@tonic-gate nn->next=NULL;
2000Sstevel@tonic-gate #ifndef OPENSSL_NO_HASH_COMP
2010Sstevel@tonic-gate nn->hash=hash;
2020Sstevel@tonic-gate #endif
2030Sstevel@tonic-gate *rn=nn;
2040Sstevel@tonic-gate ret=NULL;
2050Sstevel@tonic-gate lh->num_insert++;
2060Sstevel@tonic-gate lh->num_items++;
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate else /* replace same key */
2090Sstevel@tonic-gate {
2100Sstevel@tonic-gate ret= (*rn)->data;
2110Sstevel@tonic-gate (*rn)->data=data;
2120Sstevel@tonic-gate lh->num_replace++;
2130Sstevel@tonic-gate }
214*2139Sjp161948 return(ret);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate
lh_delete(LHASH * lh,const void * data)2170Sstevel@tonic-gate void *lh_delete(LHASH *lh, const void *data)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate unsigned long hash;
2200Sstevel@tonic-gate LHASH_NODE *nn,**rn;
221*2139Sjp161948 void *ret;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate lh->error=0;
2240Sstevel@tonic-gate rn=getrn(lh,data,&hash);
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate if (*rn == NULL)
2270Sstevel@tonic-gate {
2280Sstevel@tonic-gate lh->num_no_delete++;
2290Sstevel@tonic-gate return(NULL);
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate else
2320Sstevel@tonic-gate {
2330Sstevel@tonic-gate nn= *rn;
2340Sstevel@tonic-gate *rn=nn->next;
2350Sstevel@tonic-gate ret=nn->data;
2360Sstevel@tonic-gate OPENSSL_free(nn);
2370Sstevel@tonic-gate lh->num_delete++;
2380Sstevel@tonic-gate }
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate lh->num_items--;
2410Sstevel@tonic-gate if ((lh->num_nodes > MIN_NODES) &&
2420Sstevel@tonic-gate (lh->down_load >= (lh->num_items*LH_LOAD_MULT/lh->num_nodes)))
2430Sstevel@tonic-gate contract(lh);
2440Sstevel@tonic-gate
245*2139Sjp161948 return(ret);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
lh_retrieve(LHASH * lh,const void * data)2480Sstevel@tonic-gate void *lh_retrieve(LHASH *lh, const void *data)
2490Sstevel@tonic-gate {
2500Sstevel@tonic-gate unsigned long hash;
2510Sstevel@tonic-gate LHASH_NODE **rn;
252*2139Sjp161948 void *ret;
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate lh->error=0;
2550Sstevel@tonic-gate rn=getrn(lh,data,&hash);
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate if (*rn == NULL)
2580Sstevel@tonic-gate {
2590Sstevel@tonic-gate lh->num_retrieve_miss++;
2600Sstevel@tonic-gate return(NULL);
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate else
2630Sstevel@tonic-gate {
2640Sstevel@tonic-gate ret= (*rn)->data;
2650Sstevel@tonic-gate lh->num_retrieve++;
2660Sstevel@tonic-gate }
267*2139Sjp161948 return(ret);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate
doall_util_fn(LHASH * lh,int use_arg,LHASH_DOALL_FN_TYPE func,LHASH_DOALL_ARG_FN_TYPE func_arg,void * arg)2700Sstevel@tonic-gate static void doall_util_fn(LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func,
2710Sstevel@tonic-gate LHASH_DOALL_ARG_FN_TYPE func_arg, void *arg)
2720Sstevel@tonic-gate {
2730Sstevel@tonic-gate int i;
2740Sstevel@tonic-gate LHASH_NODE *a,*n;
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /* reverse the order so we search from 'top to bottom'
2770Sstevel@tonic-gate * We were having memory leaks otherwise */
2780Sstevel@tonic-gate for (i=lh->num_nodes-1; i>=0; i--)
2790Sstevel@tonic-gate {
2800Sstevel@tonic-gate a=lh->b[i];
2810Sstevel@tonic-gate while (a != NULL)
2820Sstevel@tonic-gate {
2830Sstevel@tonic-gate /* 28/05/91 - eay - n added so items can be deleted
2840Sstevel@tonic-gate * via lh_doall */
2850Sstevel@tonic-gate n=a->next;
2860Sstevel@tonic-gate if(use_arg)
2870Sstevel@tonic-gate func_arg(a->data,arg);
2880Sstevel@tonic-gate else
2890Sstevel@tonic-gate func(a->data);
2900Sstevel@tonic-gate a=n;
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate
lh_doall(LHASH * lh,LHASH_DOALL_FN_TYPE func)2950Sstevel@tonic-gate void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func)
2960Sstevel@tonic-gate {
2970Sstevel@tonic-gate doall_util_fn(lh, 0, func, (LHASH_DOALL_ARG_FN_TYPE)0, NULL);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate
lh_doall_arg(LHASH * lh,LHASH_DOALL_ARG_FN_TYPE func,void * arg)3000Sstevel@tonic-gate void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg)
3010Sstevel@tonic-gate {
3020Sstevel@tonic-gate doall_util_fn(lh, 1, (LHASH_DOALL_FN_TYPE)0, func, arg);
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate
expand(LHASH * lh)3050Sstevel@tonic-gate static void expand(LHASH *lh)
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate LHASH_NODE **n,**n1,**n2,*np;
3080Sstevel@tonic-gate unsigned int p,i,j;
3090Sstevel@tonic-gate unsigned long hash,nni;
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate lh->num_nodes++;
3120Sstevel@tonic-gate lh->num_expands++;
3130Sstevel@tonic-gate p=(int)lh->p++;
3140Sstevel@tonic-gate n1= &(lh->b[p]);
3150Sstevel@tonic-gate n2= &(lh->b[p+(int)lh->pmax]);
3160Sstevel@tonic-gate *n2=NULL; /* 27/07/92 - eay - undefined pointer bug */
3170Sstevel@tonic-gate nni=lh->num_alloc_nodes;
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate for (np= *n1; np != NULL; )
3200Sstevel@tonic-gate {
3210Sstevel@tonic-gate #ifndef OPENSSL_NO_HASH_COMP
3220Sstevel@tonic-gate hash=np->hash;
3230Sstevel@tonic-gate #else
3240Sstevel@tonic-gate hash=lh->hash(np->data);
3250Sstevel@tonic-gate lh->num_hash_calls++;
3260Sstevel@tonic-gate #endif
3270Sstevel@tonic-gate if ((hash%nni) != p)
3280Sstevel@tonic-gate { /* move it */
3290Sstevel@tonic-gate *n1= (*n1)->next;
3300Sstevel@tonic-gate np->next= *n2;
3310Sstevel@tonic-gate *n2=np;
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate else
3340Sstevel@tonic-gate n1= &((*n1)->next);
3350Sstevel@tonic-gate np= *n1;
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate if ((lh->p) >= lh->pmax)
3390Sstevel@tonic-gate {
3400Sstevel@tonic-gate j=(int)lh->num_alloc_nodes*2;
3410Sstevel@tonic-gate n=(LHASH_NODE **)OPENSSL_realloc(lh->b,
342*2139Sjp161948 (int)(sizeof(LHASH_NODE *)*j));
3430Sstevel@tonic-gate if (n == NULL)
3440Sstevel@tonic-gate {
3450Sstevel@tonic-gate /* fputs("realloc error in lhash",stderr); */
3460Sstevel@tonic-gate lh->error++;
3470Sstevel@tonic-gate lh->p=0;
3480Sstevel@tonic-gate return;
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate /* else */
3510Sstevel@tonic-gate for (i=(int)lh->num_alloc_nodes; i<j; i++)/* 26/02/92 eay */
3520Sstevel@tonic-gate n[i]=NULL; /* 02/03/92 eay */
3530Sstevel@tonic-gate lh->pmax=lh->num_alloc_nodes;
3540Sstevel@tonic-gate lh->num_alloc_nodes=j;
3550Sstevel@tonic-gate lh->num_expand_reallocs++;
3560Sstevel@tonic-gate lh->p=0;
3570Sstevel@tonic-gate lh->b=n;
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate
contract(LHASH * lh)3610Sstevel@tonic-gate static void contract(LHASH *lh)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate LHASH_NODE **n,*n1,*np;
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate np=lh->b[lh->p+lh->pmax-1];
3660Sstevel@tonic-gate lh->b[lh->p+lh->pmax-1]=NULL; /* 24/07-92 - eay - weird but :-( */
3670Sstevel@tonic-gate if (lh->p == 0)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate n=(LHASH_NODE **)OPENSSL_realloc(lh->b,
3700Sstevel@tonic-gate (unsigned int)(sizeof(LHASH_NODE *)*lh->pmax));
3710Sstevel@tonic-gate if (n == NULL)
3720Sstevel@tonic-gate {
3730Sstevel@tonic-gate /* fputs("realloc error in lhash",stderr); */
3740Sstevel@tonic-gate lh->error++;
3750Sstevel@tonic-gate return;
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate lh->num_contract_reallocs++;
3780Sstevel@tonic-gate lh->num_alloc_nodes/=2;
3790Sstevel@tonic-gate lh->pmax/=2;
3800Sstevel@tonic-gate lh->p=lh->pmax-1;
3810Sstevel@tonic-gate lh->b=n;
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate else
3840Sstevel@tonic-gate lh->p--;
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate lh->num_nodes--;
3870Sstevel@tonic-gate lh->num_contracts++;
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate n1=lh->b[(int)lh->p];
3900Sstevel@tonic-gate if (n1 == NULL)
3910Sstevel@tonic-gate lh->b[(int)lh->p]=np;
3920Sstevel@tonic-gate else
3930Sstevel@tonic-gate {
3940Sstevel@tonic-gate while (n1->next != NULL)
3950Sstevel@tonic-gate n1=n1->next;
3960Sstevel@tonic-gate n1->next=np;
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate }
3990Sstevel@tonic-gate
getrn(LHASH * lh,const void * data,unsigned long * rhash)4000Sstevel@tonic-gate static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash)
4010Sstevel@tonic-gate {
4020Sstevel@tonic-gate LHASH_NODE **ret,*n1;
4030Sstevel@tonic-gate unsigned long hash,nn;
404*2139Sjp161948 LHASH_COMP_FN_TYPE cf;
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate hash=(*(lh->hash))(data);
4070Sstevel@tonic-gate lh->num_hash_calls++;
4080Sstevel@tonic-gate *rhash=hash;
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate nn=hash%lh->pmax;
4110Sstevel@tonic-gate if (nn < lh->p)
4120Sstevel@tonic-gate nn=hash%lh->num_alloc_nodes;
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate cf=lh->comp;
4150Sstevel@tonic-gate ret= &(lh->b[(int)nn]);
4160Sstevel@tonic-gate for (n1= *ret; n1 != NULL; n1=n1->next)
4170Sstevel@tonic-gate {
4180Sstevel@tonic-gate #ifndef OPENSSL_NO_HASH_COMP
4190Sstevel@tonic-gate lh->num_hash_comps++;
4200Sstevel@tonic-gate if (n1->hash != hash)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate ret= &(n1->next);
4230Sstevel@tonic-gate continue;
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate #endif
4260Sstevel@tonic-gate lh->num_comp_calls++;
4270Sstevel@tonic-gate if(cf(n1->data,data) == 0)
4280Sstevel@tonic-gate break;
4290Sstevel@tonic-gate ret= &(n1->next);
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate return(ret);
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate /* The following hash seems to work very well on normal text strings
4350Sstevel@tonic-gate * no collisions on /usr/dict/words and it distributes on %2^n quite
4360Sstevel@tonic-gate * well, not as good as MD5, but still good.
4370Sstevel@tonic-gate */
lh_strhash(const char * c)4380Sstevel@tonic-gate unsigned long lh_strhash(const char *c)
4390Sstevel@tonic-gate {
4400Sstevel@tonic-gate unsigned long ret=0;
4410Sstevel@tonic-gate long n;
4420Sstevel@tonic-gate unsigned long v;
4430Sstevel@tonic-gate int r;
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate if ((c == NULL) || (*c == '\0'))
4460Sstevel@tonic-gate return(ret);
4470Sstevel@tonic-gate /*
4480Sstevel@tonic-gate unsigned char b[16];
4490Sstevel@tonic-gate MD5(c,strlen(c),b);
4500Sstevel@tonic-gate return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24));
4510Sstevel@tonic-gate */
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate n=0x100;
4540Sstevel@tonic-gate while (*c)
4550Sstevel@tonic-gate {
4560Sstevel@tonic-gate v=n|(*c);
4570Sstevel@tonic-gate n+=0x100;
4580Sstevel@tonic-gate r= (int)((v>>2)^v)&0x0f;
4590Sstevel@tonic-gate ret=(ret<<r)|(ret>>(32-r));
4600Sstevel@tonic-gate ret&=0xFFFFFFFFL;
4610Sstevel@tonic-gate ret^=v*v;
4620Sstevel@tonic-gate c++;
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate return((ret>>16)^ret);
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate
lh_num_items(const LHASH * lh)4670Sstevel@tonic-gate unsigned long lh_num_items(const LHASH *lh)
4680Sstevel@tonic-gate {
4690Sstevel@tonic-gate return lh ? lh->num_items : 0;
4700Sstevel@tonic-gate }
471