/* #define DEBUG_GROW */
+#define virHashIterationError(ret) \
+ do { \
+ VIR_ERROR0(_("Hash operation not allowed during iteration")); \
+ return ret; \
+ } while (0)
+
/*
* A single entry in the hash table
*/
struct _virHashEntry *table;
int size;
int nbElems;
+ /* True iff we are iterating over hash entries. */
+ bool iterating;
+ /* Pointer to the current entry during iteration. */
+ virHashEntryPtr current;
virHashDataFree dataFree;
virHashKeyCode keyCode;
virHashKeyEqual keyEqual;
if ((table == NULL) || (name == NULL))
return (-1);
+ if (table->iterating)
+ virHashIterationError(-1);
+
/*
* Check for duplicate and insertion location.
*/
for (entry = &(table->table[key]); entry != NULL;
entry = entry->next) {
if (table->keyEqual(entry->name, name)) {
+ if (table->iterating && table->current != entry)
+ virHashIterationError(-1);
if (table->dataFree && (entry->payload != NULL))
table->dataFree(entry->payload, entry->name);
entry->payload = NULL;
* @data: opaque data to pass to the iterator
*
* Iterates over every element in the hash table, invoking the
- * 'iter' callback. The callback is allowed to remove the element using
- * virHashRemoveEntry but calling other virHash* functions is prohibited.
+ * 'iter' callback. The callback is allowed to remove the current element
+ * using virHashRemoveEntry but calling other virHash* functions is prohibited.
*
* Returns number of items iterated over upon completion, -1 on failure
*/
-int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) {
+int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data)
+{
int i, count = 0;
if (table == NULL || iter == NULL)
return (-1);
+ if (table->iterating)
+ virHashIterationError(-1);
+
+ table->iterating = true;
+ table->current = NULL;
for (i = 0 ; i < table->size ; i++) {
virHashEntryPtr entry = table->table + i;
while (entry) {
virHashEntryPtr next = entry->next;
if (entry->valid) {
+ table->current = entry;
iter(entry->payload, entry->name, data);
+ table->current = NULL;
count++;
}
entry = next;
}
}
+ table->iterating = false;
+
return (count);
}
if (table == NULL || iter == NULL)
return (-1);
+ if (table->iterating)
+ virHashIterationError(-1);
+
+ table->iterating = true;
+ table->current = NULL;
for (i = 0 ; i < table->size ; i++) {
virHashEntryPtr prev = NULL;
virHashEntryPtr entry = &(table->table[i]);
}
}
}
+ table->iterating = false;
+
return (count);
}
if (table == NULL || iter == NULL)
return (NULL);
+ if (table->iterating)
+ virHashIterationError(NULL);
+
+ table->iterating = true;
+ table->current = 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))
+ if (iter(entry->payload, entry->name, data)) {
+ table->iterating = false;
return entry->payload;
+ }
}
entry = entry->next;
}
}
+ table->iterating = false;
+
return (NULL);
}