* 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;
}
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);
}
}
/* 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;
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);
}
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);
/* 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;
}
-/* 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;
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
#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