mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
string-util: make strjoin() just a special case of strextend() (#36011)
This is split out of #36010, but makes a ton of sense on its own.
This commit is contained in:
@@ -77,38 +77,6 @@ char* strnappend(const char *s, const char *suffix, size_t b) {
|
||||
return r;
|
||||
}
|
||||
|
||||
char* strjoin_real(const char *x, ...) {
|
||||
va_list ap;
|
||||
size_t l = 1;
|
||||
char *r, *p;
|
||||
|
||||
va_start(ap, x);
|
||||
for (const char *t = x; t; t = va_arg(ap, const char *)) {
|
||||
size_t n;
|
||||
|
||||
n = strlen(t);
|
||||
if (n > SIZE_MAX - l) {
|
||||
va_end(ap);
|
||||
return NULL;
|
||||
}
|
||||
l += n;
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
p = r = new(char, l);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
va_start(ap, x);
|
||||
for (const char *t = x; t; t = va_arg(ap, const char *))
|
||||
p = stpcpy(p, t);
|
||||
va_end(ap);
|
||||
|
||||
*p = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char* strstrip(char *s) {
|
||||
if (!s)
|
||||
return NULL;
|
||||
@@ -843,12 +811,14 @@ char* strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
|
||||
}
|
||||
|
||||
char* strextend_with_separator_internal(char **x, const char *separator, ...) {
|
||||
_cleanup_free_ char *buffer = NULL;
|
||||
size_t f, l, l_separator;
|
||||
bool need_separator;
|
||||
char *nr, *p;
|
||||
va_list ap;
|
||||
|
||||
assert(x);
|
||||
if (!x)
|
||||
x = &buffer;
|
||||
|
||||
l = f = strlen_ptr(*x);
|
||||
|
||||
@@ -856,13 +826,14 @@ char* strextend_with_separator_internal(char **x, const char *separator, ...) {
|
||||
l_separator = strlen_ptr(separator);
|
||||
|
||||
va_start(ap, separator);
|
||||
for (;;) {
|
||||
const char *t;
|
||||
for (const char *t;;) {
|
||||
size_t n;
|
||||
|
||||
t = va_arg(ap, const char *);
|
||||
if (!t)
|
||||
break;
|
||||
if (t == POINTER_MAX)
|
||||
continue;
|
||||
|
||||
n = strlen(t);
|
||||
|
||||
@@ -895,6 +866,8 @@ char* strextend_with_separator_internal(char **x, const char *separator, ...) {
|
||||
t = va_arg(ap, const char *);
|
||||
if (!t)
|
||||
break;
|
||||
if (t == POINTER_MAX)
|
||||
continue;
|
||||
|
||||
if (need_separator && separator)
|
||||
p = stpcpy(p, separator);
|
||||
@@ -906,9 +879,13 @@ char* strextend_with_separator_internal(char **x, const char *separator, ...) {
|
||||
va_end(ap);
|
||||
|
||||
assert(p == nr + l);
|
||||
|
||||
*p = 0;
|
||||
|
||||
/* If no buffer to extend was passed in return the start of the buffer */
|
||||
if (buffer)
|
||||
return TAKE_PTR(buffer);
|
||||
|
||||
/* Otherwise we extended the buffer: return the end */
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -108,8 +108,7 @@ char* first_word(const char *s, const char *word) _pure_;
|
||||
|
||||
char* strnappend(const char *s, const char *suffix, size_t length);
|
||||
|
||||
char* strjoin_real(const char *x, ...) _sentinel_;
|
||||
#define strjoin(a, ...) strjoin_real((a), __VA_ARGS__, NULL)
|
||||
#define strjoin(a, ...) strextend_with_separator_internal(NULL, NULL, a, __VA_ARGS__, NULL)
|
||||
|
||||
#define strjoina(a, ...) \
|
||||
({ \
|
||||
|
||||
@@ -262,6 +262,12 @@ TEST(strextend) {
|
||||
ASSERT_STREQ(str, "0123");
|
||||
assert_se(strextend(&str, "456", "78", "9"));
|
||||
ASSERT_STREQ(str, "0123456789");
|
||||
|
||||
assert_se(strextend(&str, "more", NULL, "huch"));
|
||||
ASSERT_STREQ(str, "0123456789more");
|
||||
|
||||
assert_se(strextend(&str, "MORE", POINTER_MAX, "HUCH"));
|
||||
ASSERT_STREQ(str, "0123456789moreMOREHUCH");
|
||||
}
|
||||
|
||||
TEST(strextend_with_separator) {
|
||||
@@ -285,6 +291,9 @@ TEST(strextend_with_separator) {
|
||||
ASSERT_STREQ(str, "start,,1,234");
|
||||
assert_se(strextend_with_separator(&str, ";", "more", "5", "678"));
|
||||
ASSERT_STREQ(str, "start,,1,234;more;5;678");
|
||||
|
||||
assert_se(strextend_with_separator(&str, ";", "xxxx", POINTER_MAX, "yyy"));
|
||||
ASSERT_STREQ(str, "start,,1,234;more;5;678;xxxx;yyy");
|
||||
}
|
||||
|
||||
TEST(strrep) {
|
||||
@@ -400,6 +409,10 @@ TEST(strjoin) {
|
||||
actual = strjoin("foo", NULL, "bar");
|
||||
ASSERT_STREQ(actual, "foo");
|
||||
free(actual);
|
||||
|
||||
actual = strjoin("foo", POINTER_MAX, "bar");
|
||||
ASSERT_STREQ(actual, "foobar");
|
||||
free(actual);
|
||||
}
|
||||
|
||||
TEST(strcmp_ptr) {
|
||||
|
||||
Reference in New Issue
Block a user