From 77bcf6b5986d5fa2e8a3897f731ca2f97c60fe8f Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 15 Nov 2006 20:11:56 +0000 Subject: [PATCH] Added several iterators to hashtable API --- ChangeLog | 6 +++ src/hash.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/hash.h | 30 ++++++++++++- 3 files changed, 164 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index cd186694b2..5a45484e74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Wed Nov 15 15:59:13 EST 2006 Daniel Berrange + + * src/hash.c, src/hash.h: Added three new methods for iterating + over hashtable entries, virHashForEach, virHashRemoveSet & + virHashSearch. + Wed Nov 15 15:52:01 EST 2006 Daniel Berrange * src/conf.c, src/conf.h: Add two new APIs virConfNew() and diff --git a/src/hash.c b/src/hash.c index cd3da8a8bf..ebc6229a83 100644 --- a/src/hash.c +++ b/src/hash.c @@ -473,6 +473,127 @@ virHashRemoveEntry(virHashTablePtr table, const char *name, } } + +/** + * virHashForEach + * @table: the hash table to process + * @iter: callback to process each element + * @data: opaque data to pass to the iterator + * + * Iterates over every element in the hash table, invoking the + * 'iter' callback. The callback must not call any other virHash* + * functions, and in particular must not attempt to remove the + * element. + * + * Returns number of items iterated over upon completion, -1 on failure + */ +int virHashForEach(virHashTablePtr table, virHashIterator iter, const void *data) { + int i, count = 0; + + if (table == NULL || iter == NULL) + return (-1); + + for (i = 0 ; i < table->size ; i++) { + virHashEntryPtr entry = table->table + i; + while (entry) { + if (entry->valid) { + iter(entry->payload, entry->name, data); + count++; + } + entry = entry->next; + } + } + return (count); +} + +/** + * virHashRemoveSet + * @table: the hash table to process + * @iter: callback to identify elements for removal + * @f: callback to free memory from element payload + * @data: opaque data to pass to the iterator + * + * Iterates over all elements in the hash table, invoking the 'iter' + * callback. If the callback returns a non-zero value, the element + * will be removed from the hash table & its payload passed to the + * callback 'f' for de-allocation. + * + * Returns number of items removed on success, -1 on failure + */ +int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, virHashDeallocator f, const void *data) { + int i, count = 0; + + if (table == NULL || iter == NULL) + return (-1); + + for (i = 0 ; i < table->size ; i++) { + virHashEntryPtr prev = NULL; + virHashEntryPtr entry = &(table->table[i]); + + while (entry && entry->valid) { + if (iter(entry->payload, entry->name, data)) { + count++; + f(entry->payload, entry->name); + if (entry->name) + free(entry->name); + if (prev) { + prev->next = entry->next; + free(entry); + } else { + if (entry->next == NULL) { + entry->valid = 0; + entry->name = NULL; + } else { + entry = entry->next; + memcpy(&(table->table[i]), entry, + sizeof(virHashEntry)); + free(entry); + entry = NULL; + } + } + table->nbElems--; + } + prev = entry; + if (entry) { + entry = entry->next; + } else { + entry = NULL; + } + } + } + return (count); +} + +/** + * virHashSearch: + * @table: the hash table to search + * @iter: an iterator to identify the desired element + * @data: extra opaque information passed to the iter + * + * Iterates over the hash table calling the 'iter' callback + * for each element. The first element for which the iter + * returns non-zero will be returned by this function. + * The elements are processed in a undefined order + */ +void *virHashSearch(virHashTablePtr table, virHashSearcher iter, const void *data) { + int i; + + if (table == NULL || iter == NULL) + return (NULL); + + for (i = 0 ; i < table->size ; i++) { + virHashEntryPtr entry = table->table + i; + while (entry) { + if (entry->valid) { + if (iter(entry->payload, entry->name, data)) + return entry->payload; + } + entry = entry->next; + } + } + return (NULL); +} + /************************************************************************ * * * Domain and Connections allocations * @@ -770,3 +891,11 @@ done: xmlMutexUnlock(conn->domains_mux); return(ret); } +/* + * Local variables: + * indent-tabs-mode: nil + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --git a/src/hash.h b/src/hash.h index 5becd9a4e3..6fc963c410 100644 --- a/src/hash.h +++ b/src/hash.h @@ -33,7 +33,27 @@ typedef virHashTable *virHashTablePtr; * * Callback to free data from a hash. */ -typedef void (*virHashDeallocator) (void *payload, char *name); +typedef void (*virHashDeallocator) (void *payload, const char *name); +/** + * virHashIterator: + * @payload: the data in the hash + * @name: the name associated + * @data: user supplied data blob + * + * Callback to process a hash entry during iteration + */ +typedef void (*virHashIterator) (const void *payload, const char *name, const void *data); +/** + * virHashSearcher + * @payload: the data in the hash + * @name: the name associated + * @data: user supplied data blob + * + * Callback to identify hash entry desired + * Returns 1 if the hash entry is desired, 0 to move + * to next entry + */ +typedef int (*virHashSearcher) (const void *payload, const char *name, const void *data); /* * Constructor and destructor. @@ -62,6 +82,14 @@ int virHashRemoveEntry(virHashTablePtr table, */ void *virHashLookup(virHashTablePtr table, const char *name); + +/* + * Iterators + */ +int virHashForEach(virHashTablePtr table, virHashIterator iter, const void *data); +int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, virHashDeallocator f, const void *data); +void *virHashSearch(virHashTablePtr table, virHashSearcher iter, const void *data); + #ifdef __cplusplus } #endif