summary refs log tree commit diff
path: root/shared/systemd/src/basic/strv.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared/systemd/src/basic/strv.c')
-rw-r--r--shared/systemd/src/basic/strv.c115
1 files changed, 72 insertions, 43 deletions
diff --git a/shared/systemd/src/basic/strv.c b/shared/systemd/src/basic/strv.c
index 6f812139..30d3af46 100644
--- a/shared/systemd/src/basic/strv.c
+++ b/shared/systemd/src/basic/strv.c
@@ -260,44 +260,6 @@ int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix) {
 }
 #endif /* NM_IGNORED */
 
-char **strv_split_full(const char *s, const char *separator, SplitFlags flags) {
-        const char *word, *state;
-        size_t l;
-        size_t n, i;
-        char **r;
-
-        assert(s);
-
-        if (!separator)
-                separator = WHITESPACE;
-
-        s += strspn(s, separator);
-        if (isempty(s))
-                return new0(char*, 1);
-
-        n = 0;
-        _FOREACH_WORD(word, l, s, separator, flags, state)
-                n++;
-
-        r = new(char*, n+1);
-        if (!r)
-                return NULL;
-
-        i = 0;
-        _FOREACH_WORD(word, l, s, separator, flags, state) {
-                r[i] = strndup(word, l);
-                if (!r[i]) {
-                        strv_free(r);
-                        return NULL;
-                }
-
-                i++;
-        }
-
-        r[i] = NULL;
-        return r;
-}
-
 char **strv_split_newlines(const char *s) {
         char **l;
         size_t n;
@@ -321,8 +283,7 @@ char **strv_split_newlines(const char *s) {
         return l;
 }
 
-#if 0 /* NM_IGNORED */
-int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
+int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags) {
         _cleanup_strv_free_ char **l = NULL;
         size_t n = 0, allocated = 0;
         int r;
@@ -357,9 +318,62 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
 
         return (int) n;
 }
+
+#if 0 /* NM_IGNORED */
+int strv_split_colon_pairs(char ***t, const char *s) {
+        _cleanup_strv_free_ char **l = NULL;
+        size_t n = 0, allocated = 0;
+        int r;
+
+        assert(t);
+        assert(s);
+
+        for (;;) {
+                _cleanup_free_ char *first = NULL, *second = NULL, *tuple = NULL, *second_or_empty = NULL;
+
+                r = extract_first_word(&s, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                const char *p = tuple;
+                r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS,
+                                       &first, &second, NULL);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+                /* Enforce that at most 2 colon-separated words are contained in each group */
+                if (!isempty(p))
+                        return -EINVAL;
+
+                second_or_empty = strdup(strempty(second));
+                if (!second_or_empty)
+                        return -ENOMEM;
+
+                if (!GREEDY_REALLOC(l, allocated, n + 3))
+                        return -ENOMEM;
+
+                l[n++] = TAKE_PTR(first);
+                l[n++] = TAKE_PTR(second_or_empty);
+
+                l[n] = NULL;
+        }
+
+        if (!l) {
+                l = new0(char*, 1);
+                if (!l)
+                        return -ENOMEM;
+        }
+
+        *t = TAKE_PTR(l);
+
+        return (int) n;
+}
 #endif /* NM_IGNORED */
 
-char *strv_join_prefix(char * const *l, const char *separator, const char *prefix) {
+char *strv_join_full(char * const *l, const char *separator, const char *prefix, bool unescape_separators) {
         char * const *s;
         char *r, *e;
         size_t n, k, m;
@@ -370,11 +384,17 @@ char *strv_join_prefix(char * const *l, const char *separator, const char *prefi
         k = strlen(separator);
         m = strlen_ptr(prefix);
 
+        if (unescape_separators) /* If there separator is multi-char, we won't know how to escape it. */
+                assert(k == 1);
+
         n = 0;
         STRV_FOREACH(s, l) {
                 if (s != l)
                         n += k;
-                n += m + strlen(*s);
+
+                bool needs_escaping = unescape_separators && strchr(*s, separator[0]);
+
+                n += m + strlen(*s) * (1 + needs_escaping);
         }
 
         r = new(char, n+1);
@@ -389,7 +409,16 @@ char *strv_join_prefix(char * const *l, const char *separator, const char *prefi
                 if (prefix)
                         e = stpcpy(e, prefix);
 
-                e = stpcpy(e, *s);
+                bool needs_escaping = unescape_separators && strchr(*s, separator[0]);
+
+                if (needs_escaping)
+                        for (size_t i = 0; (*s)[i]; i++) {
+                                if ((*s)[i] == separator[0])
+                                        *(e++) = '\\';
+                                *(e++) = (*s)[i];
+                        }
+                else
+                        e = stpcpy(e, *s);
         }
 
         *e = 0;