]> git.sur5r.net Git - cc65/commitdiff
Require that the hash node must be the first element of the structure to be
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 12 Aug 2011 16:13:10 +0000 (16:13 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 12 Aug 2011 16:13:10 +0000 (16:13 +0000)
managed in a hash table. This gives smaller code and a ~25% size reduction of
the HashNode structure which might become an advantage if many elements are
hashed.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5158 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/common/hashtab.c
src/common/hashtab.h

index a96dc16527465f18ffb00eb8aa79cdcd43849610..18ccedaf28411f4845bfd72e9bdea1e65e24275e 100644 (file)
@@ -109,7 +109,7 @@ HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash)
          * if it is not really necessary.
          */
         if (N->Hash == Hash &&
-            T->Func->Compare (Key, T->Func->GetKey (HN_GetEntry (N))) == 0) {
+            T->Func->Compare (Key, T->Func->GetKey (N)) == 0) {
             /* Found */
             break;
         }
@@ -127,11 +127,8 @@ HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash)
 void* HT_FindEntry (const HashTable* T, const void* Key)
 /* Find the node with the given index and return the corresponding entry */
 {
-    /* First, search for the hash node */
-    HashNode* N = HT_Find (T, Key);
-
-    /* Convert the node into an entry if necessary */
-    return N? HN_GetEntry (N) : 0;
+    /* Since the HashEntry must be first member, we can use HT_Find here */
+    return HT_Find (T, Key);
 }
 
 
@@ -147,8 +144,8 @@ void HT_Insert (HashTable* T, HashNode* N)
     }
 
     /* Generate the hash over the node key. */
-    N->Hash = T->Func->GenHash (T->Func->GetKey (HN_GetEntry (N)));
-
+    N->Hash = T->Func->GenHash (T->Func->GetKey (N));
+                                                  
     /* Calculate the reduced hash */
     RHash = N->Hash % T->Slots;
 
@@ -196,7 +193,10 @@ void HT_Remove (HashNode* N)
 void HT_InsertEntry (HashTable* T, void* Entry)
 /* Insert an entry into the given hash table */
 {
-    HT_Insert (T, T->Func->GetHashNode (Entry));
+    /* Since the hash node must be first member, Entry is also the pointer to
+     * the hash node.
+     */
+    HT_Insert (T, Entry);
 }
 
 
@@ -204,8 +204,8 @@ void HT_InsertEntry (HashTable* T, void* Entry)
 void HT_RemoveEntry (HashTable* T, void* Entry)
 /* Remove an entry from the given hash table */
 {
-    /* Get the node from the entry */
-    HashNode* N = T->Func->GetHashNode (Entry);
+    /* The entry is the first member, so we can just convert the pointer */
+    HashNode* N = Entry;
 
     /* Make sure the entry is actually in the given table */
     CHECK (N->Owner == T);
@@ -237,8 +237,8 @@ void HT_Walk (HashTable* T, void (*F) (void* Entry, void* Data), void* Data)
 
         /* Walk over all entries in this chain */
         while (N) {
-            /* Call the user function */
-            F (HN_GetEntry (N), Data);
+            /* Call the user function. N is also the pointer to the entry */
+            F (N, Data);
             /* Next node in chain */
             N = N->Next;
         }
index d5249a4c1711178292160bf4830d84701ecebb55..fc56983918585f589282e411d8dbc062017d32e8 100644 (file)
 
 
 
-/* Hash table node */
+/* Hash table node. NOTE: This structure must be the first member of a struct 
+ * that is hashed by the module. Having it first allows to omit a pointer to 
+ * the entry itself, because the C standard guarantees that a pointer to a 
+ * struct can be converted to its first member.
+ */
 typedef struct HashNode HashNode;
 struct HashNode {
     HashNode*           Next;           /* Next entry in hash list */
     struct HashTable*   Owner;          /* Owner table */
     unsigned            Hash;           /* The full hash value */
-    void*               Entry;          /* Pointer to user entry data */
 };
 
-#define STATIC_HASHNODE_INITIALIZER(Entry) { 0, 0, 0, Entry }
+#define STATIC_HASHNODE_INITIALIZER     { 0, 0, 0 }
 
 /* Hash table functions */
 typedef struct HashFunctions HashFunctions;
@@ -71,9 +74,6 @@ struct HashFunctions {
     const void* (*GetKey) (void* Entry);
     /* Given a pointer to the user entry data, return a pointer to the key */
 
-    HashNode* (*GetHashNode) (void* Entry);
-    /* Given a pointer to the user entry data, return a pointer to the hash node */
-
     int (*Compare) (const void* Key1, const void* Key2);
     /* Compare two keys. The function must return a value less than zero if
      * Key1 is smaller than Key2, zero if both are equal, and a value greater
@@ -101,28 +101,16 @@ struct HashTable {
 
 
 #if defined(HAVE_INLINE)
-INLINE void InitHashNode (HashNode* N, void* Entry)
+INLINE void InitHashNode (HashNode* N)
 /* Initialize a hash node. */
 {
     N->Next     = 0;
     N->Owner    = 0;
-    N->Entry    = Entry;
 }
 #else
-#define InitHashNode(N, E)     \
+#define InitHashNode(N)         \
     (N)->Next   = 0,            \
-    (N)->Owner  = 0,            \
-    (N)->Entry  = (E)
-#endif
-
-#if defined(HAVE_INLINE)
-INLINE void* HN_GetEntry (HashNode* N)
-/* Get the entry from a hash node */
-{
-    return N->Entry;
-}
-#else
-#define HN_GetEntry(N)          (N)->Entry
+    (N)->Owner  = 0
 #endif