diff options
Diffstat (limited to 'src/basic/strv.c')
-rw-r--r-- | src/basic/strv.c | 120 |
1 files changed, 83 insertions, 37 deletions
diff --git a/src/basic/strv.c b/src/basic/strv.c index 1065e1b..d081821 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -242,21 +242,19 @@ rollback: return -ENOMEM; } -int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix) { +int strv_extend_strv_biconcat(char ***a, const char *prefix, const char* const *b, const char *suffix) { int r; STRV_FOREACH(s, b) { char *v; - v = strjoin(*s, suffix); + v = strjoin(strempty(prefix), *s, suffix); if (!v) return -ENOMEM; - r = strv_push(a, v); - if (r < 0) { - free(v); + r = strv_consume(a, v); + if (r < 0) return r; - } } return 0; @@ -358,7 +356,7 @@ int strv_split_colon_pairs(char ***t, const char *s) { const char *p = tuple; r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, - &first, &second, NULL); + &first, &second); if (r < 0) return r; if (r == 0) @@ -505,29 +503,31 @@ int strv_insert(char ***l, size_t position, char *value) { char **c; size_t n, m; + assert(l); + if (!value) return 0; n = strv_length(*l); position = MIN(position, n); - /* increase and check for overflow */ - m = n + 2; - if (m < n) + /* check for overflow and increase*/ + if (n > SIZE_MAX - 2) return -ENOMEM; + m = n + 2; - c = new(char*, m); + c = reallocarray(*l, GREEDY_ALLOC_ROUND_UP(m), sizeof(char*)); if (!c) return -ENOMEM; - for (size_t i = 0; i < position; i++) - c[i] = (*l)[i]; + if (n > position) + memmove(c + position + 1, c + position, (n - position) * sizeof(char*)); + c[position] = value; - for (size_t i = position; i < n; i++) - c[i+1] = (*l)[i]; - c[n+1] = NULL; + c[n + 1] = NULL; - return free_and_replace(*l, c); + *l = c; + return 0; } int strv_consume_with_size(char ***l, size_t *n, char *value) { @@ -588,39 +588,63 @@ int strv_extend_with_size(char ***l, size_t *n, const char *value) { return strv_consume_with_size(l, n, v); } -int strv_extend_front(char ***l, const char *value) { +int strv_extend_many_internal(char ***l, const char *value, ...) { + va_list ap; size_t n, m; - char *v, **c; + int r; assert(l); - /* Like strv_extend(), but prepends rather than appends the new entry */ + m = n = strv_length(*l); - if (!value) - return 0; + r = 0; + va_start(ap, value); + for (const char *s = value; s != POINTER_MAX; s = va_arg(ap, const char*)) { + if (!s) + continue; - n = strv_length(*l); + if (m > SIZE_MAX-1) { /* overflow */ + r = -ENOMEM; + break; + } + m++; + } + va_end(ap); - /* Increase and overflow check. */ - m = n + 2; - if (m < n) + if (r < 0) + return r; + if (m > SIZE_MAX-1) return -ENOMEM; - v = strdup(value); - if (!v) + char **c = reallocarray(*l, GREEDY_ALLOC_ROUND_UP(m+1), sizeof(char*)); + if (!c) return -ENOMEM; + *l = c; - c = reallocarray(*l, m, sizeof(char*)); - if (!c) { - free(v); - return -ENOMEM; + 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); - memmove(c+1, c, n * sizeof(char*)); - c[0] = v; - c[n+1] = NULL; + if (r < 0) { + /* rollback on error */ + for (size_t j = n; j < i; j++) + c[j] = mfree(c[j]); + return r; + } - *l = c; + c[i] = NULL; return 0; } @@ -722,6 +746,26 @@ int strv_extendf(char ***l, const char *format, ...) { return strv_consume(l, x); } +char* startswith_strv(const char *s, char * const *l) { + STRV_FOREACH(i, l) { + char *found = startswith(s, *i); + if (found) + return found; + } + + return NULL; +} + +char* endswith_strv(const char *s, char * const *l) { + STRV_FOREACH(i, l) { + char *found = endswith(s, *i); + if (found) + return found; + } + + return NULL; +} + char** strv_reverse(char **l) { size_t n; @@ -848,13 +892,15 @@ int fputstrv(FILE *f, char * const *l, const char *separator, bool *space) { bool b = false; int r; + assert(f); + /* Like fputs(), but for strv, and with a less stupid argument order */ if (!space) space = &b; STRV_FOREACH(s, l) { - r = fputs_with_space(f, *s, separator, space); + r = fputs_with_separator(f, *s, separator, space); if (r < 0) return r; } |