os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclHash.c
Update contrib.
4 * Implementation of in-memory hash tables for Tcl and Tcl-based
7 * Copyright (c) 1991-1993 The Regents of the University of California.
8 * Copyright (c) 1994 Sun Microsystems, Inc.
9 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * RCS: @(#) $Id: tclHash.c,v 1.12.2.1 2004/11/11 01:18:07 das Exp $
20 * Prevent macros from clashing with function definitions.
23 #if TCL_PRESERVE_BINARY_COMPATABILITY
24 # undef Tcl_FindHashEntry
25 # undef Tcl_CreateHashEntry
29 * When there are this many entries per bucket, on average, rebuild
30 * the hash table to make it larger.
33 #define REBUILD_MULTIPLIER 3
36 * The following macro takes a preliminary integer hash value and
37 * produces an index into a hash tables bucket list. The idea is
38 * to make it so that preliminary values that are arbitrarily similar
39 * will end up in different buckets. The hash function was taken
40 * from a random-number generator.
43 #define RANDOM_INDEX(tablePtr, i) \
44 (((((long) (i))*1103515245) >> (tablePtr)->downShift) & (tablePtr)->mask)
47 * Prototypes for the array hash key methods.
50 static Tcl_HashEntry * AllocArrayEntry _ANSI_ARGS_((
51 Tcl_HashTable *tablePtr,
53 static int CompareArrayKeys _ANSI_ARGS_((
54 VOID *keyPtr, Tcl_HashEntry *hPtr));
55 static unsigned int HashArrayKey _ANSI_ARGS_((
56 Tcl_HashTable *tablePtr,
60 * Prototypes for the one word hash key methods.
64 static Tcl_HashEntry * AllocOneWordEntry _ANSI_ARGS_((
65 Tcl_HashTable *tablePtr,
67 static int CompareOneWordKeys _ANSI_ARGS_((
68 VOID *keyPtr, Tcl_HashEntry *hPtr));
69 static unsigned int HashOneWordKey _ANSI_ARGS_((
70 Tcl_HashTable *tablePtr,
75 * Prototypes for the string hash key methods.
78 static Tcl_HashEntry * AllocStringEntry _ANSI_ARGS_((
79 Tcl_HashTable *tablePtr,
81 static int CompareStringKeys _ANSI_ARGS_((
82 VOID *keyPtr, Tcl_HashEntry *hPtr));
83 static unsigned int HashStringKey _ANSI_ARGS_((
84 Tcl_HashTable *tablePtr,
88 * Procedure prototypes for static procedures in this file:
91 #if TCL_PRESERVE_BINARY_COMPATABILITY
92 static Tcl_HashEntry * BogusFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
94 static Tcl_HashEntry * BogusCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
95 CONST char *key, int *newPtr));
98 static void RebuildTable _ANSI_ARGS_((Tcl_HashTable *tablePtr));
100 Tcl_HashKeyType tclArrayHashKeyType = {
101 TCL_HASH_KEY_TYPE_VERSION, /* version */
102 TCL_HASH_KEY_RANDOMIZE_HASH, /* flags */
103 HashArrayKey, /* hashKeyProc */
104 CompareArrayKeys, /* compareKeysProc */
105 AllocArrayEntry, /* allocEntryProc */
106 NULL /* freeEntryProc */
109 Tcl_HashKeyType tclOneWordHashKeyType = {
110 TCL_HASH_KEY_TYPE_VERSION, /* version */
112 NULL, /* HashOneWordKey, */ /* hashProc */
113 NULL, /* CompareOneWordKey, */ /* compareProc */
114 NULL, /* AllocOneWordKey, */ /* allocEntryProc */
115 NULL /* FreeOneWordKey, */ /* freeEntryProc */
118 Tcl_HashKeyType tclStringHashKeyType = {
119 TCL_HASH_KEY_TYPE_VERSION, /* version */
121 HashStringKey, /* hashKeyProc */
122 CompareStringKeys, /* compareKeysProc */
123 AllocStringEntry, /* allocEntryProc */
124 NULL /* freeEntryProc */
129 *----------------------------------------------------------------------
131 * Tcl_InitHashTable --
133 * Given storage for a hash table, set up the fields to prepare
134 * the hash table for use.
140 * TablePtr is now ready to be passed to Tcl_FindHashEntry and
141 * Tcl_CreateHashEntry.
143 *----------------------------------------------------------------------
146 #undef Tcl_InitHashTable
148 Tcl_InitHashTable(tablePtr, keyType)
149 register Tcl_HashTable *tablePtr; /* Pointer to table record, which
150 * is supplied by the caller. */
151 int keyType; /* Type of keys to use in table:
152 * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS,
153 * or an integer >= 2. */
156 * Use a special value to inform the extended version that it must
157 * not access any of the new fields in the Tcl_HashTable. If an
158 * extension is rebuilt then any calls to this function will be
159 * redirected to the extended version by a macro.
161 Tcl_InitCustomHashTable(tablePtr, keyType, (Tcl_HashKeyType *) -1);
165 *----------------------------------------------------------------------
167 * Tcl_InitCustomHashTable --
169 * Given storage for a hash table, set up the fields to prepare
170 * the hash table for use. This is an extended version of
171 * Tcl_InitHashTable which supports user defined keys.
177 * TablePtr is now ready to be passed to Tcl_FindHashEntry and
178 * Tcl_CreateHashEntry.
180 *----------------------------------------------------------------------
184 Tcl_InitCustomHashTable(tablePtr, keyType, typePtr)
185 register Tcl_HashTable *tablePtr; /* Pointer to table record, which
186 * is supplied by the caller. */
187 int keyType; /* Type of keys to use in table:
188 * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS,
189 * TCL_CUSTOM_TYPE_KEYS,
190 * TCL_CUSTOM_PTR_KEYS, or an
192 Tcl_HashKeyType *typePtr; /* Pointer to structure which defines
193 * the behaviour of this table. */
195 #if (TCL_SMALL_HASH_TABLE != 4)
196 panic("Tcl_InitCustomHashTable: TCL_SMALL_HASH_TABLE is %d, not 4\n",
197 TCL_SMALL_HASH_TABLE);
200 tablePtr->buckets = tablePtr->staticBuckets;
201 tablePtr->staticBuckets[0] = tablePtr->staticBuckets[1] = 0;
202 tablePtr->staticBuckets[2] = tablePtr->staticBuckets[3] = 0;
203 tablePtr->numBuckets = TCL_SMALL_HASH_TABLE;
204 tablePtr->numEntries = 0;
205 tablePtr->rebuildSize = TCL_SMALL_HASH_TABLE*REBUILD_MULTIPLIER;
206 tablePtr->downShift = 28;
208 tablePtr->keyType = keyType;
209 #if TCL_PRESERVE_BINARY_COMPATABILITY
210 tablePtr->findProc = Tcl_FindHashEntry;
211 tablePtr->createProc = Tcl_CreateHashEntry;
213 if (typePtr == NULL) {
215 * The caller has been rebuilt so the hash table is an extended
218 } else if (typePtr != (Tcl_HashKeyType *) -1) {
220 * The caller is requesting a customized hash table so it must be
221 * an extended version.
223 tablePtr->typePtr = typePtr;
226 * The caller has not been rebuilt so the hash table is not
231 if (typePtr == NULL) {
233 * Use the key type to decide which key type is needed.
235 if (keyType == TCL_STRING_KEYS) {
236 typePtr = &tclStringHashKeyType;
237 } else if (keyType == TCL_ONE_WORD_KEYS) {
238 typePtr = &tclOneWordHashKeyType;
239 } else if (keyType == TCL_CUSTOM_TYPE_KEYS) {
240 Tcl_Panic ("No type structure specified for TCL_CUSTOM_TYPE_KEYS");
241 } else if (keyType == TCL_CUSTOM_PTR_KEYS) {
242 Tcl_Panic ("No type structure specified for TCL_CUSTOM_PTR_KEYS");
244 typePtr = &tclArrayHashKeyType;
246 } else if (typePtr == (Tcl_HashKeyType *) -1) {
248 * If the caller has not been rebuilt then we cannot continue as
249 * the hash table is not an extended version.
251 Tcl_Panic ("Hash table is not compatible");
253 tablePtr->typePtr = typePtr;
258 *----------------------------------------------------------------------
260 * Tcl_FindHashEntry --
262 * Given a hash table find the entry with a matching key.
265 * The return value is a token for the matching entry in the
266 * hash table, or NULL if there was no matching entry.
271 *----------------------------------------------------------------------
274 EXPORT_C Tcl_HashEntry *
275 Tcl_FindHashEntry(tablePtr, key)
276 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
277 CONST char *key; /* Key to use to find matching entry. */
279 register Tcl_HashEntry *hPtr;
280 Tcl_HashKeyType *typePtr;
284 #if TCL_PRESERVE_BINARY_COMPATABILITY
285 if (tablePtr->keyType == TCL_STRING_KEYS) {
286 typePtr = &tclStringHashKeyType;
287 } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
288 typePtr = &tclOneWordHashKeyType;
289 } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
290 || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
291 typePtr = tablePtr->typePtr;
293 typePtr = &tclArrayHashKeyType;
296 typePtr = tablePtr->typePtr;
297 if (typePtr == NULL) {
298 Tcl_Panic("called Tcl_FindHashEntry on deleted table");
303 if (typePtr->hashKeyProc) {
304 hash = typePtr->hashKeyProc (tablePtr, (VOID *) key);
305 if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
306 index = RANDOM_INDEX (tablePtr, hash);
308 index = hash & tablePtr->mask;
311 hash = (unsigned int) key;
312 index = RANDOM_INDEX (tablePtr, hash);
316 * Search all of the entries in the appropriate bucket.
319 if (typePtr->compareKeysProc) {
320 Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc;
321 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
322 hPtr = hPtr->nextPtr) {
323 #if TCL_HASH_KEY_STORE_HASH
324 if (hash != (unsigned int) hPtr->hash) {
328 if (compareKeysProc ((VOID *) key, hPtr)) {
333 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
334 hPtr = hPtr->nextPtr) {
335 #if TCL_HASH_KEY_STORE_HASH
336 if (hash != (unsigned int) hPtr->hash) {
340 if (key == hPtr->key.oneWordValue) {
350 *----------------------------------------------------------------------
352 * Tcl_CreateHashEntry --
354 * Given a hash table with string keys, and a string key, find
355 * the entry with a matching key. If there is no matching entry,
356 * then create a new entry that does match.
359 * The return value is a pointer to the matching entry. If this
360 * is a newly-created entry, then *newPtr will be set to a non-zero
361 * value; otherwise *newPtr will be set to 0. If this is a new
362 * entry the value stored in the entry will initially be 0.
365 * A new entry may be added to the hash table.
367 *----------------------------------------------------------------------
370 EXPORT_C Tcl_HashEntry *
371 Tcl_CreateHashEntry(tablePtr, key, newPtr)
372 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
373 CONST char *key; /* Key to use to find or create matching
375 int *newPtr; /* Store info here telling whether a new
376 * entry was created. */
378 register Tcl_HashEntry *hPtr;
379 Tcl_HashKeyType *typePtr;
383 #if TCL_PRESERVE_BINARY_COMPATABILITY
384 if (tablePtr->keyType == TCL_STRING_KEYS) {
385 typePtr = &tclStringHashKeyType;
386 } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
387 typePtr = &tclOneWordHashKeyType;
388 } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
389 || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
390 typePtr = tablePtr->typePtr;
392 typePtr = &tclArrayHashKeyType;
395 typePtr = tablePtr->typePtr;
396 if (typePtr == NULL) {
397 Tcl_Panic("called Tcl_CreateHashEntry on deleted table");
402 if (typePtr->hashKeyProc) {
403 hash = typePtr->hashKeyProc (tablePtr, (VOID *) key);
404 if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
405 index = RANDOM_INDEX (tablePtr, hash);
407 index = hash & tablePtr->mask;
410 hash = (unsigned int) key;
411 index = RANDOM_INDEX (tablePtr, hash);
415 * Search all of the entries in the appropriate bucket.
418 if (typePtr->compareKeysProc) {
419 Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc;
420 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
421 hPtr = hPtr->nextPtr) {
422 #if TCL_HASH_KEY_STORE_HASH
423 if (hash != (unsigned int) hPtr->hash) {
427 if (compareKeysProc ((VOID *) key, hPtr)) {
433 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
434 hPtr = hPtr->nextPtr) {
435 #if TCL_HASH_KEY_STORE_HASH
436 if (hash != (unsigned int) hPtr->hash) {
440 if (key == hPtr->key.oneWordValue) {
448 * Entry not found. Add a new one to the bucket.
452 if (typePtr->allocEntryProc) {
453 hPtr = typePtr->allocEntryProc (tablePtr, (VOID *) key);
455 hPtr = (Tcl_HashEntry *) ckalloc((unsigned) sizeof(Tcl_HashEntry));
456 hPtr->key.oneWordValue = (char *) key;
459 hPtr->tablePtr = tablePtr;
460 #if TCL_HASH_KEY_STORE_HASH
461 # if TCL_PRESERVE_BINARY_COMPATABILITY
462 hPtr->hash = (VOID *) hash;
466 hPtr->nextPtr = tablePtr->buckets[index];
467 tablePtr->buckets[index] = hPtr;
469 hPtr->bucketPtr = &(tablePtr->buckets[index]);
470 hPtr->nextPtr = *hPtr->bucketPtr;
471 *hPtr->bucketPtr = hPtr;
473 hPtr->clientData = 0;
474 tablePtr->numEntries++;
477 * If the table has exceeded a decent size, rebuild it with many
481 if (tablePtr->numEntries >= tablePtr->rebuildSize) {
482 RebuildTable(tablePtr);
488 *----------------------------------------------------------------------
490 * Tcl_DeleteHashEntry --
492 * Remove a single entry from a hash table.
498 * The entry given by entryPtr is deleted from its table and
499 * should never again be used by the caller. It is up to the
500 * caller to free the clientData field of the entry, if that
503 *----------------------------------------------------------------------
507 Tcl_DeleteHashEntry(entryPtr)
508 Tcl_HashEntry *entryPtr;
510 register Tcl_HashEntry *prevPtr;
511 Tcl_HashKeyType *typePtr;
512 Tcl_HashTable *tablePtr;
513 Tcl_HashEntry **bucketPtr;
514 #if TCL_HASH_KEY_STORE_HASH
518 tablePtr = entryPtr->tablePtr;
520 #if TCL_PRESERVE_BINARY_COMPATABILITY
521 if (tablePtr->keyType == TCL_STRING_KEYS) {
522 typePtr = &tclStringHashKeyType;
523 } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
524 typePtr = &tclOneWordHashKeyType;
525 } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
526 || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
527 typePtr = tablePtr->typePtr;
529 typePtr = &tclArrayHashKeyType;
532 typePtr = tablePtr->typePtr;
535 #if TCL_HASH_KEY_STORE_HASH
536 if (typePtr->hashKeyProc == NULL
537 || typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
538 index = RANDOM_INDEX (tablePtr, entryPtr->hash);
540 index = ((unsigned int) entryPtr->hash) & tablePtr->mask;
543 bucketPtr = &(tablePtr->buckets[index]);
545 bucketPtr = entryPtr->bucketPtr;
548 if (*bucketPtr == entryPtr) {
549 *bucketPtr = entryPtr->nextPtr;
551 for (prevPtr = *bucketPtr; ; prevPtr = prevPtr->nextPtr) {
552 if (prevPtr == NULL) {
553 panic("malformed bucket chain in Tcl_DeleteHashEntry");
555 if (prevPtr->nextPtr == entryPtr) {
556 prevPtr->nextPtr = entryPtr->nextPtr;
562 tablePtr->numEntries--;
563 if (typePtr->freeEntryProc) {
564 typePtr->freeEntryProc (entryPtr);
566 ckfree((char *) entryPtr);
571 *----------------------------------------------------------------------
573 * Tcl_DeleteHashTable --
575 * Free up everything associated with a hash table except for
576 * the record for the table itself.
582 * The hash table is no longer useable.
584 *----------------------------------------------------------------------
588 Tcl_DeleteHashTable(tablePtr)
589 register Tcl_HashTable *tablePtr; /* Table to delete. */
591 register Tcl_HashEntry *hPtr, *nextPtr;
592 Tcl_HashKeyType *typePtr;
595 #if TCL_PRESERVE_BINARY_COMPATABILITY
596 if (tablePtr->keyType == TCL_STRING_KEYS) {
597 typePtr = &tclStringHashKeyType;
598 } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
599 typePtr = &tclOneWordHashKeyType;
600 } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
601 || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
602 typePtr = tablePtr->typePtr;
604 typePtr = &tclArrayHashKeyType;
607 typePtr = tablePtr->typePtr;
611 * Free up all the entries in the table.
614 for (i = 0; i < tablePtr->numBuckets; i++) {
615 hPtr = tablePtr->buckets[i];
616 while (hPtr != NULL) {
617 nextPtr = hPtr->nextPtr;
618 if (typePtr->freeEntryProc) {
619 typePtr->freeEntryProc (hPtr);
621 ckfree((char *) hPtr);
628 * Free up the bucket array, if it was dynamically allocated.
631 if (tablePtr->buckets != tablePtr->staticBuckets) {
632 ckfree((char *) tablePtr->buckets);
636 * Arrange for panics if the table is used again without
640 #if TCL_PRESERVE_BINARY_COMPATABILITY
641 tablePtr->findProc = BogusFind;
642 tablePtr->createProc = BogusCreate;
644 tablePtr->typePtr = NULL;
649 *----------------------------------------------------------------------
651 * Tcl_FirstHashEntry --
653 * Locate the first entry in a hash table and set up a record
654 * that can be used to step through all the remaining entries
658 * The return value is a pointer to the first entry in tablePtr,
659 * or NULL if tablePtr has no entries in it. The memory at
660 * *searchPtr is initialized so that subsequent calls to
661 * Tcl_NextHashEntry will return all of the entries in the table,
667 *----------------------------------------------------------------------
670 EXPORT_C Tcl_HashEntry *
671 Tcl_FirstHashEntry(tablePtr, searchPtr)
672 Tcl_HashTable *tablePtr; /* Table to search. */
673 Tcl_HashSearch *searchPtr; /* Place to store information about
674 * progress through the table. */
676 searchPtr->tablePtr = tablePtr;
677 searchPtr->nextIndex = 0;
678 searchPtr->nextEntryPtr = NULL;
679 return Tcl_NextHashEntry(searchPtr);
683 *----------------------------------------------------------------------
685 * Tcl_NextHashEntry --
687 * Once a hash table enumeration has been initiated by calling
688 * Tcl_FirstHashEntry, this procedure may be called to return
689 * successive elements of the table.
692 * The return value is the next entry in the hash table being
693 * enumerated, or NULL if the end of the table is reached.
698 *----------------------------------------------------------------------
701 EXPORT_C Tcl_HashEntry *
702 Tcl_NextHashEntry(searchPtr)
703 register Tcl_HashSearch *searchPtr; /* Place to store information about
704 * progress through the table. Must
705 * have been initialized by calling
706 * Tcl_FirstHashEntry. */
709 Tcl_HashTable *tablePtr = searchPtr->tablePtr;
711 while (searchPtr->nextEntryPtr == NULL) {
712 if (searchPtr->nextIndex >= tablePtr->numBuckets) {
715 searchPtr->nextEntryPtr =
716 tablePtr->buckets[searchPtr->nextIndex];
717 searchPtr->nextIndex++;
719 hPtr = searchPtr->nextEntryPtr;
720 searchPtr->nextEntryPtr = hPtr->nextPtr;
725 *----------------------------------------------------------------------
729 * Return statistics describing the layout of the hash table
730 * in its hash buckets.
733 * The return value is a malloc-ed string containing information
734 * about tablePtr. It is the caller's responsibility to free
740 *----------------------------------------------------------------------
743 EXPORT_C CONST char *
744 Tcl_HashStats(tablePtr)
745 Tcl_HashTable *tablePtr; /* Table for which to produce stats. */
747 #define NUM_COUNTERS 10
748 int count[NUM_COUNTERS], overflow, i, j;
750 register Tcl_HashEntry *hPtr;
754 * Compute a histogram of bucket usage.
757 for (i = 0; i < NUM_COUNTERS; i++) {
762 for (i = 0; i < tablePtr->numBuckets; i++) {
764 for (hPtr = tablePtr->buckets[i]; hPtr != NULL; hPtr = hPtr->nextPtr) {
767 if (j < NUM_COUNTERS) {
773 average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
777 * Print out the histogram and a few other pieces of information.
780 result = (char *) ckalloc((unsigned) ((NUM_COUNTERS*60) + 300));
781 sprintf(result, "%d entries in table, %d buckets\n",
782 tablePtr->numEntries, tablePtr->numBuckets);
783 p = result + strlen(result);
784 for (i = 0; i < NUM_COUNTERS; i++) {
785 sprintf(p, "number of buckets with %d entries: %d\n",
789 sprintf(p, "number of buckets with %d or more entries: %d\n",
790 NUM_COUNTERS, overflow);
792 sprintf(p, "average search distance for entry: %.1f", average);
797 *----------------------------------------------------------------------
801 * Allocate space for a Tcl_HashEntry containing the array key.
804 * The return value is a pointer to the created entry.
809 *----------------------------------------------------------------------
812 static Tcl_HashEntry *
813 AllocArrayEntry(tablePtr, keyPtr)
814 Tcl_HashTable *tablePtr; /* Hash table. */
815 VOID *keyPtr; /* Key to store in the hash table entry. */
817 int *array = (int *) keyPtr;
818 register int *iPtr1, *iPtr2;
823 count = tablePtr->keyType;
825 size = sizeof(Tcl_HashEntry) + (count*sizeof(int)) - sizeof(hPtr->key);
826 if (size < sizeof(Tcl_HashEntry))
827 size = sizeof(Tcl_HashEntry);
828 hPtr = (Tcl_HashEntry *) ckalloc(size);
830 for (iPtr1 = array, iPtr2 = hPtr->key.words;
831 count > 0; count--, iPtr1++, iPtr2++) {
839 *----------------------------------------------------------------------
841 * CompareArrayKeys --
843 * Compares two array keys.
846 * The return value is 0 if they are different and 1 if they are
852 *----------------------------------------------------------------------
856 CompareArrayKeys(keyPtr, hPtr)
857 VOID *keyPtr; /* New key to compare. */
858 Tcl_HashEntry *hPtr; /* Existing key to compare. */
860 register CONST int *iPtr1 = (CONST int *) keyPtr;
861 register CONST int *iPtr2 = (CONST int *) hPtr->key.words;
862 Tcl_HashTable *tablePtr = hPtr->tablePtr;
865 for (count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) {
869 if (*iPtr1 != *iPtr2) {
877 *----------------------------------------------------------------------
881 * Compute a one-word summary of an array, which can be
882 * used to generate a hash index.
885 * The return value is a one-word summary of the information in
891 *----------------------------------------------------------------------
895 HashArrayKey(tablePtr, keyPtr)
896 Tcl_HashTable *tablePtr; /* Hash table. */
897 VOID *keyPtr; /* Key from which to compute hash value. */
899 register CONST int *array = (CONST int *) keyPtr;
900 register unsigned int result;
903 for (result = 0, count = tablePtr->keyType; count > 0;
911 *----------------------------------------------------------------------
913 * AllocStringEntry --
915 * Allocate space for a Tcl_HashEntry containing the string key.
918 * The return value is a pointer to the created entry.
923 *----------------------------------------------------------------------
926 static Tcl_HashEntry *
927 AllocStringEntry(tablePtr, keyPtr)
928 Tcl_HashTable *tablePtr; /* Hash table. */
929 VOID *keyPtr; /* Key to store in the hash table entry. */
931 CONST char *string = (CONST char *) keyPtr;
935 size = sizeof(Tcl_HashEntry) + strlen(string) + 1 - sizeof(hPtr->key);
936 if (size < sizeof(Tcl_HashEntry))
937 size = sizeof(Tcl_HashEntry);
938 hPtr = (Tcl_HashEntry *) ckalloc(size);
939 strcpy(hPtr->key.string, string);
945 *----------------------------------------------------------------------
947 * CompareStringKeys --
949 * Compares two string keys.
952 * The return value is 0 if they are different and 1 if they are
958 *----------------------------------------------------------------------
962 CompareStringKeys(keyPtr, hPtr)
963 VOID *keyPtr; /* New key to compare. */
964 Tcl_HashEntry *hPtr; /* Existing key to compare. */
966 register CONST char *p1 = (CONST char *) keyPtr;
967 register CONST char *p2 = (CONST char *) hPtr->key.string;
969 for (;; p1++, p2++) {
981 *----------------------------------------------------------------------
985 * Compute a one-word summary of a text string, which can be
986 * used to generate a hash index.
989 * The return value is a one-word summary of the information in
995 *----------------------------------------------------------------------
999 HashStringKey(tablePtr, keyPtr)
1000 Tcl_HashTable *tablePtr; /* Hash table. */
1001 VOID *keyPtr; /* Key from which to compute hash value. */
1003 register CONST char *string = (CONST char *) keyPtr;
1004 register unsigned int result;
1008 * I tried a zillion different hash functions and asked many other
1009 * people for advice. Many people had their own favorite functions,
1010 * all different, but no-one had much idea why they were good ones.
1011 * I chose the one below (multiply by 9 and add new character)
1012 * because of the following reasons:
1014 * 1. Multiplying by 10 is perfect for keys that are decimal strings,
1015 * and multiplying by 9 is just about as good.
1016 * 2. Times-9 is (shift-left-3) plus (old). This means that each
1017 * character's bits hang around in the low-order bits of the
1018 * hash value for ever, plus they spread fairly rapidly up to
1019 * the high-order bits to fill out the hash value. This seems
1020 * works well both for decimal and non-decimal strings.
1029 result += (result<<3) + c;
1035 #if TCL_PRESERVE_BINARY_COMPATABILITY
1037 *----------------------------------------------------------------------
1041 * This procedure is invoked when an Tcl_FindHashEntry is called
1042 * on a table that has been deleted.
1045 * If panic returns (which it shouldn't) this procedure returns
1049 * Generates a panic.
1051 *----------------------------------------------------------------------
1055 static Tcl_HashEntry *
1056 BogusFind(tablePtr, key)
1057 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
1058 CONST char *key; /* Key to use to find matching entry. */
1060 panic("called Tcl_FindHashEntry on deleted table");
1065 *----------------------------------------------------------------------
1069 * This procedure is invoked when an Tcl_CreateHashEntry is called
1070 * on a table that has been deleted.
1073 * If panic returns (which it shouldn't) this procedure returns
1077 * Generates a panic.
1079 *----------------------------------------------------------------------
1083 static Tcl_HashEntry *
1084 BogusCreate(tablePtr, key, newPtr)
1085 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
1086 CONST char *key; /* Key to use to find or create matching
1088 int *newPtr; /* Store info here telling whether a new
1089 * entry was created. */
1091 panic("called Tcl_CreateHashEntry on deleted table");
1097 *----------------------------------------------------------------------
1101 * This procedure is invoked when the ratio of entries to hash
1102 * buckets becomes too large. It creates a new table with a
1103 * larger bucket array and moves all of the entries into the
1110 * Memory gets reallocated and entries get re-hashed to new
1113 *----------------------------------------------------------------------
1117 RebuildTable(tablePtr)
1118 register Tcl_HashTable *tablePtr; /* Table to enlarge. */
1120 int oldSize, count, index;
1121 Tcl_HashEntry **oldBuckets;
1122 register Tcl_HashEntry **oldChainPtr, **newChainPtr;
1123 register Tcl_HashEntry *hPtr;
1124 Tcl_HashKeyType *typePtr;
1127 oldSize = tablePtr->numBuckets;
1128 oldBuckets = tablePtr->buckets;
1131 * Allocate and initialize the new bucket array, and set up
1132 * hashing constants for new array size.
1135 tablePtr->numBuckets *= 4;
1136 tablePtr->buckets = (Tcl_HashEntry **) ckalloc((unsigned)
1137 (tablePtr->numBuckets * sizeof(Tcl_HashEntry *)));
1138 for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets;
1139 count > 0; count--, newChainPtr++) {
1140 *newChainPtr = NULL;
1142 tablePtr->rebuildSize *= 4;
1143 tablePtr->downShift -= 2;
1144 tablePtr->mask = (tablePtr->mask << 2) + 3;
1146 #if TCL_PRESERVE_BINARY_COMPATABILITY
1147 if (tablePtr->keyType == TCL_STRING_KEYS) {
1148 typePtr = &tclStringHashKeyType;
1149 } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
1150 typePtr = &tclOneWordHashKeyType;
1151 } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
1152 || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
1153 typePtr = tablePtr->typePtr;
1155 typePtr = &tclArrayHashKeyType;
1158 typePtr = tablePtr->typePtr;
1162 * Rehash all of the existing entries into the new bucket array.
1165 for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) {
1166 for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) {
1167 *oldChainPtr = hPtr->nextPtr;
1169 key = (VOID *) Tcl_GetHashKey (tablePtr, hPtr);
1171 #if TCL_HASH_KEY_STORE_HASH
1172 if (typePtr->hashKeyProc == NULL
1173 || typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
1174 index = RANDOM_INDEX (tablePtr, hPtr->hash);
1176 index = ((unsigned int) hPtr->hash) & tablePtr->mask;
1178 hPtr->nextPtr = tablePtr->buckets[index];
1179 tablePtr->buckets[index] = hPtr;
1181 if (typePtr->hashKeyProc) {
1183 hash = typePtr->hashKeyProc (tablePtr, (VOID *) key);
1184 if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
1185 index = RANDOM_INDEX (tablePtr, hash);
1187 index = hash & tablePtr->mask;
1190 index = RANDOM_INDEX (tablePtr, key);
1193 hPtr->bucketPtr = &(tablePtr->buckets[index]);
1194 hPtr->nextPtr = *hPtr->bucketPtr;
1195 *hPtr->bucketPtr = hPtr;
1201 * Free up the old bucket array, if it was dynamically allocated.
1204 if (oldBuckets != tablePtr->staticBuckets) {
1205 ckfree((char *) oldBuckets);