tclhash.c

来自「tcl是工具命令语言」· C语言 代码 · 共 1,204 行 · 第 1/3 页

C
1,204
字号
 *---------------------------------------------------------------------- */static Tcl_HashEntry *AllocArrayEntry(tablePtr, keyPtr)    Tcl_HashTable *tablePtr;	/* Hash table. */    VOID *keyPtr;		/* Key to store in the hash table entry. */{    int *array = (int *) keyPtr;    register int *iPtr1, *iPtr2;    Tcl_HashEntry *hPtr;    int count;    unsigned int size;    count = tablePtr->keyType;        size = sizeof(Tcl_HashEntry) + (count*sizeof(int)) - sizeof(hPtr->key);    if (size < sizeof(Tcl_HashEntry))	size = sizeof(Tcl_HashEntry);    hPtr = (Tcl_HashEntry *) ckalloc(size);        for (iPtr1 = array, iPtr2 = hPtr->key.words;	    count > 0; count--, iPtr1++, iPtr2++) {	*iPtr2 = *iPtr1;    }    return hPtr;}/* *---------------------------------------------------------------------- * * CompareArrayKeys -- * *	Compares two array keys. * * Results: *	The return value is 0 if they are different and 1 if they are *	the same. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intCompareArrayKeys(keyPtr, hPtr)    VOID *keyPtr;		/* New key to compare. */    Tcl_HashEntry *hPtr;	/* Existing key to compare. */{    register CONST int *iPtr1 = (CONST int *) keyPtr;    register CONST int *iPtr2 = (CONST int *) hPtr->key.words;    Tcl_HashTable *tablePtr = hPtr->tablePtr;    int count;    for (count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) {	if (count == 0) {	    return 1;	}	if (*iPtr1 != *iPtr2) {	    break;	}    }    return 0;}/* *---------------------------------------------------------------------- * * HashArrayKey -- * *	Compute a one-word summary of an array, which can be *	used to generate a hash index. * * Results: *	The return value is a one-word summary of the information in *	string. * * Side effects: *	None. * *---------------------------------------------------------------------- */static unsigned intHashArrayKey(tablePtr, keyPtr)    Tcl_HashTable *tablePtr;	/* Hash table. */    VOID *keyPtr;		/* Key from which to compute hash value. */{    register CONST int *array = (CONST int *) keyPtr;    register unsigned int result;    int count;    for (result = 0, count = tablePtr->keyType; count > 0;	    count--, array++) {	result += *array;    }    return result;}/* *---------------------------------------------------------------------- * * AllocStringEntry -- * *	Allocate space for a Tcl_HashEntry containing the string key. * * Results: *	The return value is a pointer to the created entry. * * Side effects: *	None. * *---------------------------------------------------------------------- */static Tcl_HashEntry *AllocStringEntry(tablePtr, keyPtr)    Tcl_HashTable *tablePtr;	/* Hash table. */    VOID *keyPtr;		/* Key to store in the hash table entry. */{    CONST char *string = (CONST char *) keyPtr;    Tcl_HashEntry *hPtr;    unsigned int size;    size = sizeof(Tcl_HashEntry) + strlen(string) + 1 - sizeof(hPtr->key);    if (size < sizeof(Tcl_HashEntry))	size = sizeof(Tcl_HashEntry);    hPtr = (Tcl_HashEntry *) ckalloc(size);    strcpy(hPtr->key.string, string);    return hPtr;}/* *---------------------------------------------------------------------- * * CompareStringKeys -- * *	Compares two string keys. * * Results: *	The return value is 0 if they are different and 1 if they are *	the same. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intCompareStringKeys(keyPtr, hPtr)    VOID *keyPtr;		/* New key to compare. */    Tcl_HashEntry *hPtr;		/* Existing key to compare. */{    register CONST char *p1 = (CONST char *) keyPtr;    register CONST char *p2 = (CONST char *) hPtr->key.string;    for (;; p1++, p2++) {	if (*p1 != *p2) {	    break;	}	if (*p1 == '\0') {	    return 1;	}    }    return 0;}/* *---------------------------------------------------------------------- * * HashStringKey -- * *	Compute a one-word summary of a text string, which can be *	used to generate a hash index. * * Results: *	The return value is a one-word summary of the information in *	string. * * Side effects: *	None. * *---------------------------------------------------------------------- */static unsigned intHashStringKey(tablePtr, keyPtr)    Tcl_HashTable *tablePtr;	/* Hash table. */    VOID *keyPtr;		/* Key from which to compute hash value. */{    register CONST char *string = (CONST char *) keyPtr;    register unsigned int result;    register int c;    /*     * I tried a zillion different hash functions and asked many other     * people for advice.  Many people had their own favorite functions,     * all different, but no-one had much idea why they were good ones.     * I chose the one below (multiply by 9 and add new character)     * because of the following reasons:     *     * 1. Multiplying by 10 is perfect for keys that are decimal strings,     *    and multiplying by 9 is just about as good.     * 2. Times-9 is (shift-left-3) plus (old).  This means that each     *    character's bits hang around in the low-order bits of the     *    hash value for ever, plus they spread fairly rapidly up to     *    the high-order bits to fill out the hash value.  This seems     *    works well both for decimal and non-decimal strings.     */    result = 0;    while (1) {	c = *string;	if (c == 0) {	    break;	}	result += (result<<3) + c;	string++;    }    return result;}#if TCL_PRESERVE_BINARY_COMPATABILITY/* *---------------------------------------------------------------------- * * BogusFind -- * *	This procedure is invoked when an Tcl_FindHashEntry is called *	on a table that has been deleted. * * Results: *	If panic returns (which it shouldn't) this procedure returns *	NULL. * * Side effects: *	Generates a panic. * *---------------------------------------------------------------------- */	/* ARGSUSED */static Tcl_HashEntry *BogusFind(tablePtr, key)    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */    CONST char *key;		/* Key to use to find matching entry. */{    panic("called Tcl_FindHashEntry on deleted table");    return NULL;}/* *---------------------------------------------------------------------- * * BogusCreate -- * *	This procedure is invoked when an Tcl_CreateHashEntry is called *	on a table that has been deleted. * * Results: *	If panic returns (which it shouldn't) this procedure returns *	NULL. * * Side effects: *	Generates a panic. * *---------------------------------------------------------------------- */	/* ARGSUSED */static Tcl_HashEntry *BogusCreate(tablePtr, key, newPtr)    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */    CONST char *key;		/* Key to use to find or create matching				 * entry. */    int *newPtr;		/* Store info here telling whether a new				 * entry was created. */{    panic("called Tcl_CreateHashEntry on deleted table");    return NULL;}#endif/* *---------------------------------------------------------------------- * * RebuildTable -- * *	This procedure is invoked when the ratio of entries to hash *	buckets becomes too large.  It creates a new table with a *	larger bucket array and moves all of the entries into the *	new table. * * Results: *	None. * * Side effects: *	Memory gets reallocated and entries get re-hashed to new *	buckets. * *---------------------------------------------------------------------- */static voidRebuildTable(tablePtr)    register Tcl_HashTable *tablePtr;	/* Table to enlarge. */{    int oldSize, count, index;    Tcl_HashEntry **oldBuckets;    register Tcl_HashEntry **oldChainPtr, **newChainPtr;    register Tcl_HashEntry *hPtr;    Tcl_HashKeyType *typePtr;    VOID *key;    oldSize = tablePtr->numBuckets;    oldBuckets = tablePtr->buckets;    /*     * Allocate and initialize the new bucket array, and set up     * hashing constants for new array size.     */    tablePtr->numBuckets *= 4;    tablePtr->buckets = (Tcl_HashEntry **) ckalloc((unsigned)	    (tablePtr->numBuckets * sizeof(Tcl_HashEntry *)));    for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets;	    count > 0; count--, newChainPtr++) {	*newChainPtr = NULL;    }    tablePtr->rebuildSize *= 4;    tablePtr->downShift -= 2;    tablePtr->mask = (tablePtr->mask << 2) + 3;#if TCL_PRESERVE_BINARY_COMPATABILITY    if (tablePtr->keyType == TCL_STRING_KEYS) {	typePtr = &tclStringHashKeyType;    } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {	typePtr = &tclOneWordHashKeyType;    } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS	       || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {	typePtr = tablePtr->typePtr;    } else {	typePtr = &tclArrayHashKeyType;    }#else    typePtr = tablePtr->typePtr;#endif    /*     * Rehash all of the existing entries into the new bucket array.     */    for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) {	for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) {	    *oldChainPtr = hPtr->nextPtr;	    key = (VOID *) Tcl_GetHashKey (tablePtr, hPtr);#if TCL_HASH_KEY_STORE_HASH	    if (typePtr->hashKeyProc == NULL		|| typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {		index = RANDOM_INDEX (tablePtr, hPtr->hash);	    } else {		index = ((unsigned int) hPtr->hash) & tablePtr->mask;	    }	    hPtr->nextPtr = tablePtr->buckets[index];	    tablePtr->buckets[index] = hPtr;#else	    if (typePtr->hashKeyProc) {		unsigned int hash;		hash = typePtr->hashKeyProc (tablePtr, (VOID *) key);		if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {		    index = RANDOM_INDEX (tablePtr, hash);		} else {		    index = hash & tablePtr->mask;		}	    } else {		index = RANDOM_INDEX (tablePtr, key);	    }	    hPtr->bucketPtr = &(tablePtr->buckets[index]);	    hPtr->nextPtr = *hPtr->bucketPtr;	    *hPtr->bucketPtr = hPtr;#endif	}    }    /*     * Free up the old bucket array, if it was dynamically allocated.     */    if (oldBuckets != tablePtr->staticBuckets) {	ckfree((char *) oldBuckets);    }}

⌨️ 快捷键说明

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