strv: add strv_split_colon_pairs function

Given a string in the format 'one:two three four:five', returns a string
vector with each word. If the second element of the tuple is not
present, an empty string is returned in its place, so that the vector
can be processed in pairs.

[zjs: use EXTRACT_UNESCAPE_SEPARATORS instead of EXTRACT_CUNESCAPE_RELAX.
This way we do escaping exactly once and in normal strict mode.]
This commit is contained in:
Luca Boccassi
2020-08-05 21:29:13 +01:00
parent 1e198efcdb
commit a082edd53a
3 changed files with 87 additions and 0 deletions
+52
View File
@@ -353,6 +353,58 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
return (int) n;
}
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;
}
char *strv_join_prefix(char * const *l, const char *separator, const char *prefix) {
char * const *s;
char *r, *e;