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 <stefanb(a)linux.vnet.ibm.com>
---
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
@@ -559,6 +559,8 @@ virHashAddEntry;
virHashCreate;
virHashForEach;
virHashFree;
+virHashFreeKeys;
+virHashGetKeys;
virHashLookup;
virHashRemoveEntry;
virHashRemoveSet;
@@ -566,6 +568,7 @@ virHashSearch;
virHashSize;
virHashSteal;
virHashTableSize;
+virHashUpdateEntry;
# hooks.h