xref: /onnv-gate/usr/src/common/openssl/crypto/lhash/lhash.c (revision 2139:6243c3338933)
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