diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index 73160a38a4..dd2b92c97b 100644 --- a/src/conf/nwfilter_params.c +++ b/src/conf/nwfilter_params.c @@ -755,13 +755,6 @@ virNWFilterParseParamAttributes(xmlNodePtr cur) } -static int -virNWFilterFormatParameterNameSorter(const virHashKeyValuePair *a, - const virHashKeyValuePair *b) -{ - return strcmp(a->key, b->key); -} - int virNWFilterFormatParamAttributes(virBufferPtr buf, virHashTablePtr table, @@ -779,8 +772,7 @@ virNWFilterFormatParamAttributes(virBufferPtr buf, return -1; } - items = virHashGetItems(table, - virNWFilterFormatParameterNameSorter); + items = virHashGetItems(table, NULL, true); if (!items) return -1; diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index 1d0d33ec6d..7a66e4810e 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -681,7 +681,7 @@ hypervSerializeEmbeddedParam(hypervParamPtr p, const char *resourceUri, /* retrieve parameters out of hash table */ numKeys = virHashSize(p->embedded.table); - items = virHashGetItems(p->embedded.table, NULL); + items = virHashGetItems(p->embedded.table, NULL, false); if (!items) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not read embedded param hash table")); diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c index 8f16dfd064..021792cc69 100644 --- a/src/locking/lock_daemon.c +++ b/src/locking/lock_daemon.c @@ -730,7 +730,7 @@ virLockDaemonPreExecRestart(const char *state_file, } - tmp = pairs = virHashGetItems(lockDaemon->lockspaces, NULL); + tmp = pairs = virHashGetItems(lockDaemon->lockspaces, NULL, false); while (tmp && tmp->key) { virLockSpacePtr lockspace = (virLockSpacePtr)tmp->value; diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index da6f88f135..8dfc870ab7 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -3126,9 +3126,12 @@ virNWFilterRuleInstSortPtr(const void *a, const void *b) static int -ebiptablesFilterOrderSort(const virHashKeyValuePair *a, - const virHashKeyValuePair *b) +ebiptablesFilterOrderSort(const void *va, + const void *vb) { + const virHashKeyValuePair *a = va; + const virHashKeyValuePair *b = vb; + /* elements' values has been limited to range [-1000, 1000] */ return *(virNWFilterChainPriority *)a->value - *(virNWFilterChainPriority *)b->value; @@ -3288,13 +3291,15 @@ ebtablesGetSubChainInsts(virHashTablePtr chains, size_t *ninsts) { g_autofree virHashKeyValuePairPtr filter_names = NULL; + size_t nfilter_names; size_t i; - filter_names = virHashGetItems(chains, - ebiptablesFilterOrderSort); + filter_names = virHashGetItems(chains, &nfilter_names, false); if (filter_names == NULL) return -1; + qsort(filter_names, nfilter_names, sizeof(*filter_names), ebiptablesFilterOrderSort); + for (i = 0; filter_names[i].key; i++) { g_autofree ebtablesSubChainInstPtr inst = NULL; enum l3_proto_idx idx = ebtablesGetProtoIdxByFiltername( diff --git a/src/qemu/qemu_interop_config.c b/src/qemu/qemu_interop_config.c index e1c20aff11..c8b81c59a8 100644 --- a/src/qemu/qemu_interop_config.c +++ b/src/qemu/qemu_interop_config.c @@ -79,13 +79,6 @@ qemuBuildFileList(virHashTablePtr files, const char *dir) return 0; } -static int -qemuConfigFilesSorter(const virHashKeyValuePair *a, - const virHashKeyValuePair *b) -{ - return strcmp(a->key, b->key); -} - #define QEMU_SYSTEM_LOCATION PREFIX "/share/qemu" #define QEMU_ETC_LOCATION SYSCONFDIR "/qemu" @@ -141,7 +134,7 @@ qemuInteropFetchConfigs(const char *name, if (virHashSize(files) == 0) return 0; - if (!(pairs = virHashGetItems(files, qemuConfigFilesSorter))) + if (!(pairs = virHashGetItems(files, NULL, true))) return -1; for (tmp = pairs; tmp->key; tmp++) { diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c index ce13f0d927..525cbb3ce6 100644 --- a/src/rpc/virnetdaemon.c +++ b/src/rpc/virnetdaemon.c @@ -378,15 +378,6 @@ virNetDaemonNewPostExecRestart(virJSONValuePtr object, } -static int -daemonServerCompare(const virHashKeyValuePair *a, const virHashKeyValuePair *b) -{ - const char *as = a->key; - const char *bs = b->key; - - return strcmp(as, bs); -} - virJSONValuePtr virNetDaemonPreExecRestart(virNetDaemonPtr dmn) { @@ -402,7 +393,7 @@ virNetDaemonPreExecRestart(virNetDaemonPtr dmn) goto error; } - if (!(srvArray = virHashGetItems(dmn->servers, daemonServerCompare))) + if (!(srvArray = virHashGetItems(dmn->servers, NULL, true))) goto error; for (i = 0; srvArray[i].key; i++) { diff --git a/src/util/virhash.c b/src/util/virhash.c index b30db8a87a..f644990712 100644 --- a/src/util/virhash.c +++ b/src/util/virhash.c @@ -626,49 +626,63 @@ void *virHashSearch(const virHashTable *ctable, return NULL; } -struct getKeysIter -{ - virHashKeyValuePair *sortArray; - size_t arrayIdx; + +struct virHashGetItemsIteratorData { + virHashKeyValuePair *items; + size_t i; }; -static int virHashGetKeysIterator(void *payload, - const char *key, void *data) + +static int +virHashGetItemsIterator(void *payload, + const char *key, + void *opaque) { - struct getKeysIter *iter = data; + struct virHashGetItemsIteratorData *data = opaque; - iter->sortArray[iter->arrayIdx].key = key; - iter->sortArray[iter->arrayIdx].value = payload; + data->items[data->i].key = key; + data->items[data->i].value = payload; - iter->arrayIdx++; + data->i++; return 0; } -typedef int (*qsort_comp)(const void *, const void *); -virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table, - virHashKeyComparator compar) +static int +virHashGetItemsKeySorter(const void *va, + const void *vb) { - ssize_t numElems = virHashSize(table); - struct getKeysIter iter = { - .arrayIdx = 0, - .sortArray = NULL, - }; + const virHashKeyValuePair *a = va; + const virHashKeyValuePair *b = vb; - if (numElems < 0) - return NULL; - - iter.sortArray = g_new0(virHashKeyValuePair, numElems + 1); - - virHashForEach(table, virHashGetKeysIterator, &iter); - - if (compar) - qsort(&iter.sortArray[0], numElems, sizeof(iter.sortArray[0]), - (qsort_comp)compar); - - return iter.sortArray; + return strcmp(a->key, b->key); } + +virHashKeyValuePairPtr +virHashGetItems(virHashTablePtr table, + size_t *nitems, + bool sortKeys) +{ + size_t dummy; + struct virHashGetItemsIteratorData data = { .items = NULL, .i = 0 }; + + if (!nitems) + nitems = &dummy; + + *nitems = virHashSize(table); + + data.items = g_new0(virHashKeyValuePair, *nitems + 1); + + virHashForEach(table, virHashGetItemsIterator, &data); + + if (sortKeys) + qsort(data.items, *nitems, sizeof(* data.items), virHashGetItemsKeySorter); + + return data.items; +} + + struct virHashEqualData { bool equal; diff --git a/src/util/virhash.h b/src/util/virhash.h index b2ea5c9a96..688e1adf4d 100644 --- a/src/util/virhash.h +++ b/src/util/virhash.h @@ -116,10 +116,9 @@ struct _virHashKeyValuePair { const void *key; const void *value; }; -typedef int (*virHashKeyComparator)(const virHashKeyValuePair *, - const virHashKeyValuePair *); virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table, - virHashKeyComparator compar); + size_t *nitems, + bool sortedKeys); /* * Compare two tables for equality: the lookup of a key's value in diff --git a/src/util/virlockspace.c b/src/util/virlockspace.c index 2731d46dfc..d39f2c026f 100644 --- a/src/util/virlockspace.c +++ b/src/util/virlockspace.c @@ -435,7 +435,7 @@ virJSONValuePtr virLockSpacePreExecRestart(virLockSpacePtr lockspace) goto error; } - tmp = pairs = virHashGetItems(lockspace->resources, NULL); + tmp = pairs = virHashGetItems(lockspace->resources, NULL, false); while (tmp && tmp->value) { virLockSpaceResourcePtr res = (virLockSpaceResourcePtr)tmp->value; virJSONValuePtr child = virJSONValueNewObject(); diff --git a/tests/virhashtest.c b/tests/virhashtest.c index 8cc3109929..93949d8b7a 100644 --- a/tests/virhashtest.c +++ b/tests/virhashtest.c @@ -361,13 +361,6 @@ testHashSearch(const void *data G_GNUC_UNUSED) } -static int -testHashGetItemsCompKey(const virHashKeyValuePair *a, - const virHashKeyValuePair *b) -{ - return strcmp(a->key, b->key); -} - static int testHashGetItems(const void *data G_GNUC_UNUSED) { @@ -389,14 +382,14 @@ testHashGetItems(const void *data G_GNUC_UNUSED) goto cleanup; } - if (!(array = virHashGetItems(hash, NULL)) || + if (!(array = virHashGetItems(hash, NULL, false)) || array[3].key || array[3].value) { VIR_TEST_VERBOSE("\nfailed to get items with NULL sort"); goto cleanup; } VIR_FREE(array); - if (!(array = virHashGetItems(hash, testHashGetItemsCompKey)) || + if (!(array = virHashGetItems(hash, NULL, true)) || STRNEQ(array[0].key, "a") || STRNEQ(array[0].value, "3") || STRNEQ(array[1].key, "b") ||