mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-05 22:05:47 +00:00
util: hash: Rewrite sorting of elements in virHashGetItems
All but one of the callers either use the list in arbitrary order or sorted by key. Rewrite the function so that it supports sorting by key natively and make it return the element count. This in turn allows to rewrite the only caller to sort by value internally. This allows to remove multiple sorting functions which were sorting by key and the function will be also later reused for some hash operations internally. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com> Reviewed-by: Matt Coleman <matt@datto.com>
This commit is contained in:
parent
6e29698037
commit
4eb8e9ae8b
@ -755,13 +755,6 @@ virNWFilterParseParamAttributes(xmlNodePtr cur)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
virNWFilterFormatParameterNameSorter(const virHashKeyValuePair *a,
|
|
||||||
const virHashKeyValuePair *b)
|
|
||||||
{
|
|
||||||
return strcmp(a->key, b->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
virNWFilterFormatParamAttributes(virBufferPtr buf,
|
virNWFilterFormatParamAttributes(virBufferPtr buf,
|
||||||
virHashTablePtr table,
|
virHashTablePtr table,
|
||||||
@ -779,8 +772,7 @@ virNWFilterFormatParamAttributes(virBufferPtr buf,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
items = virHashGetItems(table,
|
items = virHashGetItems(table, NULL, true);
|
||||||
virNWFilterFormatParameterNameSorter);
|
|
||||||
if (!items)
|
if (!items)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -681,7 +681,7 @@ hypervSerializeEmbeddedParam(hypervParamPtr p, const char *resourceUri,
|
|||||||
|
|
||||||
/* retrieve parameters out of hash table */
|
/* retrieve parameters out of hash table */
|
||||||
numKeys = virHashSize(p->embedded.table);
|
numKeys = virHashSize(p->embedded.table);
|
||||||
items = virHashGetItems(p->embedded.table, NULL);
|
items = virHashGetItems(p->embedded.table, NULL, false);
|
||||||
if (!items) {
|
if (!items) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("Could not read embedded param hash table"));
|
_("Could not read embedded param hash table"));
|
||||||
|
@ -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) {
|
while (tmp && tmp->key) {
|
||||||
virLockSpacePtr lockspace = (virLockSpacePtr)tmp->value;
|
virLockSpacePtr lockspace = (virLockSpacePtr)tmp->value;
|
||||||
|
|
||||||
|
@ -3126,9 +3126,12 @@ virNWFilterRuleInstSortPtr(const void *a, const void *b)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ebiptablesFilterOrderSort(const virHashKeyValuePair *a,
|
ebiptablesFilterOrderSort(const void *va,
|
||||||
const virHashKeyValuePair *b)
|
const void *vb)
|
||||||
{
|
{
|
||||||
|
const virHashKeyValuePair *a = va;
|
||||||
|
const virHashKeyValuePair *b = vb;
|
||||||
|
|
||||||
/* elements' values has been limited to range [-1000, 1000] */
|
/* elements' values has been limited to range [-1000, 1000] */
|
||||||
return *(virNWFilterChainPriority *)a->value -
|
return *(virNWFilterChainPriority *)a->value -
|
||||||
*(virNWFilterChainPriority *)b->value;
|
*(virNWFilterChainPriority *)b->value;
|
||||||
@ -3288,13 +3291,15 @@ ebtablesGetSubChainInsts(virHashTablePtr chains,
|
|||||||
size_t *ninsts)
|
size_t *ninsts)
|
||||||
{
|
{
|
||||||
g_autofree virHashKeyValuePairPtr filter_names = NULL;
|
g_autofree virHashKeyValuePairPtr filter_names = NULL;
|
||||||
|
size_t nfilter_names;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
filter_names = virHashGetItems(chains,
|
filter_names = virHashGetItems(chains, &nfilter_names, false);
|
||||||
ebiptablesFilterOrderSort);
|
|
||||||
if (filter_names == NULL)
|
if (filter_names == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
qsort(filter_names, nfilter_names, sizeof(*filter_names), ebiptablesFilterOrderSort);
|
||||||
|
|
||||||
for (i = 0; filter_names[i].key; i++) {
|
for (i = 0; filter_names[i].key; i++) {
|
||||||
g_autofree ebtablesSubChainInstPtr inst = NULL;
|
g_autofree ebtablesSubChainInstPtr inst = NULL;
|
||||||
enum l3_proto_idx idx = ebtablesGetProtoIdxByFiltername(
|
enum l3_proto_idx idx = ebtablesGetProtoIdxByFiltername(
|
||||||
|
@ -79,13 +79,6 @@ qemuBuildFileList(virHashTablePtr files, const char *dir)
|
|||||||
return 0;
|
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_SYSTEM_LOCATION PREFIX "/share/qemu"
|
||||||
#define QEMU_ETC_LOCATION SYSCONFDIR "/qemu"
|
#define QEMU_ETC_LOCATION SYSCONFDIR "/qemu"
|
||||||
|
|
||||||
@ -141,7 +134,7 @@ qemuInteropFetchConfigs(const char *name,
|
|||||||
if (virHashSize(files) == 0)
|
if (virHashSize(files) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(pairs = virHashGetItems(files, qemuConfigFilesSorter)))
|
if (!(pairs = virHashGetItems(files, NULL, true)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (tmp = pairs; tmp->key; tmp++) {
|
for (tmp = pairs; tmp->key; tmp++) {
|
||||||
|
@ -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
|
virJSONValuePtr
|
||||||
virNetDaemonPreExecRestart(virNetDaemonPtr dmn)
|
virNetDaemonPreExecRestart(virNetDaemonPtr dmn)
|
||||||
{
|
{
|
||||||
@ -402,7 +393,7 @@ virNetDaemonPreExecRestart(virNetDaemonPtr dmn)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(srvArray = virHashGetItems(dmn->servers, daemonServerCompare)))
|
if (!(srvArray = virHashGetItems(dmn->servers, NULL, true)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
for (i = 0; srvArray[i].key; i++) {
|
for (i = 0; srvArray[i].key; i++) {
|
||||||
|
@ -626,49 +626,63 @@ void *virHashSearch(const virHashTable *ctable,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct getKeysIter
|
|
||||||
{
|
struct virHashGetItemsIteratorData {
|
||||||
virHashKeyValuePair *sortArray;
|
virHashKeyValuePair *items;
|
||||||
size_t arrayIdx;
|
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;
|
data->items[data->i].key = key;
|
||||||
iter->sortArray[iter->arrayIdx].value = payload;
|
data->items[data->i].value = payload;
|
||||||
|
|
||||||
iter->arrayIdx++;
|
data->i++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef int (*qsort_comp)(const void *, const void *);
|
|
||||||
|
|
||||||
virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table,
|
static int
|
||||||
virHashKeyComparator compar)
|
virHashGetItemsKeySorter(const void *va,
|
||||||
|
const void *vb)
|
||||||
{
|
{
|
||||||
ssize_t numElems = virHashSize(table);
|
const virHashKeyValuePair *a = va;
|
||||||
struct getKeysIter iter = {
|
const virHashKeyValuePair *b = vb;
|
||||||
.arrayIdx = 0,
|
|
||||||
.sortArray = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (numElems < 0)
|
return strcmp(a->key, b->key);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
struct virHashEqualData
|
||||||
{
|
{
|
||||||
bool equal;
|
bool equal;
|
||||||
|
@ -116,10 +116,9 @@ struct _virHashKeyValuePair {
|
|||||||
const void *key;
|
const void *key;
|
||||||
const void *value;
|
const void *value;
|
||||||
};
|
};
|
||||||
typedef int (*virHashKeyComparator)(const virHashKeyValuePair *,
|
|
||||||
const virHashKeyValuePair *);
|
|
||||||
virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table,
|
virHashKeyValuePairPtr virHashGetItems(virHashTablePtr table,
|
||||||
virHashKeyComparator compar);
|
size_t *nitems,
|
||||||
|
bool sortedKeys);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compare two tables for equality: the lookup of a key's value in
|
* Compare two tables for equality: the lookup of a key's value in
|
||||||
|
@ -435,7 +435,7 @@ virJSONValuePtr virLockSpacePreExecRestart(virLockSpacePtr lockspace)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = pairs = virHashGetItems(lockspace->resources, NULL);
|
tmp = pairs = virHashGetItems(lockspace->resources, NULL, false);
|
||||||
while (tmp && tmp->value) {
|
while (tmp && tmp->value) {
|
||||||
virLockSpaceResourcePtr res = (virLockSpaceResourcePtr)tmp->value;
|
virLockSpaceResourcePtr res = (virLockSpaceResourcePtr)tmp->value;
|
||||||
virJSONValuePtr child = virJSONValueNewObject();
|
virJSONValuePtr child = virJSONValueNewObject();
|
||||||
|
@ -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
|
static int
|
||||||
testHashGetItems(const void *data G_GNUC_UNUSED)
|
testHashGetItems(const void *data G_GNUC_UNUSED)
|
||||||
{
|
{
|
||||||
@ -389,14 +382,14 @@ testHashGetItems(const void *data G_GNUC_UNUSED)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(array = virHashGetItems(hash, NULL)) ||
|
if (!(array = virHashGetItems(hash, NULL, false)) ||
|
||||||
array[3].key || array[3].value) {
|
array[3].key || array[3].value) {
|
||||||
VIR_TEST_VERBOSE("\nfailed to get items with NULL sort");
|
VIR_TEST_VERBOSE("\nfailed to get items with NULL sort");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
VIR_FREE(array);
|
VIR_FREE(array);
|
||||||
|
|
||||||
if (!(array = virHashGetItems(hash, testHashGetItemsCompKey)) ||
|
if (!(array = virHashGetItems(hash, NULL, true)) ||
|
||||||
STRNEQ(array[0].key, "a") ||
|
STRNEQ(array[0].key, "a") ||
|
||||||
STRNEQ(array[0].value, "3") ||
|
STRNEQ(array[0].value, "3") ||
|
||||||
STRNEQ(array[1].key, "b") ||
|
STRNEQ(array[1].key, "b") ||
|
||||||
|
Loading…
Reference in New Issue
Block a user