X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbasic%2Fstrv.c;h=7401c29081b5d98c9ce2bb002ea5ded2821bc360;hb=eaca07ccfdf5d7dabc50afc7e539c2413dd69d3e;hp=b6e6d505013619cd20e4daa929634d7b0eb58449;hpb=21ecddbbb2c9e06d080b2526a870898a8b90f52a;p=elogind.git diff --git a/src/basic/strv.c b/src/basic/strv.c index b6e6d5050..7401c2908 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -19,13 +19,16 @@ along with systemd; If not, see . ***/ -#include +#include #include +#include #include -#include -#include "util.h" +#include "alloc-util.h" +#include "escape.h" +#include "string-util.h" #include "strv.h" +#include "util.h" char *strv_find(char **l, const char *name) { char **i; @@ -86,6 +89,15 @@ char **strv_free(char **l) { return NULL; } +char **strv_free_erase(char **l) { + char **i; + + STRV_FOREACH(i, l) + string_erase(*i); + + return strv_free(l); +} + char **strv_copy(char * const *l) { char **r, **k; @@ -188,17 +200,48 @@ char **strv_new(const char *x, ...) { return r; } -int strv_extend_strv(char ***a, char **b) { - int r; - char **s; +int strv_extend_strv(char ***a, char **b, bool filter_duplicates) { + char **s, **t; + size_t p, q, i = 0, j; + + assert(a); + + if (strv_isempty(b)) + return 0; + + p = strv_length(*a); + q = strv_length(b); + + t = realloc(*a, sizeof(char*) * (p + q + 1)); + if (!t) + return -ENOMEM; + + t[p] = NULL; + *a = t; STRV_FOREACH(s, b) { - r = strv_extend(a, *s); - if (r < 0) - return r; + + if (filter_duplicates && strv_contains(t, *s)) + continue; + + t[p+i] = strdup(*s); + if (!t[p+i]) + goto rollback; + + i++; + t[p+i] = NULL; } - return 0; + assert(i <= q); + + return (int) i; + +rollback: + for (j = 0; j < i; j++) + free(t[p + j]); + + t[p] = NULL; + return -ENOMEM; } /// UNNEEDED by elogind @@ -275,17 +318,15 @@ char **strv_split_newlines(const char *s) { if (n <= 0) return l; - if (isempty(l[n-1])) { - free(l[n-1]); - l[n-1] = NULL; - } + if (isempty(l[n - 1])) + l[n-1] = mfree(l[n-1]); return l; } int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) { - size_t n = 0, allocated = 0; _cleanup_strv_free_ char **l = NULL; + size_t n = 0, allocated = 0; int r; assert(t); @@ -297,9 +338,8 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract r = extract_first_word(&s, &word, separators, flags); if (r < 0) return r; - if (r == 0) { + if (r == 0) break; - } if (!GREEDY_REALLOC(l, allocated, n + 2)) return -ENOMEM; @@ -310,13 +350,16 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract l[n] = NULL; } - if (!l) + if (!l) { l = new0(char*, 1); + if (!l) + return -ENOMEM; + } *t = l; l = NULL; - return 0; + return (int) n; } #endif // 0 @@ -633,6 +676,43 @@ char **strv_split_nulstr(const char *s) { return r; } +/// UNNEEDED by elogind +#if 0 +int strv_make_nulstr(char **l, char **p, size_t *q) { + size_t n_allocated = 0, n = 0; + _cleanup_free_ char *m = NULL; + char **i; + + assert(p); + assert(q); + + STRV_FOREACH(i, l) { + size_t z; + + z = strlen(*i); + + if (!GREEDY_REALLOC(m, n_allocated, n + z + 1)) + return -ENOMEM; + + memcpy(m + n, *i, z + 1); + n += z + 1; + } + + if (!m) { + m = new0(char, 1); + if (!m) + return -ENOMEM; + n = 0; + } + + *p = m; + *q = n; + + m = NULL; + + return 0; +} + bool strv_overlap(char **a, char **b) { char **i; @@ -642,6 +722,7 @@ bool strv_overlap(char **a, char **b) { return false; } +#endif // 0 static int str_compare(const void *_a, const void *_b) { const char **a = (const char**) _a, **b = (const char**) _b; @@ -661,8 +742,12 @@ char **strv_sort(char **l) { /// UNNEEDED by elogind #if 0 bool strv_equal(char **a, char **b) { - if (!a || !b) - return a == b; + + if (strv_isempty(a)) + return strv_isempty(b); + + if (strv_isempty(b)) + return false; for ( ; *a || *b; ++a, ++b) if (!streq_ptr(*a, *b)) @@ -670,7 +755,6 @@ bool strv_equal(char **a, char **b) { return true; } -#endif // 0 void strv_print(char **l) { char **s; @@ -679,8 +763,6 @@ void strv_print(char **l) { puts(*s); } -/// UNNEEDED by elogind -#if 0 int strv_extendf(char ***l, const char *format, ...) { va_list ap; char *x; @@ -713,7 +795,6 @@ char **strv_reverse(char **l) { return l; } -#endif // 0 char **strv_shell_escape(char **l, const char *bad) { char **s; @@ -744,3 +825,67 @@ bool strv_fnmatch(char* const* patterns, const char *s, int flags) { return false; } + +char ***strv_free_free(char ***l) { + char ***i; + + if (!l) + return NULL; + + for (i = l; *i; i++) + strv_free(*i); + + free(l); + return NULL; +} + +char **strv_skip(char **l, size_t n) { + + while (n > 0) { + if (strv_isempty(l)) + return l; + + l++, n--; + } + + return l; +} + +int strv_extend_n(char ***l, const char *value, size_t n) { + size_t i, j, k; + char **nl; + + assert(l); + + if (!value) + return 0; + if (n == 0) + return 0; + + /* Adds the value value n times to l */ + + k = strv_length(*l); + + nl = realloc(*l, sizeof(char*) * (k + n + 1)); + if (!nl) + return -ENOMEM; + + *l = nl; + + for (i = k; i < k + n; i++) { + nl[i] = strdup(value); + if (!nl[i]) + goto rollback; + } + + nl[i] = NULL; + return 0; + +rollback: + for (j = k; j < i; j++) + free(nl[j]); + + nl[k] = NULL; + return -ENOMEM; +} +#endif // 0