]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
strv: introduce strv_sort_uniq()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 17 Jun 2024 14:52:14 +0000 (23:52 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 17 Jun 2024 15:22:33 +0000 (00:22 +0900)
We often call strv_sort() and strv_uniq(). If a strv is already sorted.
uniquifying can be faster.

Prompted by https://github.com/systemd/systemd/pull/33012#discussion_r1636633627.

src/basic/strv.c
src/basic/strv.h
src/test/test-strv.c

index d081821a8625a378c8445a73e2dd6419c28b11e7..a4cbac5ea7a023b93e5ae7e851e1e5a1dd3bea50 100644 (file)
@@ -704,6 +704,21 @@ char** strv_sort(char **l) {
         return l;
 }
 
+char** strv_sort_uniq(char **l) {
+        if (strv_isempty(l))
+                return l;
+
+        char **tail = strv_sort(l), *prev = NULL;
+        STRV_FOREACH(i, l)
+                if (streq_ptr(*i, prev))
+                        free(*i);
+                else
+                        *(tail++) = prev = *i;
+
+        *tail = NULL;
+        return l;
+}
+
 int strv_compare(char * const *a, char * const *b) {
         int r;
 
index 169737d1d8c18f72cdb3991cf7994b278168796b..4ea9b1a010796a26bc181c0502568a89e9d58538 100644 (file)
@@ -161,6 +161,7 @@ bool strv_overlap(char * const *a, char * const *b) _pure_;
         _STRV_FOREACH_PAIR(x, y, l, UNIQ_T(i, UNIQ))
 
 char** strv_sort(char **l);
+char** strv_sort_uniq(char **l);
 void strv_print_full(char * const *l, const char *prefix);
 static inline void strv_print(char * const *l) {
         strv_print_full(l, NULL);
index 28b8b2270c099bfafda3b77203fe9f2fc0f566a9..2cd2029c403c3ec2bb727beb51c9a44172efb2e1 100644 (file)
@@ -527,6 +527,81 @@ TEST(strv_sort) {
         ASSERT_STREQ(input_table[4], "durian");
 }
 
+TEST(strv_sort_uniq) {
+        static const char* input_table[] = {
+                "durian",
+                "apple",
+                "citrus",
+                 "CAPITAL LETTERS FIRST",
+                "banana",
+                "durian",
+                "apple",
+                "citrus",
+                 "CAPITAL LETTERS FIRST",
+                "banana",
+                "durian",
+                "apple",
+                "citrus",
+                 "CAPITAL LETTERS FIRST",
+                "banana",
+                NULL
+        };
+
+        _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL;
+
+        ASSERT_NULL(strv_sort_uniq(a));
+
+        ASSERT_NOT_NULL(a = strv_new(NULL));
+        assert_se(strv_sort_uniq(a) == a);
+        ASSERT_NULL(a[0]);
+        a = strv_free(a);
+
+        ASSERT_NOT_NULL(a = strv_new("a", "a", "a", "a", "a"));
+        assert_se(strv_sort_uniq(a) == a);
+        ASSERT_STREQ(a[0], "a");
+        ASSERT_NULL(a[1]);
+        a = strv_free(a);
+
+        ASSERT_NOT_NULL(a = strv_new("a", "a", "a", "a", "b"));
+        assert_se(strv_sort_uniq(a) == a);
+        ASSERT_STREQ(a[0], "a");
+        ASSERT_STREQ(a[1], "b");
+        ASSERT_NULL(a[2]);
+        a = strv_free(a);
+
+        ASSERT_NOT_NULL(a = strv_new("b", "a", "a", "a", "a"));
+        assert_se(strv_sort_uniq(a) == a);
+        ASSERT_STREQ(a[0], "a");
+        ASSERT_STREQ(a[1], "b");
+        ASSERT_NULL(a[2]);
+        a = strv_free(a);
+
+        ASSERT_NOT_NULL(a = strv_new("a", "a", "b", "a", "b"));
+        assert_se(strv_sort_uniq(a) == a);
+        ASSERT_STREQ(a[0], "a");
+        ASSERT_STREQ(a[1], "b");
+        ASSERT_NULL(a[2]);
+        a = strv_free(a);
+
+        ASSERT_NOT_NULL(a = strv_copy((char**) input_table));
+        ASSERT_NOT_NULL(b = strv_copy((char**) input_table));
+        ASSERT_NOT_NULL(c = strv_copy((char**) input_table));
+
+        assert_se(strv_sort_uniq(a) == a);
+        assert_se(strv_sort(strv_uniq(b)) == b);
+        assert_se(strv_uniq(strv_sort(c)) == c);
+
+        assert_se(strv_equal(a, b));
+        assert_se(strv_equal(a, c));
+
+        ASSERT_STREQ(a[0], "CAPITAL LETTERS FIRST");
+        ASSERT_STREQ(a[1], "apple");
+        ASSERT_STREQ(a[2], "banana");
+        ASSERT_STREQ(a[3], "citrus");
+        ASSERT_STREQ(a[4], "durian");
+        ASSERT_NULL(a[5]);
+}
+
 TEST(strv_extend_strv_biconcat) {
         _cleanup_strv_free_ char **a = NULL, **b = NULL;