summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2020-12-06 20:10:48 +0900
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-02-02 14:53:56 +0100
commit041fe7dfeeb0873b7c2f8ae53d8ce3ad2b038721 (patch)
tree32f4eee049596c4dd3efc9d1fcf8ed74af9c94eb
parentfc398137fc2e030821a4e91cb4b348b41e1a85d9 (diff)
downloadsystemd-041fe7dfeeb0873b7c2f8ae53d8ce3ad2b038721.tar.gz
set: introduce set_strjoin()
(cherry picked from commit 4dbce717873000cff7b56f89266d1d2fe53f9284)
-rw-r--r--src/basic/hashmap.c35
-rw-r--r--src/basic/set.h2
-rw-r--r--src/test/test-set.c51
3 files changed, 88 insertions, 0 deletions
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index dd1b18c878..e38e580530 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -1976,3 +1976,38 @@ IteratedCache* iterated_cache_free(IteratedCache *cache) {
return mfree(cache);
}
+
+int set_strjoin(Set *s, const char *separator, char **ret) {
+ size_t separator_len, allocated = 0, len = 0;
+ _cleanup_free_ char *str = NULL;
+ const char *value;
+ bool first = true;
+
+ assert(ret);
+
+ separator_len = strlen_ptr(separator);
+
+ SET_FOREACH(value, s) {
+ size_t l = strlen_ptr(value);
+
+ if (l == 0)
+ continue;
+
+ if (!GREEDY_REALLOC(str, allocated, len + l + (first ? 0 : separator_len) + 1))
+ return -ENOMEM;
+
+ if (separator_len > 0 && !first) {
+ memcpy(str + len, separator, separator_len);
+ len += separator_len;
+ }
+
+ memcpy(str + len, value, l);
+ len += l;
+ first = false;
+ }
+ if (str)
+ str[len] = '\0';
+
+ *ret = TAKE_PTR(str);
+ return 0;
+}
diff --git a/src/basic/set.h b/src/basic/set.h
index 20abc8f0dc..2b06c39cbe 100644
--- a/src/basic/set.h
+++ b/src/basic/set.h
@@ -150,3 +150,5 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
#define _cleanup_set_free_ _cleanup_(set_freep)
#define _cleanup_set_free_free_ _cleanup_(set_free_freep)
+
+int set_strjoin(Set *s, const char *separator, char **ret);
diff --git a/src/test/test-set.c b/src/test/test-set.c
index 16314d051b..8979408242 100644
--- a/src/test/test-set.c
+++ b/src/test/test-set.c
@@ -150,6 +150,56 @@ static void test_set_ensure_consume(void) {
assert_se(set_size(m) == 2);
}
+static void test_set_strjoin(void) {
+ _cleanup_set_free_ Set *m = NULL;
+ _cleanup_free_ char *joined = NULL;
+
+ assert_se(set_strjoin(m, NULL, &joined) >= 0);
+ assert_se(!joined);
+ assert_se(set_strjoin(m, "", &joined) >= 0);
+ assert_se(!joined);
+ assert_se(set_strjoin(m, " ", &joined) >= 0);
+ assert_se(!joined);
+ assert_se(set_strjoin(m, "xxx", &joined) >= 0);
+ assert_se(!joined);
+
+ assert_se(set_put_strdup(&m, "aaa") == 1);
+
+ assert_se(set_strjoin(m, NULL, &joined) >= 0);
+ assert_se(streq(joined, "aaa"));
+
+ joined = mfree(joined);
+ assert_se(set_strjoin(m, "", &joined) >= 0);
+ assert_se(streq(joined, "aaa"));
+
+ joined = mfree(joined);
+ assert_se(set_strjoin(m, " ", &joined) >= 0);
+ assert_se(streq(joined, "aaa"));
+
+ joined = mfree(joined);
+ assert_se(set_strjoin(m, "xxx", &joined) >= 0);
+ assert_se(streq(joined, "aaa"));
+
+ assert_se(set_put_strdup(&m, "bbb") == 1);
+ assert_se(set_put_strdup(&m, "aaa") == 0);
+
+ joined = mfree(joined);
+ assert_se(set_strjoin(m, NULL, &joined) >= 0);
+ assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
+
+ joined = mfree(joined);
+ assert_se(set_strjoin(m, "", &joined) >= 0);
+ assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
+
+ joined = mfree(joined);
+ assert_se(set_strjoin(m, " ", &joined) >= 0);
+ assert_se(STR_IN_SET(joined, "aaa bbb", "bbb aaa"));
+
+ joined = mfree(joined);
+ assert_se(set_strjoin(m, "xxx", &joined) >= 0);
+ assert_se(STR_IN_SET(joined, "aaaxxxbbb", "bbbxxxaaa"));
+}
+
int main(int argc, const char *argv[]) {
test_set_steal_first();
test_set_free_with_destructor();
@@ -160,6 +210,7 @@ int main(int argc, const char *argv[]) {
test_set_ensure_allocated();
test_set_ensure_put();
test_set_ensure_consume();
+ test_set_strjoin();
return 0;
}