Add a function to the virHashTable for getting an array of the hash table's keys and have the keys (optionally) sorted. Signed-off-by: Stefan Berger --- src/libvirt_private.syms | 3 + src/util/hash.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/hash.h | 14 ++++++ 3 files changed, 115 insertions(+) Index: libvirt-acl/src/util/hash.c =================================================================== --- libvirt-acl.orig/src/util/hash.c +++ libvirt-acl/src/util/hash.c @@ -618,3 +618,101 @@ void *virHashSearch(virHashTablePtr tabl return NULL; } + + +struct getKeysIter +{ + virHashTablePtr table; + void **array; + virHashKeyValuePair *sortArray; + unsigned arrayIdx; + bool error; +}; + +static void virHashGetKeysIterator(void *payload, + const void *name, void *data) +{ + struct getKeysIter *iter = data; + void *key; + + if (iter->error) + return; + + key = iter->table->keyCopy(name); + + if (key == NULL) { + virReportOOMError(); + iter->error = true; + return; + } + + if (iter->sortArray) { + iter->sortArray[iter->arrayIdx].key = key; + iter->sortArray[iter->arrayIdx].value = payload; + } else { + iter->array[iter->arrayIdx] = iter->table->keyCopy(name); + } + iter->arrayIdx++; +} + +void virHashFreeKeys(virHashTablePtr table, void **keys) +{ + unsigned i = 0; + + if (keys == NULL) + return; + + while (keys[i]) + table->keyFree(keys[i++]); + + VIR_FREE(keys); +} + +typedef int (*qsort_comp)(const void *, const void *); + +void **virHashGetKeys(virHashTablePtr table, + virHashKeyComparator compar) +{ + int i, numElems = virHashSize(table); + struct getKeysIter iter = { + .table = table, + .arrayIdx = 0, + .error = false, + }; + + if (numElems < 0) { + return NULL; + } + + if (VIR_ALLOC_N(iter.array, numElems + 1)) { + virReportOOMError(); + return NULL; + } + + /* null-terminate array */ + iter.array[numElems] = NULL; + + if (compar && + VIR_ALLOC_N(iter.sortArray, numElems)) { + VIR_FREE(iter.array); + virReportOOMError(); + return NULL; + } + + virHashForEach(table, virHashGetKeysIterator, &iter); + if (iter.error) { + VIR_FREE(iter.sortArray); + virHashFreeKeys(table, iter.array); + return NULL; + } + + if (compar) { + qsort(&iter.sortArray[0], numElems, sizeof(iter.sortArray[0]), + (qsort_comp)compar); + for (i = 0; i < numElems; i++) + iter.array[i] = iter.sortArray[i].key; + VIR_FREE(iter.sortArray); + } + + return iter.array; +} Index: libvirt-acl/src/util/hash.h =================================================================== --- libvirt-acl.orig/src/util/hash.h +++ libvirt-acl/src/util/hash.h @@ -130,6 +130,20 @@ void *virHashLookup(virHashTablePtr tabl */ void *virHashSteal(virHashTablePtr table, const void *name); +/* + * Get the set of keys and have them optionally sorted. + */ +typedef struct _virHashKeyValuePair virHashKeyValuePair; +typedef virHashKeyValuePair *virHashKeyValuePairPtr; +struct _virHashKeyValuePair { + void *key; + const void *value; +}; +typedef int (*virHashKeyComparator)(const virHashKeyValuePairPtr , + const virHashKeyValuePairPtr ); +void **virHashGetKeys(virHashTablePtr table, virHashKeyComparator compar); +void virHashFreeKeys(virHashTablePtr table, void **); + /* * Iterators Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -552,6 +552,8 @@ virHashAddEntry; virHashCreate; virHashForEach; virHashFree; +virHashFreeKeys; +virHashGetKeys; virHashLookup; virHashRemoveEntry; virHashRemoveSet; @@ -559,6 +561,7 @@ virHashSearch; virHashSize; virHashSteal; virHashTableSize; +virHashUpdateEntry; # hooks.h