From: uz Date: Fri, 12 Aug 2011 16:13:10 +0000 (+0000) Subject: Require that the hash node must be the first element of the structure to be X-Git-Tag: V2.13.3~304 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=f571ec44aefc80288973f6c9abb5ef02f3274c36;p=cc65 Require that the hash node must be the first element of the structure to be 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 --- diff --git a/src/common/hashtab.c b/src/common/hashtab.c index a96dc1652..18ccedaf2 100644 --- a/src/common/hashtab.c +++ b/src/common/hashtab.c @@ -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; } diff --git a/src/common/hashtab.h b/src/common/hashtab.h index d5249a4c1..fc5698391 100644 --- a/src/common/hashtab.h +++ b/src/common/hashtab.h @@ -50,16 +50,19 @@ -/* 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