Iterate the hash elements sorted by key. This is useful to provide a stable ordering such as in cases when the output is checked in tests. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- src/libvirt_private.syms | 1 + src/util/virhash.c | 39 +++++++++++++++++++++++++++++++++++---- src/util/virhash.h | 1 + 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 95e50835ad..1793b81ad9 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2203,6 +2203,7 @@ virHashAtomicSteal; virHashAtomicUpdate; virHashEqual; virHashForEach; +virHashForEachSorted; virHashFree; virHashGetItems; virHashHasEntry; diff --git a/src/util/virhash.c b/src/util/virhash.c index f644990712..f205291de9 100644 --- a/src/util/virhash.c +++ b/src/util/virhash.c @@ -481,14 +481,25 @@ virHashRemoveEntry(virHashTablePtr table, const char *name) /** - * virHashForEach + * virHashForEach, virHashForEachSorted * @table: the hash table to process * @iter: callback to process each element * @opaque: 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 current element - * using virHashRemoveEntry but calling other virHash* functions is prohibited. + * Iterates over every element in the hash table, invoking the 'iter' callback. + * + * The elements are iterated in arbitrary order. + * + * virHashForEach allows the callback to remove the current + * element using virHashRemoveEntry but calling other virHash* functions is + * prohibited. Note that removing the entry invalidates @key and @payload in + * the callback. + * + * virHashForEachSorted iterates the elements in order by sorted key. + * + * virHashForEachSorted is more computationally + * expensive than virHashForEach. + * * If @iter fails and returns a negative value, the evaluation is stopped and -1 * is returned. * @@ -520,6 +531,26 @@ virHashForEach(virHashTablePtr table, virHashIterator iter, void *opaque) } +int +virHashForEachSorted(virHashTablePtr table, + virHashIterator iter, + void *opaque) +{ + g_autofree virHashKeyValuePairPtr items = virHashGetItems(table, NULL, true); + size_t i; + + if (!items) + return -1; + + for (i = 0; items[i].key; i++) { + if (iter((void *)items[i].value, items[i].key, opaque) < 0) + return -1; + } + + return 0; +} + + /** * virHashRemoveSet * @table: the hash table to process diff --git a/src/util/virhash.h b/src/util/virhash.h index 688e1adf4d..1a59e9799d 100644 --- a/src/util/virhash.h +++ b/src/util/virhash.h @@ -136,6 +136,7 @@ bool virHashEqual(const virHashTable *table1, * Iterators */ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *opaque); +int virHashForEachSorted(virHashTablePtr table, virHashIterator iter, void *opaque); ssize_t virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *opaque); void *virHashSearch(const virHashTable *table, virHashSearcher iter, const void *opaque, char **name); -- 2.26.2