Initial check in. Preliminary development stage.
authorDennis Glatting <dennisg@gnu.org>
Thu, 24 Oct 1991 00:45:39 +0000 (00:45 +0000)
committerDennis Glatting <dennisg@gnu.org>
Thu, 24 Oct 1991 00:45:39 +0000 (00:45 +0000)
From-SVN: r46

gcc/objc/hash.c [new file with mode: 0644]
gcc/objc/hash.h [new file with mode: 0644]

diff --git a/gcc/objc/hash.c b/gcc/objc/hash.c
new file mode 100644 (file)
index 0000000..80719ce
--- /dev/null
@@ -0,0 +1,237 @@
+/* -*-c-*-
+ * This file contains the hashing implementation.
+ *
+  $Header$
+  $Author$
+  $Date$
+  $Log$
+*/
+
+#include  <hash.h>
+#include  <ObjC.h>
+
+#include  <assert.h>
+#include  <libc.h>
+#include  <math.h>
+
+
+                                                /* Local forward decl. */
+  u_int hashValue( Cache_t, void* );
+
+
+Cache_t hash_new( u_int numberOfBuckets ) {
+
+  Cache_t retCache;
+  int     i;
+
+
+  assert( numberOfBuckets );
+
+                                                /* Allocate the cache 
+                                                  structure.  calloc() insures
+                                                  its initialization for
+                                                  default values. */
+  retCache = calloc( 1, sizeof( Cache ));
+  assert( retCache );
+  
+                                                /* Allocate the array of 
+                                                  buckets for the cache.  
+                                                  calloc() initializes all of 
+                                                  the pointers to NULL. */
+  retCache->theNodeTable = calloc( numberOfBuckets, sizeof( CacheNode_t ));
+  assert( retCache->theNodeTable );
+  
+  retCache->numberOfBuckets = numberOfBuckets;
+
+                                                /* Calculate the number of 
+                                                  bits required to represent 
+                                                  the hash mask. */
+  retCache->numberOfMaskBits = 
+    ceil( log( retCache->numberOfBuckets ) / log( 2 ));
+
+                                                /* Form a bit mask for the 
+                                                  hash. */
+  for( i = 0; i < retCache->numberOfMaskBits; ++i )
+    retCache->mask = ( retCache->mask << 1 ) | 0x01 ;
+
+  assert( retCache->numberOfMaskBits );
+  assert( retCache->mask );
+
+  return retCache;
+}
+
+
+void hash_delete( Cache_t theCache ) {
+
+  void* aNode;
+  
+
+                                                /* Purge all key/value pairs 
+                                                  from the table. */
+  while( aNode = hash_next( theCache, NULL ))
+    hash_remove( theCache, aNode );
+
+                                                /* Release the array of nodes 
+                                                  and the cache itself. */
+  free( theCache->theNodeTable );
+  free( theCache );
+}
+
+
+void hash_add( Cache_t theCache, void* aKey, void* aValue ) {
+
+  u_int       indx = hashValue( theCache, aKey );
+  CacheNode_t aCacheNode = calloc( 1, sizeof( CacheNode ));
+
+
+  assert( aCacheNode );
+  
+                                                /* Initialize the new node. */
+  aCacheNode->theKey    = aKey;
+  aCacheNode->theValue  = aValue;
+  aCacheNode->nextNode  = ( *theCache->theNodeTable )[ indx ];
+  
+                                                /* Debugging.
+                                                
+                                                  Check the list for another 
+                                                  key. */
+#ifdef DEBUG
+    { CacheNode_t checkHashNode = ( *theCache->theNodeTable )[ indx ];
+    
+      while( checkHashNode ) {
+    
+        assert( checkHashNode->theKey != aKey );
+        checkHashNode = checkHashNode->nextNode;
+      }
+    }
+
+                                                /* Install the node as the
+                                                  first element on the list. */
+  ( *theCache->theNodeTable )[ indx ] = aCacheNode;
+
+#endif
+}
+
+
+void hash_remove( Cache_t theCache, void* aKey ) {
+
+  u_int       indx = hashValue( theCache, aKey );
+  CacheNode_t aCacheNode = ( *theCache->theNodeTable )[ indx ];
+  
+  
+                                                /* We assume there is an entry 
+                                                  in the table.  Error if it 
+                                                  is not. */
+  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 );
+  } else {
+                                                /* Otherwise, find the hash 
+                                                  entry. */
+    CacheNode_t prevHashNode = aCacheNode;
+    BOOL        removed = NO;
+    
+    do {
+    
+      if( aCacheNode->theKey == aKey ) {
+        prevHashNode->nextNode = aCacheNode->nextNode, removed = YES;
+        free( aCacheNode );
+      } else
+        prevHashNode = aCacheNode, aCacheNode = aCacheNode->nextNode;
+    } while( !removed && aCacheNode );
+    assert( removed );
+  }
+}
+
+
+void* hash_value_for_key( Cache_t theCache, void* aKey ) {
+
+  u_int       indx = hashValue( theCache, aKey );
+  CacheNode_t aCacheNode = ( *theCache->theNodeTable )[ indx ];
+  void*       retVal = NULL;
+  
+
+  if( aCacheNode ) {
+    BOOL  found = NO;
+  
+    do {
+      if( aCacheNode->theKey == aKey )
+        retVal = aCacheNode->theValue, found = YES;
+      else
+        aCacheNode = aCacheNode->nextNode;
+    } while( !found && aCacheNode );
+  }
+  
+  return retVal;
+}
+
+
+CacheNode_t hash_next( Cache_t theCache, CacheNode_t aCacheNode ) {
+
+  CacheNode_t theCacheNode = aCacheNode;
+  
+  
+                                                /* If the scan is being started
+                                                  then reset the last node 
+                                                  visitied pointer and bucket 
+                                                  index. */
+  if( !theCacheNode )
+    theCache->lastBucket  = 0;
+  
+                                                /* If there is a node visited
+                                                  last then check for another 
+                                                  entry in the same bucket; 
+                                                  Otherwise step to the next 
+                                                  bucket. */
+  if( theCacheNode )
+    if( theCacheNode->nextNode )
+                                                /* There is a node which 
+                                                  follows the last node 
+                                                  returned.  Step to that node 
+                                                  and retun it. */
+      return theCacheNode->nextNode;
+    else
+      ++theCache->lastBucket;
+
+                                                /* If the list isn't exhausted 
+                                                  then search the buckets for 
+                                                  other nodes. */
+  if( theCache->lastBucket < theCache->numberOfBuckets ) {
+                                                /*  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->numberOfBuckets )
+      if(( *theCache->theNodeTable )[ theCache->lastBucket ])
+        return ( *theCache->theNodeTable )[ theCache->lastBucket ];
+      else
+        ++theCache->lastBucket;
+  
+                                                /* No further nodes were found
+                                                  in the hash table. */
+    return NULL;
+  } else
+    return NULL;
+}
+
+
+u_int hashValue( Cache_t theCache, void* aKey ) {
+
+  u_int hash = 0;
+  int   i;
+  
+  
+  assert( theCache->numberOfMaskBits );
+  for( i = 0; i < ( sizeof( aKey ) * 8 ); i += theCache->numberOfMaskBits )
+    hash ^= (( u_int )aKey ) >> i ;
+
+  return ( hash & theCache->mask ) % theCache->numberOfBuckets;
+}
+
diff --git a/gcc/objc/hash.h b/gcc/objc/hash.h
new file mode 100644 (file)
index 0000000..34c77dc
--- /dev/null
@@ -0,0 +1,134 @@
+/* -*-c-*-
+ * This is a general purpose hash object.
+ *
+ * The hash object used throughout the run-time
+ *  is an integer hash.  The key and data is of type
+ *  void*.  The hashing function converts the key to
+ *  an integer and computes it hash value.
+ *
+  $Header$
+  $Author$
+  $Date$
+  $Log$
+*/
+
+#ifndef _hash_INCLUDE_GNU
+#define _hash_INCLUDE_GNU
+
+                                                /* If someone is using a c++
+                                                  compiler then adjust the 
+                                                  types in the file back 
+                                                  to C. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include  <sys/types.h>
+
+
+/*
+ * This data structure is used to hold items
+ *  stored in a hash table.  Each node holds 
+ *  a key/value pair.
+ *
+ * Items in the cache are really of type void*.
+ */
+typedef struct cache_node {
+  struct cache_node*  nextNode;                   /* Pointer to next entry on
+                                                    the list.  NULL indicates
+                                                    end of list. */
+  void*               theKey;                     /* Key used to locate the
+                                                    value.  Used to locate
+                                                    value when more than one
+                                                    key computes the same hash
+                                                    value. */
+  void*               theValue;                   /* Value stored for the
+                                                    key. */
+} CacheNode, *CacheNode_t;
+
+
+/*
+ * This data structure is the cache.
+ *
+ * It must be passed to all of the hashing routines
+ *  (except for new).
+ */
+typedef struct cache {
+  /*
+   * Variables used to implement the
+   *  hash itself.
+   */
+  CacheNode_t (* theNodeTable )[];                /* Pointer to an array of
+                                                    hash nodes. */
+  u_int       numberOfBuckets,                    /* Number of buckets 
+                                                    allocated for the hash
+                                                    table (number of array
+                                                    entries allocated for
+                                                    "theCache"). */
+              mask,                               /* Mask used when computing
+                                                    a hash value.  The number
+                                                    of bits set in the mask
+                                                    is contained in the next
+                                                    member variable. */
+              numberOfMaskBits;                   /* Number of bits used for
+                                                    the mask.  Useful for 
+                                                    efficient hash value
+                                                    calculation. */
+  /*
+   * Variables used to implement indexing
+   *  through the hash table.
+   */
+  u_int       lastBucket;                         /* Tracks which entry in the
+                                                    array where the last value
+                                                    was returned. */
+} Cache, *Cache_t;
+
+
+                                                /* Prototypes for hash
+                                                  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 numberOfBuckets );
+                                                /* Deallocate all of the
+                                                  hash nodes and the cache
+                                                  itself. */
+void hash_delete( Cache_t theCache );
+                                                /* Add the key/value pair
+                                                  to the hash table.  assert()
+                                                  if the key is already in
+                                                  the hash. */
+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 );
+                                                /* 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 );
+                                                /* Used to index through the
+                                                  hash table.  Start with NULL
+                                                  to get the first entry.
+                                                  
+                                                  Successive calls pass the
+                                                  value returned previously.
+                                                  ** Don't modify the hash
+                                                  during this operation *** 
+                                                  
+                                                  Cache nodes are returned
+                                                  such that key or value can
+                                                  ber extracted. */
+CacheNode_t hash_next( Cache_t theCache, CacheNode_t aCacheNode );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif