#include "random-util.h"
#include "set.h"
#include "siphash24.h"
+#include "sort-util.h"
#include "string-util.h"
#include "strv.h"
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;
+ }
+
+ entries = new(struct hashmap_base_entry*, _hashmap_size(h));
+ if (!entries)
+ return -ENOMEM;
+
+ HASHMAP_FOREACH_IDX(idx, h, iter)
+ entries[n++] = bucket_at(h, idx);
+
+ assert(n == _hashmap_size(h));
+
+ 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;
+}
return _hashmap_get_strv(HASHMAP_BASE(h));
}
+int _hashmap_dump_sorted(HashmapBase *h, void ***ret, size_t *ret_n);
+static inline int hashmap_dump_sorted(Hashmap *h, void ***ret, size_t *ret_n) {
+ return _hashmap_dump_sorted(HASHMAP_BASE(h), ret, ret_n);
+}
+static inline int ordered_hashmap_dump_sorted(OrderedHashmap *h, void ***ret, size_t *ret_n) {
+ return _hashmap_dump_sorted(HASHMAP_BASE(h), ret, ret_n);
+}
+static inline int set_dump_sorted(Set *h, void ***ret, size_t *ret_n) {
+ return _hashmap_dump_sorted(HASHMAP_BASE(h), ret, ret_n);
+}
+
/*
* Hashmaps are iterated in unpredictable order.
* OrderedHashmaps are an exception to this. They are iterated in the order
assert_se(strv_equal(s, STRV_MAKE("bar", "BAR")));
}
+TEST(hashmap_dump_sorted) {
+ static void * const expected[] = { UINT_TO_PTR(123U), UINT_TO_PTR(12U), UINT_TO_PTR(345U), };
+ _cleanup_hashmap_free_ Hashmap *m = NULL;
+ _cleanup_free_ void **vals = NULL;
+ size_t n;
+
+ assert_se(m = hashmap_new(&string_hash_ops));
+
+ assert_se(hashmap_dump_sorted(m, &vals, &n) >= 0);
+ assert_se(n == 0);
+ assert_se(!vals);
+
+ assert_se(hashmap_put(m, "key 0", expected[0]) == 1);
+ assert_se(hashmap_put(m, "key 1", expected[1]) == 1);
+ assert_se(hashmap_put(m, "key 2", expected[2]) == 1);
+
+ assert_se(hashmap_dump_sorted(m, &vals, &n) >= 0);
+ assert_se(n == ELEMENTSOF(expected));
+ assert_se(memcmp(vals, expected, n * sizeof(void*)) == 0);
+
+ vals = mfree(vals);
+ m = hashmap_free(m);
+
+ assert_se(m = hashmap_new(NULL));
+
+ assert_se(hashmap_dump_sorted(m, &vals, &n) >= 0);
+ assert_se(n == 0);
+ assert_se(!vals);
+
+ assert_se(hashmap_put(m, UINT_TO_PTR(333U), expected[2]) == 1);
+ assert_se(hashmap_put(m, UINT_TO_PTR(222U), expected[1]) == 1);
+ assert_se(hashmap_put(m, UINT_TO_PTR(111U), expected[0]) == 1);
+
+ assert_se(hashmap_dump_sorted(m, &vals, &n) >= 0);
+ assert_se(n == ELEMENTSOF(expected));
+ assert_se(memcmp(vals, expected, n * sizeof(void*)) == 0);
+}
+
/* Signal to test-hashmap.c that tests from this compilation unit were run. */
extern int n_extern_tests_run;
TEST(ensure_extern_hashmap_tests) {