⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lhash.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
字号:
/* crypto/lhash/lhash.c *//* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. *  * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to.  The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code.  The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). *  * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *    "This product includes cryptographic software written by *     Eric Young (eay@cryptsoft.com)" *    The word 'cryptographic' can be left out if the rouines from the library *    being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from  *    the apps directory (application code) you must include an acknowledgement: *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" *  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *  * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed.  i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] *//* Code for dynamic hash table routines * Author - Eric Young v 2.0 * * 2.2 eay - added #include "crypto.h" so the memory leak checking code is *	     present. eay 18-Jun-98 * * 2.1 eay - Added an 'error in last operation' flag. eay 6-May-98 * * 2.0 eay - Fixed a bug that occurred when using lh_delete *	     from inside lh_doall().  As entries were deleted, *	     the 'table' was 'contract()ed', making some entries *	     jump from the end of the table to the start, there by *	     skipping the lh_doall() processing. eay - 4/12/95 * * 1.9 eay - Fixed a memory leak in lh_free, the LHASH_NODEs *	     were not being free()ed. 21/11/95 * * 1.8 eay - Put the stats routines into a separate file, lh_stats.c *	     19/09/95 * * 1.7 eay - Removed the fputs() for realloc failures - the code *           should silently tolerate them.  I have also fixed things *           lint complained about 04/05/95 * * 1.6 eay - Fixed an invalid pointers in contract/expand 27/07/92 * * 1.5 eay - Fixed a misuse of realloc in expand 02/03/1992 * * 1.4 eay - Fixed lh_doall so the function can call lh_delete 28/05/91 * * 1.3 eay - Fixed a few lint problems 19/3/1991 * * 1.2 eay - Fixed lh_doall problem 13/3/1991 * * 1.1 eay - Added lh_doall * * 1.0 eay - First version */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <openssl/crypto.h>#include <openssl/lhash.h>const char *lh_version="lhash" OPENSSL_VERSION_PTEXT;#undef MIN_NODES #define MIN_NODES	16#define UP_LOAD		(2*LH_LOAD_MULT) /* load times 256  (default 2) */#define DOWN_LOAD	(LH_LOAD_MULT)   /* load times 256  (default 1) */static void expand(LHASH *lh);static void contract(LHASH *lh);static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash);LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c)	{	LHASH *ret;	int i;	if ((ret=(LHASH *)OPENSSL_malloc(sizeof(LHASH))) == NULL)		goto err0;	if ((ret->b=(LHASH_NODE **)OPENSSL_malloc(sizeof(LHASH_NODE *)*MIN_NODES)) == NULL)		goto err1;	for (i=0; i<MIN_NODES; i++)		ret->b[i]=NULL;	ret->comp=((c == NULL)?(LHASH_COMP_FN_TYPE)strcmp:c);	ret->hash=((h == NULL)?(LHASH_HASH_FN_TYPE)lh_strhash:h);	ret->num_nodes=MIN_NODES/2;	ret->num_alloc_nodes=MIN_NODES;	ret->p=0;	ret->pmax=MIN_NODES/2;	ret->up_load=UP_LOAD;	ret->down_load=DOWN_LOAD;	ret->num_items=0;	ret->num_expands=0;	ret->num_expand_reallocs=0;	ret->num_contracts=0;	ret->num_contract_reallocs=0;	ret->num_hash_calls=0;	ret->num_comp_calls=0;	ret->num_insert=0;	ret->num_replace=0;	ret->num_delete=0;	ret->num_no_delete=0;	ret->num_retrieve=0;	ret->num_retrieve_miss=0;	ret->num_hash_comps=0;	ret->error=0;	return(ret);err1:	OPENSSL_free(ret);err0:	return(NULL);	}void lh_free(LHASH *lh)	{	unsigned int i;	LHASH_NODE *n,*nn;	if (lh == NULL)	    return;	for (i=0; i<lh->num_nodes; i++)		{		n=lh->b[i];		while (n != NULL)			{			nn=n->next;			OPENSSL_free(n);			n=nn;			}		}	OPENSSL_free(lh->b);	OPENSSL_free(lh);	}void *lh_insert(LHASH *lh, void *data)	{	unsigned long hash;	LHASH_NODE *nn,**rn;	void *ret;	lh->error=0;	if (lh->up_load <= (lh->num_items*LH_LOAD_MULT/lh->num_nodes))		expand(lh);	rn=getrn(lh,data,&hash);	if (*rn == NULL)		{		if ((nn=(LHASH_NODE *)OPENSSL_malloc(sizeof(LHASH_NODE))) == NULL)			{			lh->error++;			return(NULL);			}		nn->data=data;		nn->next=NULL;#ifndef OPENSSL_NO_HASH_COMP		nn->hash=hash;#endif		*rn=nn;		ret=NULL;		lh->num_insert++;		lh->num_items++;		}	else /* replace same key */		{		ret= (*rn)->data;		(*rn)->data=data;		lh->num_replace++;		}	return(ret);	}void *lh_delete(LHASH *lh, const void *data)	{	unsigned long hash;	LHASH_NODE *nn,**rn;	void *ret;	lh->error=0;	rn=getrn(lh,data,&hash);	if (*rn == NULL)		{		lh->num_no_delete++;		return(NULL);		}	else		{		nn= *rn;		*rn=nn->next;		ret=nn->data;		OPENSSL_free(nn);		lh->num_delete++;		}	lh->num_items--;	if ((lh->num_nodes > MIN_NODES) &&		(lh->down_load >= (lh->num_items*LH_LOAD_MULT/lh->num_nodes)))		contract(lh);	return(ret);	}void *lh_retrieve(LHASH *lh, const void *data)	{	unsigned long hash;	LHASH_NODE **rn;	void *ret;	lh->error=0;	rn=getrn(lh,data,&hash);	if (*rn == NULL)		{		lh->num_retrieve_miss++;		return(NULL);		}	else		{		ret= (*rn)->data;		lh->num_retrieve++;		}	return(ret);	}static void doall_util_fn(LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func,			  LHASH_DOALL_ARG_FN_TYPE func_arg, void *arg)	{	int i;	LHASH_NODE *a,*n;	/* reverse the order so we search from 'top to bottom'	 * We were having memory leaks otherwise */	for (i=lh->num_nodes-1; i>=0; i--)		{		a=lh->b[i];		while (a != NULL)			{			/* 28/05/91 - eay - n added so items can be deleted			 * via lh_doall */			n=a->next;			if(use_arg)				func_arg(a->data,arg);			else				func(a->data);			a=n;			}		}	}void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func)	{	doall_util_fn(lh, 0, func, (LHASH_DOALL_ARG_FN_TYPE)0, NULL);	}void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg)	{	doall_util_fn(lh, 1, (LHASH_DOALL_FN_TYPE)0, func, arg);	}static void expand(LHASH *lh)	{	LHASH_NODE **n,**n1,**n2,*np;	unsigned int p,i,j;	unsigned long hash,nni;	lh->num_nodes++;	lh->num_expands++;	p=(int)lh->p++;	n1= &(lh->b[p]);	n2= &(lh->b[p+(int)lh->pmax]);	*n2=NULL;        /* 27/07/92 - eay - undefined pointer bug */	nni=lh->num_alloc_nodes;		for (np= *n1; np != NULL; )		{#ifndef OPENSSL_NO_HASH_COMP		hash=np->hash;#else		hash=lh->hash(np->data);		lh->num_hash_calls++;#endif		if ((hash%nni) != p)			{ /* move it */			*n1= (*n1)->next;			np->next= *n2;			*n2=np;			}		else			n1= &((*n1)->next);		np= *n1;		}	if ((lh->p) >= lh->pmax)		{		j=(int)lh->num_alloc_nodes*2;		n=(LHASH_NODE **)OPENSSL_realloc(lh->b,			(int)(sizeof(LHASH_NODE *)*j));		if (n == NULL)			{/*			fputs("realloc error in lhash",stderr); */			lh->error++;			lh->p=0;			return;			}		/* else */		for (i=(int)lh->num_alloc_nodes; i<j; i++)/* 26/02/92 eay */			n[i]=NULL;			  /* 02/03/92 eay */		lh->pmax=lh->num_alloc_nodes;		lh->num_alloc_nodes=j;		lh->num_expand_reallocs++;		lh->p=0;		lh->b=n;		}	}static void contract(LHASH *lh)	{	LHASH_NODE **n,*n1,*np;	np=lh->b[lh->p+lh->pmax-1];	lh->b[lh->p+lh->pmax-1]=NULL; /* 24/07-92 - eay - weird but :-( */	if (lh->p == 0)		{		n=(LHASH_NODE **)OPENSSL_realloc(lh->b,			(unsigned int)(sizeof(LHASH_NODE *)*lh->pmax));		if (n == NULL)			{/*			fputs("realloc error in lhash",stderr); */			lh->error++;			return;			}		lh->num_contract_reallocs++;		lh->num_alloc_nodes/=2;		lh->pmax/=2;		lh->p=lh->pmax-1;		lh->b=n;		}	else		lh->p--;	lh->num_nodes--;	lh->num_contracts++;	n1=lh->b[(int)lh->p];	if (n1 == NULL)		lh->b[(int)lh->p]=np;	else		{		while (n1->next != NULL)			n1=n1->next;		n1->next=np;		}	}static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash)	{	LHASH_NODE **ret,*n1;	unsigned long hash,nn;	LHASH_COMP_FN_TYPE cf;	hash=(*(lh->hash))(data);	lh->num_hash_calls++;	*rhash=hash;	nn=hash%lh->pmax;	if (nn < lh->p)		nn=hash%lh->num_alloc_nodes;	cf=lh->comp;	ret= &(lh->b[(int)nn]);	for (n1= *ret; n1 != NULL; n1=n1->next)		{#ifndef OPENSSL_NO_HASH_COMP		lh->num_hash_comps++;		if (n1->hash != hash)			{			ret= &(n1->next);			continue;			}#endif		lh->num_comp_calls++;		if(cf(n1->data,data) == 0)			break;		ret= &(n1->next);		}	return(ret);	}/* The following hash seems to work very well on normal text strings * no collisions on /usr/dict/words and it distributes on %2^n quite * well, not as good as MD5, but still good. */unsigned long lh_strhash(const char *c)	{	unsigned long ret=0;	long n;	unsigned long v;	int r;	if ((c == NULL) || (*c == '\0'))		return(ret);/*	unsigned char b[16];	MD5(c,strlen(c),b);	return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24)); */	n=0x100;	while (*c)		{		v=n|(*c);		n+=0x100;		r= (int)((v>>2)^v)&0x0f;		ret=(ret<<r)|(ret>>(32-r));		ret&=0xFFFFFFFFL;		ret^=v*v;		c++;		}	return((ret>>16)^ret);	}unsigned long lh_num_items(const LHASH *lh)	{	return lh ? lh->num_items : 0;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -