summaryrefslogtreecommitdiff
path: root/src/libnm-systemd-shared/src/basic/hashmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-systemd-shared/src/basic/hashmap.c')
-rw-r--r--src/libnm-systemd-shared/src/basic/hashmap.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/src/libnm-systemd-shared/src/basic/hashmap.c b/src/libnm-systemd-shared/src/basic/hashmap.c
index 356200cfcc..28d2efa0e2 100644
--- a/src/libnm-systemd-shared/src/basic/hashmap.c
+++ b/src/libnm-systemd-shared/src/basic/hashmap.c
@@ -23,6 +23,7 @@
#include "random-util.h"
#include "set.h"
#include "siphash24.h"
+#include "sort-util.h"
#include "string-util.h"
#include "strv.h"
@@ -176,9 +177,9 @@ struct _packed_ indirect_storage {
};
struct direct_storage {
- /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit.
- * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit,
- * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */
+ /* This gives us 39 bytes on 64-bit, or 35 bytes on 32-bit.
+ * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64-bit,
+ * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32-bit. */
uint8_t storage[sizeof(struct indirect_storage)];
};
@@ -2112,3 +2113,54 @@ bool set_fnmatch(Set *include_patterns, Set *exclude_patterns, const char *needl
return set_fnmatch_one(include_patterns, needle);
}
+
+static int hashmap_entry_compare(
+ struct hashmap_base_entry * const *a,
+ struct hashmap_base_entry * const *b,
+ compare_func_t compare) {
+
+ assert(a && *a);
+ assert(b && *b);
+ assert(compare);
+
+ return compare((*a)->key, (*b)->key);
+}
+
+int _hashmap_dump_sorted(HashmapBase *h, void ***ret, size_t *ret_n) {
+ _cleanup_free_ struct hashmap_base_entry **entries = NULL;
+ Iterator iter;
+ unsigned idx;
+ size_t n = 0;
+
+ assert(ret);
+
+ if (_hashmap_size(h) == 0) {
+ *ret = NULL;
+ if (ret_n)
+ *ret_n = 0;
+ return 0;
+ }
+
+ /* We append one more element than needed so that the resulting array can be used as a strv. We
+ * don't count this entry in the returned size. */
+ entries = new(struct hashmap_base_entry*, _hashmap_size(h) + 1);
+ if (!entries)
+ return -ENOMEM;
+
+ HASHMAP_FOREACH_IDX(idx, h, iter)
+ entries[n++] = bucket_at(h, idx);
+
+ assert(n == _hashmap_size(h));
+ entries[n] = NULL;
+
+ typesafe_qsort_r(entries, n, hashmap_entry_compare, h->hash_ops->compare);
+
+ /* Reuse the array. */
+ FOREACH_ARRAY(e, entries, n)
+ *e = entry_value(h, *e);
+
+ *ret = (void**) TAKE_PTR(entries);
+ if (ret_n)
+ *ret_n = n;
+ return 0;
+}