summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/basic/string-util.c28
-rw-r--r--src/basic/string-util.h4
-rw-r--r--src/test/test-string-util.c35
3 files changed, 58 insertions, 9 deletions
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index 445766e4a..704d020b2 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -708,16 +708,20 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
return obuf;
}
-char *strextend(char **x, ...) {
- va_list ap;
- size_t f, l;
+char *strextend_with_separator(char **x, const char *separator, ...) {
+ bool need_separator;
+ size_t f, l, l_separator;
char *r, *p;
+ va_list ap;
assert(x);
l = f = strlen_ptr(*x);
- va_start(ap, x);
+ need_separator = !isempty(*x);
+ l_separator = strlen_ptr(separator);
+
+ va_start(ap, separator);
for (;;) {
const char *t;
size_t n;
@@ -727,22 +731,29 @@ char *strextend(char **x, ...) {
break;
n = strlen(t);
+
+ if (need_separator)
+ n += l_separator;
+
if (n > ((size_t) -1) - l) {
va_end(ap);
return NULL;
}
l += n;
+ need_separator = true;
}
va_end(ap);
+ need_separator = !isempty(*x);
+
r = realloc(*x, l+1);
if (!r)
return NULL;
p = r + f;
- va_start(ap, x);
+ va_start(ap, separator);
for (;;) {
const char *t;
@@ -750,10 +761,17 @@ char *strextend(char **x, ...) {
if (!t)
break;
+ if (need_separator && separator)
+ p = stpcpy(p, separator);
+
p = stpcpy(p, t);
+
+ need_separator = true;
}
va_end(ap);
+ assert(p == r + l);
+
*p = 0;
*x = r;
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
index f68b5f2f3..7276cfd6f 100644
--- a/src/basic/string-util.h
+++ b/src/basic/string-util.h
@@ -174,7 +174,9 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
char *strip_tab_ansi(char **p, size_t *l);
-char *strextend(char **x, ...) _sentinel_;
+char *strextend_with_separator(char **x, const char *separator, ...) _sentinel_;
+
+#define strextend(x, ...) strextend_with_separator(x, NULL, __VA_ARGS__)
char *strrep(const char *s, unsigned n);
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 3938012d2..12340f075 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -105,9 +105,37 @@ static void test_strstrip(void) {
}
static void test_strextend(void) {
- _cleanup_free_ char *str = strdup("0123");
- strextend(&str, "456", "78", "9", NULL);
- assert_se(streq(str, "0123456789"));
+ _cleanup_free_ char *str = NULL;
+
+ assert_se(strextend(&str, NULL));
+ assert_se(streq_ptr(str, ""));
+ assert_se(strextend(&str, "", "0", "", "", "123", NULL));
+ assert_se(streq_ptr(str, "0123"));
+ assert_se(strextend(&str, "456", "78", "9", NULL));
+ assert_se(streq_ptr(str, "0123456789"));
+}
+
+static void test_strextend_with_separator(void) {
+ _cleanup_free_ char *str = NULL;
+
+ assert_se(strextend_with_separator(&str, NULL, NULL));
+ assert_se(streq_ptr(str, ""));
+ str = mfree(str);
+
+ assert_se(strextend_with_separator(&str, "...", NULL));
+ assert_se(streq_ptr(str, ""));
+ assert_se(strextend_with_separator(&str, "...", NULL));
+ assert_se(streq_ptr(str, ""));
+ str = mfree(str);
+
+ assert_se(strextend_with_separator(&str, "xyz", "a", "bb", "ccc", NULL));
+ assert_se(streq_ptr(str, "axyzbbxyzccc"));
+ str = mfree(str);
+
+ assert_se(strextend_with_separator(&str, ",", "start", "", "1", "234", NULL));
+ assert_se(streq_ptr(str, "start,,1,234"));
+ assert_se(strextend_with_separator(&str, ";", "more", "5", "678", NULL));
+ assert_se(streq_ptr(str, "start,,1,234;more;5;678"));
}
static void test_strrep(void) {
@@ -357,6 +385,7 @@ int main(int argc, char *argv[]) {
test_streq_ptr();
test_strstrip();
test_strextend();
+ test_strextend_with_separator();
test_strrep();
test_strappend();
test_string_has_cc();