]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/strv.c
strv: rework strv_split_quoted() to use unquote_first_word()
[thirdparty/systemd.git] / src / shared / strv.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include "util.h"
29 #include "strv.h"
30
31 char *strv_find(char **l, const char *name) {
32 char **i;
33
34 assert(name);
35
36 STRV_FOREACH(i, l)
37 if (streq(*i, name))
38 return *i;
39
40 return NULL;
41 }
42
43 char *strv_find_prefix(char **l, const char *name) {
44 char **i;
45
46 assert(name);
47
48 STRV_FOREACH(i, l)
49 if (startswith(*i, name))
50 return *i;
51
52 return NULL;
53 }
54
55 char *strv_find_startswith(char **l, const char *name) {
56 char **i, *e;
57
58 assert(name);
59
60 /* Like strv_find_prefix, but actually returns only the
61 * suffix, not the whole item */
62
63 STRV_FOREACH(i, l) {
64 e = startswith(*i, name);
65 if (e)
66 return e;
67 }
68
69 return NULL;
70 }
71
72 void strv_free(char **l) {
73 char **k;
74
75 if (!l)
76 return;
77
78 for (k = l; *k; k++)
79 free(*k);
80
81 free(l);
82 }
83
84 char **strv_copy(char * const *l) {
85 char **r, **k;
86
87 k = r = new(char*, strv_length(l) + 1);
88 if (!r)
89 return NULL;
90
91 if (l)
92 for (; *l; k++, l++) {
93 *k = strdup(*l);
94 if (!*k) {
95 strv_free(r);
96 return NULL;
97 }
98 }
99
100 *k = NULL;
101 return r;
102 }
103
104 unsigned strv_length(char * const *l) {
105 unsigned n = 0;
106
107 if (!l)
108 return 0;
109
110 for (; *l; l++)
111 n++;
112
113 return n;
114 }
115
116 char **strv_new_ap(const char *x, va_list ap) {
117 const char *s;
118 char **a;
119 unsigned n = 0, i = 0;
120 va_list aq;
121
122 /* As a special trick we ignore all listed strings that equal
123 * (const char*) -1. This is supposed to be used with the
124 * STRV_IFNOTNULL() macro to include possibly NULL strings in
125 * the string list. */
126
127 if (x) {
128 n = x == (const char*) -1 ? 0 : 1;
129
130 va_copy(aq, ap);
131 while ((s = va_arg(aq, const char*))) {
132 if (s == (const char*) -1)
133 continue;
134
135 n++;
136 }
137
138 va_end(aq);
139 }
140
141 a = new(char*, n+1);
142 if (!a)
143 return NULL;
144
145 if (x) {
146 if (x != (const char*) -1) {
147 a[i] = strdup(x);
148 if (!a[i])
149 goto fail;
150 i++;
151 }
152
153 while ((s = va_arg(ap, const char*))) {
154
155 if (s == (const char*) -1)
156 continue;
157
158 a[i] = strdup(s);
159 if (!a[i])
160 goto fail;
161
162 i++;
163 }
164 }
165
166 a[i] = NULL;
167
168 return a;
169
170 fail:
171 strv_free(a);
172 return NULL;
173 }
174
175 char **strv_new(const char *x, ...) {
176 char **r;
177 va_list ap;
178
179 va_start(ap, x);
180 r = strv_new_ap(x, ap);
181 va_end(ap);
182
183 return r;
184 }
185
186 int strv_extend_strv(char ***a, char **b) {
187 int r;
188 char **s;
189
190 STRV_FOREACH(s, b) {
191 r = strv_extend(a, *s);
192 if (r < 0)
193 return r;
194 }
195
196 return 0;
197 }
198
199 int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
200 int r;
201 char **s;
202
203 STRV_FOREACH(s, b) {
204 char *v;
205
206 v = strappend(*s, suffix);
207 if (!v)
208 return -ENOMEM;
209
210 r = strv_push(a, v);
211 if (r < 0) {
212 free(v);
213 return r;
214 }
215 }
216
217 return 0;
218 }
219
220 char **strv_split(const char *s, const char *separator) {
221 const char *word, *state;
222 size_t l;
223 unsigned n, i;
224 char **r;
225
226 assert(s);
227
228 n = 0;
229 FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
230 n++;
231
232 r = new(char*, n+1);
233 if (!r)
234 return NULL;
235
236 i = 0;
237 FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
238 r[i] = strndup(word, l);
239 if (!r[i]) {
240 strv_free(r);
241 return NULL;
242 }
243
244 i++;
245 }
246
247 r[i] = NULL;
248 return r;
249 }
250
251 char **strv_split_newlines(const char *s) {
252 char **l;
253 unsigned n;
254
255 assert(s);
256
257 /* Special version of strv_split() that splits on newlines and
258 * suppresses an empty string at the end */
259
260 l = strv_split(s, NEWLINE);
261 if (!l)
262 return NULL;
263
264 n = strv_length(l);
265 if (n <= 0)
266 return l;
267
268 if (isempty(l[n-1])) {
269 free(l[n-1]);
270 l[n-1] = NULL;
271 }
272
273 return l;
274 }
275
276 int strv_split_quoted(char ***t, const char *s, bool relax) {
277 size_t n = 0, allocated = 0;
278 _cleanup_strv_free_ char **l = NULL;
279 int r;
280
281 assert(t);
282 assert(s);
283
284 for (;;) {
285 _cleanup_free_ char *word = NULL;
286
287 r = unquote_first_word(&s, &word, relax);
288 if (r < 0)
289 return r;
290 if (r == 0)
291 break;
292
293 if (!GREEDY_REALLOC(l, allocated, n + 2))
294 return -ENOMEM;
295
296 l[n++] = word;
297 word = NULL;
298
299 l[n] = NULL;
300 }
301
302 if (!l)
303 l = new0(char*, 1);
304
305 *t = l;
306 l = NULL;
307
308 return 0;
309 }
310
311 char *strv_join(char **l, const char *separator) {
312 char *r, *e;
313 char **s;
314 size_t n, k;
315
316 if (!separator)
317 separator = " ";
318
319 k = strlen(separator);
320
321 n = 0;
322 STRV_FOREACH(s, l) {
323 if (n != 0)
324 n += k;
325 n += strlen(*s);
326 }
327
328 r = new(char, n+1);
329 if (!r)
330 return NULL;
331
332 e = r;
333 STRV_FOREACH(s, l) {
334 if (e != r)
335 e = stpcpy(e, separator);
336
337 e = stpcpy(e, *s);
338 }
339
340 *e = 0;
341
342 return r;
343 }
344
345 char *strv_join_quoted(char **l) {
346 char *buf = NULL;
347 char **s;
348 size_t allocated = 0, len = 0;
349
350 STRV_FOREACH(s, l) {
351 /* assuming here that escaped string cannot be more
352 * than twice as long, and reserving space for the
353 * separator and quotes.
354 */
355 _cleanup_free_ char *esc = NULL;
356 size_t needed;
357
358 if (!GREEDY_REALLOC(buf, allocated,
359 len + strlen(*s) * 2 + 3))
360 goto oom;
361
362 esc = cescape(*s);
363 if (!esc)
364 goto oom;
365
366 needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
367 len > 0 ? " " : "", esc);
368 assert(needed < allocated - len);
369 len += needed;
370 }
371
372 if (!buf)
373 buf = malloc0(1);
374
375 return buf;
376
377 oom:
378 free(buf);
379 return NULL;
380 }
381
382 int strv_push(char ***l, char *value) {
383 char **c;
384 unsigned n, m;
385
386 if (!value)
387 return 0;
388
389 n = strv_length(*l);
390
391 /* increase and check for overflow */
392 m = n + 2;
393 if (m < n)
394 return -ENOMEM;
395
396 c = realloc_multiply(*l, sizeof(char*), m);
397 if (!c)
398 return -ENOMEM;
399
400 c[n] = value;
401 c[n+1] = NULL;
402
403 *l = c;
404 return 0;
405 }
406
407 int strv_push_prepend(char ***l, char *value) {
408 char **c;
409 unsigned n, m, i;
410
411 if (!value)
412 return 0;
413
414 n = strv_length(*l);
415
416 /* increase and check for overflow */
417 m = n + 2;
418 if (m < n)
419 return -ENOMEM;
420
421 c = new(char*, m);
422 if (!c)
423 return -ENOMEM;
424
425 for (i = 0; i < n; i++)
426 c[i+1] = (*l)[i];
427
428 c[0] = value;
429 c[n+1] = NULL;
430
431 free(*l);
432 *l = c;
433
434 return 0;
435 }
436
437 int strv_consume(char ***l, char *value) {
438 int r;
439
440 r = strv_push(l, value);
441 if (r < 0)
442 free(value);
443
444 return r;
445 }
446
447 int strv_consume_prepend(char ***l, char *value) {
448 int r;
449
450 r = strv_push_prepend(l, value);
451 if (r < 0)
452 free(value);
453
454 return r;
455 }
456
457 int strv_extend(char ***l, const char *value) {
458 char *v;
459
460 if (!value)
461 return 0;
462
463 v = strdup(value);
464 if (!v)
465 return -ENOMEM;
466
467 return strv_consume(l, v);
468 }
469
470 char **strv_uniq(char **l) {
471 char **i;
472
473 /* Drops duplicate entries. The first identical string will be
474 * kept, the others dropped */
475
476 STRV_FOREACH(i, l)
477 strv_remove(i+1, *i);
478
479 return l;
480 }
481
482 char **strv_remove(char **l, const char *s) {
483 char **f, **t;
484
485 if (!l)
486 return NULL;
487
488 assert(s);
489
490 /* Drops every occurrence of s in the string list, edits
491 * in-place. */
492
493 for (f = t = l; *f; f++)
494 if (streq(*f, s))
495 free(*f);
496 else
497 *(t++) = *f;
498
499 *t = NULL;
500 return l;
501 }
502
503 char **strv_parse_nulstr(const char *s, size_t l) {
504 const char *p;
505 unsigned c = 0, i = 0;
506 char **v;
507
508 assert(s || l <= 0);
509
510 if (l <= 0)
511 return new0(char*, 1);
512
513 for (p = s; p < s + l; p++)
514 if (*p == 0)
515 c++;
516
517 if (s[l-1] != 0)
518 c++;
519
520 v = new0(char*, c+1);
521 if (!v)
522 return NULL;
523
524 p = s;
525 while (p < s + l) {
526 const char *e;
527
528 e = memchr(p, 0, s + l - p);
529
530 v[i] = strndup(p, e ? e - p : s + l - p);
531 if (!v[i]) {
532 strv_free(v);
533 return NULL;
534 }
535
536 i++;
537
538 if (!e)
539 break;
540
541 p = e + 1;
542 }
543
544 assert(i == c);
545
546 return v;
547 }
548
549 char **strv_split_nulstr(const char *s) {
550 const char *i;
551 char **r = NULL;
552
553 NULSTR_FOREACH(i, s)
554 if (strv_extend(&r, i) < 0) {
555 strv_free(r);
556 return NULL;
557 }
558
559 if (!r)
560 return strv_new(NULL, NULL);
561
562 return r;
563 }
564
565 bool strv_overlap(char **a, char **b) {
566 char **i;
567
568 STRV_FOREACH(i, a)
569 if (strv_contains(b, *i))
570 return true;
571
572 return false;
573 }
574
575 static int str_compare(const void *_a, const void *_b) {
576 const char **a = (const char**) _a, **b = (const char**) _b;
577
578 return strcmp(*a, *b);
579 }
580
581 char **strv_sort(char **l) {
582
583 if (strv_isempty(l))
584 return l;
585
586 qsort(l, strv_length(l), sizeof(char*), str_compare);
587 return l;
588 }
589
590 void strv_print(char **l) {
591 char **s;
592
593 STRV_FOREACH(s, l)
594 puts(*s);
595 }
596
597 int strv_extendf(char ***l, const char *format, ...) {
598 va_list ap;
599 char *x;
600 int r;
601
602 va_start(ap, format);
603 r = vasprintf(&x, format, ap);
604 va_end(ap);
605
606 if (r < 0)
607 return -ENOMEM;
608
609 return strv_consume(l, x);
610 }