* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- $Header: /usr/user/dennis_glatting/ObjC/c-runtime/lib/RCS/hash.c,v 0.7 1991/11/23 22:18:29 dennisg Exp dennisg $
+ $Header: /usr/user/dennis_glatting/ObjC/c-runtime/lib/RCS/hash.c,v 0.8 1991/11/24 01:20:02 dennisg Exp dennisg $
$Author: dennisg $
- $Date: 1991/11/23 22:18:29 $
+ $Date: 1991/11/24 01:20:02 $
$Log: hash.c,v $
+ * Revision 0.8 1991/11/24 01:20:02 dennisg
+ * changed shorts back to ints.
+ * the efficiency gained didn't out weight the grossness of the code.
+ *
* Revision 0.7 1991/11/23 22:18:29 dennisg
* deleted hashIndex() and moved it to hash-inline.h
- * converted hash_value_for_key() to a inline and moved it to hash-inline.h.
+ * converted hash_value_for_key () to a inline and moved it to hash-inline.h.
*
* Revision 0.6 1991/11/21 22:27:06 dennisg
* changed hash value calculation.
- * func name changed from hashValue() to hashIndex(). the
+ * func name changed from hashValue () to hashIndex(). the
* func really calculated a index anyway.
* changed hash func impl. essentially it was calculating a hash value
* from a hash value. this is a implementation thing.
* converted hashIndex() to a inline.
*
* Revision 0.4 1991/11/19 12:34:41 dennisg
- * bug in hash_delete(). It was using void* to obtain nodes to
- * pass to hash_remove(). The value passed to hash_removed() is a
+ * bug in hash_delete (). It was using void* to obtain nodes to
+ * pass to hash_remove (). The value passed to hash_removed () is a
* entry from the node structure rather than the node itself. Using
* void* removed compiler checking.
* Modified to implement cache expansion.
These equations are
percentages. */
#define FULLNESS(cache) \
- ((((cache)->sizeOfHash * 75 ) / 100 ) <= (cache)->entriesInHash)
+ ((((cache)->sizeOfHash * 75 ) / 100) <= (cache)->entriesInHash)
#define EXPANSION(cache) \
(((cache)->sizeOfHash * 175 ) / 100 )
+#define MEMORY_ALLOCATION_ADJUST(i) \
+ ((i&0x01)?i:(i-1))
-Cache_t hash_new( u_int sizeOfHash ) {
+Cache_t hash_new (u_int sizeOfHash) {
Cache_t retCache;
+
-
- assert( sizeOfHash );
+ assert(sizeOfHash);
+
+ /* Memory is allocated on this
+ machine in even address
+ chunks. Therefore the
+ modulus must be odd. */
+ sizeOfHash = MEMORY_ALLOCATION_ADJUST(sizeOfHash);
/* Allocate the cache
- structure. calloc() insures
+ structure. calloc () insures
its initialization for
default values. */
- retCache = calloc( 1, sizeof( Cache ));
- assert( retCache );
+ retCache = calloc (1, sizeof (Cache));
+ assert(retCache);
/* Allocate the array of
buckets for the cache.
- calloc() initializes all of
+ calloc () initializes all of
the pointers to NULL. */
- retCache->theNodeTable = calloc( sizeOfHash, sizeof( CacheNode_t ));
- assert( retCache->theNodeTable );
+ retCache->theNodeTable = calloc (sizeOfHash, sizeof (CacheNode_t));
+ assert(retCache->theNodeTable);
- retCache->sizeOfHash = sizeOfHash;
+ retCache->sizeOfHash = sizeOfHash;
return retCache;
}
-void hash_delete( Cache_t theCache ) {
+void hash_delete (Cache_t theCache) {
CacheNode_t aNode;
/* Purge all key/value pairs
from the table. */
- while( aNode = hash_next( theCache, NULL ))
- hash_remove( theCache, aNode->theKey );
+ while (aNode = hash_next (theCache, NULL))
+ hash_remove (theCache, aNode->theKey);
/* Release the array of nodes
and the cache itself. */
- free( theCache->theNodeTable );
- free( theCache );
+ free (theCache->theNodeTable);
+ free (theCache);
}
-void hash_add( Cache_t* theCache, void* aKey, void* aValue ) {
+void hash_add (Cache_t* theCache, void* aKey, void* aValue) {
- u_int indx = hashIndex( *theCache, aKey );
- CacheNode_t aCacheNode = calloc( 1, sizeof( CacheNode ));
+ u_int indx = hashIndex(*theCache, aKey);
+ CacheNode_t aCacheNode = calloc (1, sizeof (CacheNode));
- assert( aCacheNode );
+ assert(aCacheNode);
/* Initialize the new node. */
aCacheNode->theKey = aKey;
aCacheNode->theValue = aValue;
- aCacheNode->nextNode = ( *( *theCache )->theNodeTable )[ indx ];
+ aCacheNode->nextNode = (* (*theCache)->theNodeTable)[ indx ];
/* Debugging.
Check the list for another
key. */
#ifdef DEBUG
- { CacheNode_t checkHashNode = ( *( *theCache )->theNodeTable )[ indx ];
+ { CacheNode_t checkHashNode = (* (*theCache)->theNodeTable)[ indx ];
- while( checkHashNode ) {
+ while (checkHashNode) {
- assert( checkHashNode->theKey != aKey );
+ assert(checkHashNode->theKey != aKey);
checkHashNode = checkHashNode->nextNode;
}
}
/* Install the node as the
first element on the list. */
- ( *( *theCache )->theNodeTable )[ indx ] = aCacheNode;
+ (* (*theCache)->theNodeTable)[ indx ] = aCacheNode;
/* Bump the number of entries
in the cache. */
- ++( *theCache )->entriesInHash;
+ ++ (*theCache)->entriesInHash;
/* Check the hash table's
fullness. We're going
to expand if it is above
the fullness level. */
- if(FULLNESS( *theCache )) {
+ if (FULLNESS (*theCache)) {
/* The hash table has reached
its fullness level. Time to
expand it.
primitive functions thereby
increasing its
correctness. */
- Cache_t newCache = hash_new(EXPANSION( *theCache ));
CacheNode_t aNode = NULL;
+ Cache_t newCache =
+ hash_new (MEMORY_ALLOCATION_ADJUST( EXPANSION (*theCache)));
DEBUG_PRINTF (stderr, "Expanding cache %#x from %d to %d\n",
- *theCache, ( *theCache )->sizeOfHash, newCache->sizeOfHash);
+ *theCache, (*theCache)->sizeOfHash, newCache->sizeOfHash);
/* Copy the nodes from the
first hash table to the
new one. */
- while( aNode = hash_next( *theCache, aNode ))
- hash_add( &newCache, aNode->theKey, aNode->theValue );
+ while (aNode = hash_next (*theCache, aNode))
+ hash_add (&newCache, aNode->theKey, aNode->theValue);
/* Trash the old cache. */
- hash_delete( *theCache );
+ hash_delete (*theCache);
/* Return a pointer to the new
hash table. */
}
-void hash_remove( Cache_t theCache, void* aKey ) {
+void hash_remove (Cache_t theCache, void* aKey) {
- u_int indx = hashIndex( theCache, aKey );
- CacheNode_t aCacheNode = ( *theCache->theNodeTable )[ indx ];
+ u_int indx = hashIndex(theCache, aKey);
+ CacheNode_t aCacheNode = (*theCache->theNodeTable)[ indx ];
/* We assume there is an entry
in the table. Error if it
is not. */
- assert( aCacheNode );
+ assert(aCacheNode);
/* Special case. First element
is the key/value pair to be
removed. */
- if( aCacheNode->theKey == aKey ) {
- ( *theCache->theNodeTable )[ indx ] = aCacheNode->nextNode;
- free( aCacheNode );
+ if (aCacheNode->theKey == aKey) {
+ (*theCache->theNodeTable)[ indx ] = aCacheNode->nextNode;
+ free (aCacheNode);
} else {
/* Otherwise, find the hash
entry. */
do {
- if( aCacheNode->theKey == aKey ) {
+ if (aCacheNode->theKey == aKey) {
prevHashNode->nextNode = aCacheNode->nextNode, removed = YES;
- free( aCacheNode );
+ free (aCacheNode);
} else
prevHashNode = aCacheNode, aCacheNode = aCacheNode->nextNode;
- } while( !removed && aCacheNode );
- assert( removed );
+ } while (!removed && aCacheNode);
+ assert(removed);
}
/* Decrement the number of
}
-CacheNode_t hash_next( Cache_t theCache, CacheNode_t aCacheNode ) {
+CacheNode_t hash_next (Cache_t theCache, CacheNode_t aCacheNode) {
CacheNode_t theCacheNode = aCacheNode;
then reset the last node
visitied pointer and bucket
index. */
- if( !theCacheNode )
+ if (!theCacheNode)
theCache->lastBucket = 0;
/* If there is a node visited
entry in the same bucket;
Otherwise step to the next
bucket. */
- if( theCacheNode )
- if( theCacheNode->nextNode )
+ if (theCacheNode)
+ if (theCacheNode->nextNode)
/* There is a node which
follows the last node
returned. Step to that node
/* If the list isn't exhausted
then search the buckets for
other nodes. */
- if( theCache->lastBucket < theCache->sizeOfHash ) {
+ if (theCache->lastBucket < theCache->sizeOfHash) {
/* Scan the remainder of the
buckets looking for an entry
at the head of the list.
Return the first item
found. */
- while( theCache->lastBucket < theCache->sizeOfHash )
- if(( *theCache->theNodeTable )[ theCache->lastBucket ])
- return ( *theCache->theNodeTable )[ theCache->lastBucket ];
+ while (theCache->lastBucket < theCache->sizeOfHash)
+ if ((*theCache->theNodeTable)[ theCache->lastBucket ])
+ return (*theCache->theNodeTable)[ theCache->lastBucket ];
else
++theCache->lastBucket;
* void*. The hashing function converts the key to
* an integer and computes it hash value.
*
- * Copyright (C) 1991 Threaded Technologies Inc.
+ * Copyright (C) 1991 Threaded Technologies Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- $Header: /usr/user/dennis_glatting/ObjC/c-runtime/lib/RCS/hash.h,v 0.5 1991/11/23 22:19:21 dennisg Exp dennisg $
+ $Header: /usr/user/dennis_glatting/ObjC/c-runtime/lib/RCS/hash.h,v 0.6 1991/11/24 01:20:02 dennisg Exp dennisg $
$Author: dennisg $
- $Date: 1991/11/23 22:19:21 $
+ $Date: 1991/11/24 01:20:02 $
$Log: hash.h,v $
+ * Revision 0.6 1991/11/24 01:20:02 dennisg
+ * changed shorts back to ints.
+ * the efficiency gained didn't out weight the grossness of the code.
+ *
* Revision 0.5 1991/11/23 22:19:21 dennisg
* converted some entries in the hash structure from ints to shorts.
* this was done to use a less expensive division instruction
- * in the hashIndex() routine.
+ * in the hashIndex () routine.
*
* Revision 0.4 1991/11/21 22:25:19 dennisg
* deleted hash mask information from hash struct.
* This data structure is the cache.
*
* It must be passed to all of the hashing routines
- * (except for new).
+ * (except for new).
*/
typedef struct cache {
/*
* Variables used to implement the
* hash itself.
*/
- CacheNode_t (* theNodeTable )[]; /* Pointer to an array of
+ CacheNode_t (* theNodeTable)[]; /* Pointer to an array of
hash nodes. */
/*
* Variables used to track the size of the hash
* table so to determine when to resize it.
*/
- u_int sizeOfHash, /* Number of buckets
+ u_int sizeOfHash, /* Number of buckets
allocated for the hash
- table (number of array
+ table (number of array
entries allocated for
- "theNodeTable"). */
+ "theNodeTable"). Must be
+ a power of two. */
entriesInHash; /* Current number of entries
in ther hash table. */
/*
functions. */
/* Allocate and initialize
a hash table. Hash table
- size taken as a parameter.
- A value of 0 is not
- allowed. */
-Cache_t hash_new( u_int sizeOfHash );
+ size taken as a parameter. */
+Cache_t hash_new (u_int sizeOfHash);
/* Deallocate all of the
hash nodes and the cache
itself. */
-void hash_delete( Cache_t theCache );
+void hash_delete (Cache_t theCache);
/* Add the key/value pair
to the hash table. If the
hash table reaches a
assert() if the key is
already in the hash. */
-void hash_add( Cache_t* theCache, void* aKey, void* aValue );
+void hash_add (Cache_t* theCache, void* aKey, void* aValue);
/* Remove the key/value pair
from the hash table.
assert() if the key isn't
in the table. */
-void hash_remove( Cache_t theCache, void* aKey );
+void hash_remove (Cache_t theCache, void* aKey);
/* Used to index through the
hash table. Start with NULL
to get the first entry.
Cache nodes are returned
such that key or value can
ber extracted. */
-CacheNode_t hash_next( Cache_t theCache, CacheNode_t aCacheNode );
+CacheNode_t hash_next (Cache_t theCache, CacheNode_t aCacheNode);
#ifdef __cplusplus