Expect more changes as hash version and other changes are made.
From-SVN: r734
* 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.10 1991/12/10 12:05:28 dennisg Exp dennisg $
+ $Header: /usr/user/dennis_glatting/ObjC/c-runtime/hash/RCS/hash.c,v 0.11 1992/01/03 02:55:03 dennisg Exp dennisg $
$Author: dennisg $
- $Date: 1991/12/10 12:05:28 $
+ $Date: 1992/01/03 02:55:03 $
$Log: hash.c,v $
+ * Revision 0.11 1992/01/03 02:55:03 dennisg
+ * modified to handle new initialization scheme.
+ * fixed code structure.
+ *
* Revision 0.10 1991/12/10 12:05:28 dennisg
* Cleaned up file format for a distribution.
*
#include <hash.h>
-#include <hash-inline.h>
-#include <ObjC.h>
-#include <ObjC-private.h>
+#include <objc.h>
+#include <objcP.h>
+#include <objc-protoP.h>
#include <assert.h>
#include <math.h>
#define FULLNESS(cache) \
((((cache)->sizeOfHash * 75 ) / 100) <= (cache)->entriesInHash)
#define EXPANSION(cache) \
- (((cache)->sizeOfHash * 175 ) / 100 )
-
-#define MEMORY_ALLOCATION_ADJUST(i) \
- ((i&0x01)?i:(i-1))
+ ((cache)->sizeOfHash * 2 )
-Cache_t hash_new (u_int sizeOfHash) {
+Cache_t
+hash_new (u_int sizeOfHash, HashFunc aHashFunc, CompareFunc aCompareFunc) {
Cache_t retCache;
+ /* Pass me a value greater
+ than 0 and a power of 2. */
assert(sizeOfHash);
+ assert( !(sizeOfHash & (sizeOfHash - 1)));
- /* 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
its initialization for
/* 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->sizeOfHash = sizeOfHash;
+ /* This should work for all
+ processor architectures? */
+ retCache->mask = ( sizeOfHash - 1 );
+
+ /* Store the hashing function
+ so that codes can be
+ computed. */
+ retCache->hashFunc = aHashFunc;
+
+ /* Store the function that
+ compares hash keys to
+ determine if they are
+ equal. */
+ retCache->compareFunc = aCompareFunc;
+
return retCache;
}
-void hash_delete (Cache_t theCache) {
+void
+hash_delete (Cache_t theCache) {
CacheNode_t aNode;
- /* Purge all key/value pairs
+ /* Purge all key/value pairs
from the table. */
while (aNode = hash_next (theCache, NULL))
hash_remove (theCache, aNode->theKey);
}
-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);
+ u_int indx = (* (*theCache)->hashFunc)(*theCache, aKey);
CacheNode_t aCacheNode = calloc (1, sizeof (CacheNode));
increasing its
correctness. */
CacheNode_t aNode = NULL;
- Cache_t newCache =
- hash_new (MEMORY_ALLOCATION_ADJUST( EXPANSION (*theCache)));
+ Cache_t newCache = hash_new (EXPANSION (*theCache),
+ (*theCache)->hashFunc,
+ (*theCache)->compareFunc);
DEBUG_PRINTF (stderr, "Expanding cache %#x from %d to %d\n",
*theCache, (*theCache)->sizeOfHash, newCache->sizeOfHash);
}
-void hash_remove (Cache_t theCache, void* aKey) {
+void
+hash_remove (Cache_t theCache, void* aKey) {
- u_int indx = hashIndex(theCache, aKey);
+ u_int indx = (*theCache->hashFunc)(theCache, aKey);
CacheNode_t aCacheNode = (*theCache->theNodeTable)[ indx ];
/* Special case. First element
is the key/value pair to be
removed. */
- if (aCacheNode->theKey == aKey) {
+ if ((*theCache->compareFunc)(aCacheNode->theKey, aKey)) {
(*theCache->theNodeTable)[ indx ] = aCacheNode->nextNode;
free (aCacheNode);
} else {
do {
- if (aCacheNode->theKey == aKey) {
+ if ((*theCache->compareFunc)(aCacheNode->theKey, aKey)) {
prevHashNode->nextNode = aCacheNode->nextNode, removed = YES;
free (aCacheNode);
} else
}
-CacheNode_t hash_next (Cache_t theCache, CacheNode_t aCacheNode) {
+CacheNode_t
+hash_next (Cache_t theCache, CacheNode_t aCacheNode) {
CacheNode_t theCacheNode = aCacheNode;
}
+ /* Given key, return its
+ value. Return NULL if the
+ key/value pair isn't in
+ the hash. */
+void*
+hash_value_for_key (Cache_t theCache, void* aKey) {
+
+ CacheNode_t aCacheNode =
+ (*theCache->theNodeTable)[(*theCache->hashFunc)(theCache, aKey)];
+ void* retVal = NULL;
+
+
+ if (aCacheNode)
+ do {
+ if ((*theCache->compareFunc)(aCacheNode->theKey, aKey))
+ retVal = aCacheNode->theValue;
+ else
+ aCacheNode = aCacheNode->nextNode;
+ } while (!retVal && aCacheNode);
+
+ return retVal;
+}
* 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.7 1991/12/03 02:01:23 dennisg Exp dennisg $
+ $Header: /usr/user/dennis_glatting/ObjC/c-runtime/hash/RCS/hash.h,v 0.8 1991/12/10 12:05:28 dennisg Exp dennisg $
$Author: dennisg $
- $Date: 1991/12/03 02:01:23 $
+ $Date: 1991/12/10 12:05:28 $
$Log: hash.h,v $
+ * Revision 0.8 1991/12/10 12:05:28 dennisg
+ * Cleaned up file format for a distribution.
+ *
* Revision 0.7 1991/12/03 02:01:23 dennisg
* fixed assert macro.
* added memory allocation adjustment macro for hash size allocation.
extern "C" {
#endif
+#include <assert.h>
#include <sys/types.h>
+#include <mutex.h>
/*
* This data structure is used to hold items
} CacheNode, *CacheNode_t;
+/*
+ * This data type is the function that computes a hash code given a key.
+ * Therefore, the key can be a pointer to anything and the function specific
+ * to the key type.
+ *
+ * Unfortunately there is a mutual data structure reference problem with this
+ * typedef. Therefore, to remove compiler warnings the functions passed to
+ * hash_new() will have to be casted to this type.
+ */
+typedef u_int (*HashFunc)(void*, void*);
+
+/*
+ * This data type is the function that compares two hash keys and returns an
+ * integer greater than, equal to, or less than 0, according as the first
+ * parameter is lexico-graphically greater than, equal to, or less than the
+ * second.
+ */
+
+typedef int (*CompareFunc)(void*, void*);
+
+
/*
* This data structure is the cache.
*
entries allocated for
"theNodeTable"). Must be
a power of two. */
- entriesInHash; /* Current number of entries
- in ther hash table. */
+ entriesInHash, /* Current number of entries
+ in the hash table. */
+ mask; /* Precomputed mask. */
/*
* Variables used to implement indexing
* through the hash table.
u_int lastBucket; /* Tracks which entry in the
array where the last value
was returned. */
+ /* Function used to compute
+ a hash code given a key.
+ This function is specified
+ when the hash table is
+ created. */
+ HashFunc hashFunc;
+ /* Function used to compare
+ two hash keys to determine
+ if they are equal. */
+ CompareFunc compareFunc;
} Cache, *Cache_t;
/* Prototypes for hash
functions. */
/* Allocate and initialize
- a hash table. Hash table
- size taken as a parameter. */
-Cache_t hash_new (u_int sizeOfHash);
+ a hash table. */
+Cache_t
+hash_new (u_int sizeOfHash, HashFunc aHashFunc, CompareFunc aCompareFunc);
/* 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);
+
+ /* Used to return a value from
+ a hash table using a given
+ key. */
+void*
+hash_value_for_key (Cache_t theCache, void* aKey);
+
+
+/************************************************
+
+ Useful hashing functions.
+
+ Declared inline for your pleaseure.
+
+************************************************/
+
+ /* Calculate a hash code by
+ performing some manipulation
+ of the key pointer. */
+static inline u_int
+intHash(Cache_t theCache, void* aKey) {
+
+
+ assert(sizeof (u_int) == sizeof (aKey));
+
+ return ((u_int)aKey >> (sizeof(void*) - 1)) & theCache->mask ;
+}
+
+ /* Calculate a hash code by
+ iterating over a NULL
+ terminate string. */
+static inline u_int
+strHash(Cache_t theCache, void* aKey) {
+
+ u_int ret = 0;
+ u_int ctr = 0;
+
+
+ while(*(char*)aKey) {
+ ret ^= *(char*)aKey++ << ctr;
+ ctr = (ctr + 1) % sizeof(void*);
+ }
+
+ return ret & theCache->mask ;
+}
+
+
+ /* Compare two integers. */
+static inline int
+intCmp(void* k1, void* k2) {
+
+
+ return !((int)k1 - (int)k2);
+}
+
+
+ /* Compare two strings. */
+static inline int
+strCmp(void* k1, void* k2) {
+
+
+ return !strcmp( k1, k2 );
+}
#ifdef __cplusplus
* 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/include/RCS/ObjC.h,v 0.9 1991/12/10 12:04:22 dennisg Exp dennisg $
+ $Header: /usr/user/dennis_glatting/ObjC/c-runtime/include/RCS/ObjC.h,v 0.10 1991/12/31 20:16:08 dennisg Exp dennisg $
$Author: dennisg $
- $Date: 1991/12/10 12:04:22 $
+ $Date: 1991/12/31 20:16:08 $
$Log: ObjC.h,v $
+ * Revision 0.10 1991/12/31 20:16:08 dennisg
+ * Deleted index variable stuff. Index variables are a hack to the language.
+ * Cleaned up some documentation.
+ *
* Revision 0.9 1991/12/10 12:04:22 dennisg
* Cleaned up file format for a distribution.
*
#endif
#include <sys/types.h>
-#include <hash.h>
+#include <record-inline.h>
#include <stdarg.h>
-#define nil ( id )0 /* id of Nil instance */
-#define Nil ( Class_t )0 /* id of Nil class */
+#define nil (id)0 /* id of Nil instance */
+#define Nil (Class_t)0 /* id of Nil class */
typedef char* STR; /* String alias */
/* Boolean typedefs */
Object. Should be ignored. */
MethodList_t methods; /* Linked List of factory methods
for the class. */
- Cache_t cache; /* Used to cache factory methods
- defined for the class and its
- super classes. Entries are
- made to the cache as the
- messager receives them. */
+ Record_t* cache; /* Pointer to factory method
+ dispatch table. */
} MetaClass, *MetaClass_t;
MethodList_t methods; /* Linked list of instance
methods defined for the
class. */
- Cache_t cache; /* Used to cache instance methods
- defined for the class and its
- super classes. Entries are
- made to the cache as the
- messager receives them. */
+ Record_t* cache; /* Pointer to instance method
+ dispatch table. */
} Class, *Class_t;