chiark / gitweb /
Prep v228: Condense elogind source masks (3/5)
[elogind.git] / src / basic / strv.c
index 9decbb4190c4282352900679fe01ce1c8db91a03..825fdcbdfe10474c9f2036c88b3da8ec6e7fdb72 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdlib.h>
+#include <errno.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 
-#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,21 +200,51 @@ 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
-#if 0
+#if 0 /// UNNEEDED by elogind
 int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
         int r;
         char **s;
@@ -256,8 +298,7 @@ char **strv_split(const char *s, const char *separator) {
         return r;
 }
 
-/// UNNEEDED by elogind
-#if 0
+#if 0 /// UNNEEDED by elogind
 char **strv_split_newlines(const char *s) {
         char **l;
         unsigned n;
@@ -275,17 +316,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 +336,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 +348,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
 
@@ -354,8 +395,7 @@ char *strv_join(char **l, const char *separator) {
         return r;
 }
 
-/// UNNEEDED by elogind
-#if 0
+#if 0 /// UNNEEDED by elogind
 char *strv_join_quoted(char **l) {
         char *buf = NULL;
         char **s;
@@ -487,8 +527,7 @@ int strv_consume(char ***l, char *value) {
         return r;
 }
 
-/// UNNEEDED by elogind
-#if 0
+#if 0 /// UNNEEDED by elogind
 int strv_consume_pair(char ***l, char *a, char *b) {
         int r;
 
@@ -537,8 +576,7 @@ char **strv_uniq(char **l) {
         return l;
 }
 
-/// UNNEEDED by elogind
-#if 0
+#if 0 /// UNNEEDED by elogind
 bool strv_is_uniq(char **l) {
         char **i;
 
@@ -633,8 +671,42 @@ char **strv_split_nulstr(const char *s) {
         return r;
 }
 
-/// UNNEEDED by elogind
-#if 0
+#if 0 /// UNNEEDED by elogind
+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;
 
@@ -644,6 +716,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;
@@ -660,9 +733,14 @@ char **strv_sort(char **l) {
         return l;
 }
 
+#if 0 /// UNNEEDED by elogind
 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))
@@ -730,7 +808,6 @@ char **strv_shell_escape(char **l, const char *bad) {
 
         return l;
 }
-#endif // 0
 
 bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
         char* const* p;
@@ -741,3 +818,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