From c9ddc44ebe9b9d9df12fe0ef354b14ffb0566c3b Mon Sep 17 00:00:00 2001 From: uz Date: Thu, 18 Aug 2011 13:05:21 +0000 Subject: [PATCH] Change HT_Walk so that it can optionally be used to delete nodes from the hash table. git-svn-id: svn://svn.cc65.org/cc65/trunk@5210 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/common/hashtab.c | 32 +++++++++++++++++++++----------- src/common/hashtab.h | 11 +++++++---- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/common/hashtab.c b/src/common/hashtab.c index ada8948ae..e57cf727b 100644 --- a/src/common/hashtab.c +++ b/src/common/hashtab.c @@ -230,10 +230,13 @@ void HT_RemoveEntry (HashTable* T, void* Entry) -void HT_Walk (HashTable* T, void (*F) (void* Entry, void* Data), void* Data) -/* Walk over all nodes of a hash table. For each node, the user supplied - * function F is called, passing a pointer to the entry, and the data pointer - * passed to HT_Walk by the caller. +void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data) +/* Walk over all nodes of a hash table, optionally deleting entries from the + * table. For each node, the user supplied function F is called, passing a + * pointer to the entry, and the data pointer passed to HT_Walk by the caller. + * If F returns true, the node is deleted from the hash table otherwise it's + * left in place. While deleting the node, the node is not accessed, so it is + * safe for F to free the memory associcated with the entry. */ { unsigned I; @@ -247,16 +250,23 @@ void HT_Walk (HashTable* T, void (*F) (void* Entry, void* Data), void* Data) for (I = 0; I < T->Slots; ++I) { /* Get the pointer to the first entry of the hash chain */ - HashNode* N = T->Table[I]; + HashNode** Cur = &T->Table[I]; /* Walk over all entries in this chain */ - while (N) { - /* Call the user function. N is also the pointer to the entry */ - F (N, Data); - /* Next node in chain */ - N = N->Next; + while (*Cur) { + /* Fetch the next node in chain now, because F() may delete it */ + HashNode* Next = (*Cur)->Next; + /* Call the user function. N is also the pointer to the entry. If + * the function returns true, the entry is to be deleted. + */ + if (F (*Cur, Data)) { + /* Delete the node from the chain */ + *Cur = Next; + } else { + /* Next node in chain */ + Cur = &(*Cur)->Next; + } } - } } diff --git a/src/common/hashtab.h b/src/common/hashtab.h index 329e11faf..0ebc069b4 100644 --- a/src/common/hashtab.h +++ b/src/common/hashtab.h @@ -162,10 +162,13 @@ void HT_InsertEntry (HashTable* T, void* Entry); void HT_RemoveEntry (HashTable* T, void* Entry); /* Remove an entry from the given hash table */ -void HT_Walk (HashTable* T, void (*F) (void* Entry, void* Data), void* Data); -/* Walk over all nodes of a hash table. For each node, the user supplied - * function F is called, passing a pointer to the entry, and the data pointer - * passed to HT_Walk by the caller. +void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data); +/* Walk over all nodes of a hash table, optionally deleting entries from the + * table. For each node, the user supplied function F is called, passing a + * pointer to the entry, and the data pointer passed to HT_Walk by the caller. + * If F returns true, the node is deleted from the hash table otherwise it's + * left in place. While deleting the node, the node is not accessed, so it is + * safe for F to free the memory associcated with the entry. */