strv: add strv_extend_many() helper

This is supposed to be a nicer, faster replacement for the often seen
pattern strv_extend_strv(l, STRV_MAKE(…), false)
This commit is contained in:
Lennart Poettering
2024-01-17 11:32:11 +01:00
parent b9d37112f2
commit 80f1e209a5
3 changed files with 88 additions and 0 deletions
+60
View File
@@ -590,6 +590,66 @@ int strv_extend_with_size(char ***l, size_t *n, const char *value) {
return strv_consume_with_size(l, n, v);
}
int strv_extend_many_internal(char ***l, const char *value, ...) {
va_list ap;
size_t n, m;
int r;
assert(l);
m = n = strv_length(*l);
r = 0;
va_start(ap, value);
for (const char *s = value; s != POINTER_MAX; s = va_arg(ap, const char*)) {
if (!s)
continue;
if (m > SIZE_MAX-1) { /* overflow */
r = -ENOMEM;
break;
}
m++;
}
va_end(ap);
if (r < 0)
return r;
if (m > SIZE_MAX-1)
return -ENOMEM;
char **c = reallocarray(*l, GREEDY_ALLOC_ROUND_UP(m+1), sizeof(char*));
if (!c)
return -ENOMEM;
*l = c;
r = 0;
size_t i = n;
va_start(ap, value);
for (const char *s = value; s != POINTER_MAX; s = va_arg(ap, const char*)) {
if (!s)
continue;
c[i] = strdup(s);
if (!c[i]) {
r = -ENOMEM;
break;
}
i++;
}
va_end(ap);
if (r < 0) {
/* rollback on error */
for (size_t j = n; j < i; j++)
c[j] = mfree(c[j]);
return r;
}
c[i] = NULL;
return 0;
}
char** strv_uniq(char **l) {
/* Drops duplicate entries. The first identical string will be
* kept, the others dropped */
+3
View File
@@ -55,6 +55,9 @@ static inline int strv_extend(char ***l, const char *value) {
return strv_extend_with_size(l, NULL, value);
}
int strv_extend_many_internal(char ***l, const char *value, ...);
#define strv_extend_many(l, ...) strv_extend_many_internal(l, __VA_ARGS__, POINTER_MAX)
int strv_extendf(char ***l, const char *format, ...) _printf_(2,3);
int strv_push_with_size(char ***l, size_t *n, char *value);