Removing an element from a hash-table + walking a hash-table

Here's another enhancement to lib-www, this time to the hash-table
functionality.

I needed to be able to delete individual elements from a hash-table,
plus I wanted to be able to walk through all associated elements in
a table without having to ask for a list of all keys and then
looking each one up.  The result is the addition of two functions:

    HTHashtable_removeObject()  and  HTHashtable_walk()

When I created the hash-walking function, I used a favorite hash
optimization of mine -- the user-called function can return a value
that either stops the walk, deletes the current object, or continues
onward.  Having the calling function delete the current element is
much more efficient than having the user's hash-walk function do a
lookup based on the key (since the caller already knows exactly
where the current object is) and it also makes it possible for the
user's function to decide to delete any other element that they need
to delete without adversely affecting the walking sequence (since we
can safely use the pointer to the current object to continue the
walk rather than saving off a "next" pointer and hoping that the
user somehow avoids deleting that one).

Other changes:

 + I got rid of a few useless variable initializations in HTHash.c
   (when the variables were being set to a value immediately
   following the init value).

 + I removed some superfluous spaces that I saw.

..wayne..

---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Index: Library/src/HTHash.c
@@ -39,13 +39,13 @@
 
 PUBLIC BOOL HTHashtable_delete (HTHashtable *me)
 {
-    int i = 0;
     if (me) {
+	int i;
 	for(i = 0; i< me->size; i++) {
 	    HTList * l = (HTList *)me->table[i];
 	    if (l) {
 		HTList *cur = l;
-		keynode *kn = NULL;
+		keynode *kn;
 		while ((kn = (keynode *) HTList_nextObject(cur))) {
 		    HT_FREE(kn->key);
 		    HT_FREE(kn);
@@ -78,14 +78,14 @@
 )
 */
 
-PUBLIC BOOL HTHashtable_addObject (HTHashtable *me, const char *key , 
+PUBLIC BOOL HTHashtable_addObject (HTHashtable *me, const char *key,
 				   void *newObject)
 {
     if(me) {
 	int size = me->size;
 	int i = hash_number(key,size);
 	HTList *l = (HTList *)me->table[i];
-	keynode *kn = NULL;
+	keynode *kn;
 	if(!l)
 	    l = me->table[i] = HTList_new();
 	if ((kn = (keynode  *) HT_CALLOC(1, sizeof (keynode))) == NULL)
@@ -98,8 +98,36 @@
     }
     return NO;
 }
+
 /*
 (
+  Remove an Element from the HashTable
+)
+*/
+
+PUBLIC BOOL HTHashtable_removeObject (HTHashtable *me, const char *key)
+{
+    if(me) {
+	int size = me->size;
+	int i = hash_number(key,size);
+	HTList *l = (HTList *)me->table[i];
+	if(l) {
+	    HTList *cur = l;
+	    keynode *kn;
+	    while ((kn = (keynode *) HTList_nextObject(cur))) {
+		if(!strcmp(key,kn->key)) {
+		    HTList_removeObject(l,kn);
+		    me->count--;
+		    return YES;
+		}
+	    }
+	}
+    }
+    return NO;
+}
+
+/*
+(
   Search for an Element in a Hash Table
 )
 */
@@ -112,7 +140,7 @@
 	HTList * l = (HTList *)me->table[i];
 	if (l) {
 	    HTList *cur = l;
-	    keynode *kn = NULL;
+	    keynode *kn;
 	    while ((kn = (keynode *) HTList_nextObject(cur))) {
 		if(!strcmp(key,kn->key))
 		    return kn->object;
@@ -128,7 +156,7 @@
 )
 */
 
-PUBLIC int HTHashtable_count  (HTHashtable *me)
+PUBLIC int HTHashtable_count (HTHashtable *me)
 {
     if(me)
 	return me->count;
@@ -137,12 +165,44 @@
 
 /*
 (
-   Extract in a dynamic array all keys of the Hash Table
+   Walk all Elements in the HashTable
 )
 */
 
+PUBLIC BOOL HTHashtable_walk (HTHashtable *me,
+			      int (*walkFunc)(HTHashtable *,char *, void *))
+{
+    if(me) {
+	int i, j;
+	for(i = 0; i< me->size; i++) {
+	    HTList *l = (HTList *)me->table[i];
+	    if(l) {
+		HTList *cur = l;
+		keynode *kn, *nextkn;
+		for(kn = (keynode *)HTList_nextObject(cur); kn; kn = nextkn) {
+		    j = walkFunc(me, kn->key, kn->object);
+		    if(j == 0)
+			return YES;
+		    nextkn = (keynode *)HTList_nextObject(cur);
+		    if(j < 0) {
+			HTList_removeObject(l, kn);
+			me->count--;
+		    }
+		}
+	    }
+	}
+	return YES;
+    }
+    return NO;
+}
+
+/*
+(
+   Extract in a dynamic array all keys of the Hash Table
+)
+*/
 
-PUBLIC HTArray * HTHashtable_keys  (HTHashtable *me)
+PUBLIC HTArray * HTHashtable_keys (HTHashtable *me)
 {
     if(me) {
 	HTArray *keys = HTArray_new(me->count);
@@ -152,7 +212,7 @@
 	    HTList * l = (HTList *)me->table[i];
 	    if (l) {
 		HTList *cur = l;
-		keynode *kn = NULL;
+		keynode *kn;
 		while ((kn = (keynode *) HTList_nextObject(cur))) {
 		    char * nkey = NULL;
 		    StrAllocCopy(nkey,kn->key);
Index: Library/src/HTHash.html
@@ -49,9 +49,15 @@
   Add an Element to a HashTable
 </H2>
 <PRE>
-extern BOOL HTHashtable_addObject (HTHashtable *me, const char *key , void *newObject);
+extern BOOL HTHashtable_addObject (HTHashtable *me, const char *key, void *newObject);
 </PRE>
 <H2>
+  Remove an Element from a HashTable
+</H2>
+<PRE>
+extern BOOL HTHashtable_removeObject (HTHashtable *me, const char *key);
+</PRE>
+<H2>
   Search for an Element in a Hash Table
 </H2>
 <PRE>
@@ -62,6 +68,23 @@
 </H2>
 <PRE>
 extern int	HTHashtable_count  (HTHashtable *me);
+</PRE>
+<H2>
+  Walk all the elements in a Hash Table
+</H2>
+<P>
+Walking the hashtable calls the specified function pointer with each key
+and object that is in the hash table.  If the callback function returns 0,
+the walking stops.  If it returns a negative number, the current element
+is removed from the hash table.  Return a positive number to keep going.
+<P>
+Note that it is legal for the walkFunc to call HTHashtable_removeObject()
+on any element in the current hash table <B>except</B> the current one (if
+you intend to keep going, that is).  The only legal way to delete the
+current element while continuing to walk the table is to use the negative
+return value.
+<PRE>
+extern BOOL	HTHashtable_walk (HTHashtable *me, int (*walkFunc)(HTHashtable *, char *, void *));
 </PRE>
 <H2>
   Extract in a dynamic array all keys of the Hash Table
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---

Received on Wednesday, 9 August 2000 16:09:05 UTC