]> git.proxmox.com Git - systemd.git/blame - src/shared/strv.c
Imported Upstream version 218
[systemd.git] / src / shared / strv.c
CommitLineData
663996b3
MS
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
31char *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
43char *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
5eef597e
MP
55char *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
663996b3
MS
72void 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
84char **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
104unsigned 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
116char **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
170fail:
171 strv_free(a);
172 return NULL;
173}
174
175char **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
60f067b4
JS
186int strv_extend_strv(char ***a, char **b) {
187 int r;
188 char **s;
663996b3 189
60f067b4
JS
190 STRV_FOREACH(s, b) {
191 r = strv_extend(a, *s);
192 if (r < 0)
193 return r;
663996b3
MS
194 }
195
60f067b4 196 return 0;
663996b3
MS
197}
198
60f067b4
JS
199int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
200 int r;
201 char **s;
663996b3 202
60f067b4
JS
203 STRV_FOREACH(s, b) {
204 char *v;
663996b3 205
60f067b4
JS
206 v = strappend(*s, suffix);
207 if (!v)
208 return -ENOMEM;
663996b3 209
60f067b4
JS
210 r = strv_push(a, v);
211 if (r < 0) {
212 free(v);
213 return r;
663996b3 214 }
663996b3
MS
215 }
216
60f067b4 217 return 0;
663996b3
MS
218}
219
220char **strv_split(const char *s, const char *separator) {
5eef597e 221 const char *word, *state;
663996b3
MS
222 size_t l;
223 unsigned n, i;
224 char **r;
225
226 assert(s);
227
228 n = 0;
5eef597e 229 FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
663996b3
MS
230 n++;
231
232 r = new(char*, n+1);
233 if (!r)
234 return NULL;
235
236 i = 0;
5eef597e
MP
237 FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
238 r[i] = strndup(word, l);
663996b3
MS
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
663996b3
MS
251char **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
f47781d8
MP
276int 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
663996b3
MS
311char *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
14228c0d
MB
345char *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
663996b3
MS
382int strv_push(char ***l, char *value) {
383 char **c;
5eef597e 384 unsigned n, m;
663996b3
MS
385
386 if (!value)
387 return 0;
388
389 n = strv_length(*l);
5eef597e 390
f47781d8 391 /* Increase and check for overflow */
5eef597e
MP
392 m = n + 2;
393 if (m < n)
394 return -ENOMEM;
395
396 c = realloc_multiply(*l, sizeof(char*), m);
663996b3
MS
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
f47781d8
MP
407int strv_push_pair(char ***l, char *a, char *b) {
408 char **c;
409 unsigned n, m;
410
411 if (!a && !b)
412 return 0;
413
414 n = strv_length(*l);
415
416 /* increase and check for overflow */
417 m = n + !!a + !!b + 1;
418 if (m < n)
419 return -ENOMEM;
420
421 c = realloc_multiply(*l, sizeof(char*), m);
422 if (!c)
423 return -ENOMEM;
424
425 if (a)
426 c[n++] = a;
427 if (b)
428 c[n++] = b;
429 c[n] = NULL;
430
431 *l = c;
432 return 0;
433}
434
e842803a
MB
435int strv_push_prepend(char ***l, char *value) {
436 char **c;
5eef597e 437 unsigned n, m, i;
e842803a
MB
438
439 if (!value)
440 return 0;
441
442 n = strv_length(*l);
5eef597e
MP
443
444 /* increase and check for overflow */
445 m = n + 2;
446 if (m < n)
447 return -ENOMEM;
448
449 c = new(char*, m);
e842803a
MB
450 if (!c)
451 return -ENOMEM;
452
453 for (i = 0; i < n; i++)
454 c[i+1] = (*l)[i];
455
456 c[0] = value;
457 c[n+1] = NULL;
458
459 free(*l);
460 *l = c;
461
462 return 0;
463}
464
60f067b4
JS
465int strv_consume(char ***l, char *value) {
466 int r;
467
468 r = strv_push(l, value);
469 if (r < 0)
470 free(value);
471
e842803a
MB
472 return r;
473}
474
f47781d8
MP
475int strv_consume_pair(char ***l, char *a, char *b) {
476 int r;
477
478 r = strv_push_pair(l, a, b);
479 if (r < 0) {
480 free(a);
481 free(b);
482 }
483
484 return r;
485}
486
e842803a
MB
487int strv_consume_prepend(char ***l, char *value) {
488 int r;
489
490 r = strv_push_prepend(l, value);
491 if (r < 0)
492 free(value);
493
60f067b4
JS
494 return r;
495}
496
663996b3
MS
497int strv_extend(char ***l, const char *value) {
498 char *v;
663996b3
MS
499
500 if (!value)
501 return 0;
502
503 v = strdup(value);
504 if (!v)
505 return -ENOMEM;
506
60f067b4 507 return strv_consume(l, v);
663996b3
MS
508}
509
510char **strv_uniq(char **l) {
511 char **i;
512
513 /* Drops duplicate entries. The first identical string will be
514 * kept, the others dropped */
515
516 STRV_FOREACH(i, l)
517 strv_remove(i+1, *i);
518
519 return l;
520}
521
522char **strv_remove(char **l, const char *s) {
523 char **f, **t;
524
525 if (!l)
526 return NULL;
527
528 assert(s);
529
530 /* Drops every occurrence of s in the string list, edits
531 * in-place. */
532
60f067b4
JS
533 for (f = t = l; *f; f++)
534 if (streq(*f, s))
663996b3 535 free(*f);
60f067b4
JS
536 else
537 *(t++) = *f;
663996b3
MS
538
539 *t = NULL;
540 return l;
541}
542
543char **strv_parse_nulstr(const char *s, size_t l) {
544 const char *p;
545 unsigned c = 0, i = 0;
546 char **v;
547
548 assert(s || l <= 0);
549
550 if (l <= 0)
60f067b4 551 return new0(char*, 1);
663996b3
MS
552
553 for (p = s; p < s + l; p++)
554 if (*p == 0)
555 c++;
556
557 if (s[l-1] != 0)
558 c++;
559
560 v = new0(char*, c+1);
561 if (!v)
562 return NULL;
563
564 p = s;
565 while (p < s + l) {
566 const char *e;
567
568 e = memchr(p, 0, s + l - p);
569
570 v[i] = strndup(p, e ? e - p : s + l - p);
571 if (!v[i]) {
572 strv_free(v);
573 return NULL;
574 }
575
576 i++;
577
578 if (!e)
579 break;
580
581 p = e + 1;
582 }
583
584 assert(i == c);
585
586 return v;
587}
588
589char **strv_split_nulstr(const char *s) {
590 const char *i;
591 char **r = NULL;
592
593 NULSTR_FOREACH(i, s)
594 if (strv_extend(&r, i) < 0) {
595 strv_free(r);
596 return NULL;
597 }
598
599 if (!r)
600 return strv_new(NULL, NULL);
601
602 return r;
603}
604
605bool strv_overlap(char **a, char **b) {
60f067b4 606 char **i;
663996b3 607
60f067b4
JS
608 STRV_FOREACH(i, a)
609 if (strv_contains(b, *i))
610 return true;
663996b3
MS
611
612 return false;
613}
614
615static int str_compare(const void *_a, const void *_b) {
616 const char **a = (const char**) _a, **b = (const char**) _b;
617
618 return strcmp(*a, *b);
619}
620
621char **strv_sort(char **l) {
622
623 if (strv_isempty(l))
624 return l;
625
626 qsort(l, strv_length(l), sizeof(char*), str_compare);
627 return l;
628}
629
f47781d8
MP
630bool strv_equal(char **a, char **b) {
631 if (!a || !b)
632 return a == b;
633
634 for ( ; *a || *b; ++a, ++b)
635 if (!streq_ptr(*a, *b))
636 return false;
637
638 return true;
639}
640
663996b3
MS
641void strv_print(char **l) {
642 char **s;
643
663996b3
MS
644 STRV_FOREACH(s, l)
645 puts(*s);
646}
60f067b4
JS
647
648int strv_extendf(char ***l, const char *format, ...) {
649 va_list ap;
650 char *x;
651 int r;
652
653 va_start(ap, format);
654 r = vasprintf(&x, format, ap);
655 va_end(ap);
656
657 if (r < 0)
658 return -ENOMEM;
659
660 return strv_consume(l, x);
661}