chiark / gitweb /
Prep v220: Apply "Fixes to user and session saving"
[elogind.git] / src / basic / 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 <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <errno.h>
26
27 #include "util.h"
28 #include "strv.h"
29
30 char *strv_find(char **l, const char *name) {
31         char **i;
32
33         assert(name);
34
35         STRV_FOREACH(i, l)
36                 if (streq(*i, name))
37                         return *i;
38
39         return NULL;
40 }
41
42 char *strv_find_prefix(char **l, const char *name) {
43         char **i;
44
45         assert(name);
46
47         STRV_FOREACH(i, l)
48                 if (startswith(*i, name))
49                         return *i;
50
51         return NULL;
52 }
53
54 char *strv_find_startswith(char **l, const char *name) {
55         char **i, *e;
56
57         assert(name);
58
59         /* Like strv_find_prefix, but actually returns only the
60          * suffix, not the whole item */
61
62         STRV_FOREACH(i, l) {
63                 e = startswith(*i, name);
64                 if (e)
65                         return e;
66         }
67
68         return NULL;
69 }
70
71 void strv_clear(char **l) {
72         char **k;
73
74         if (!l)
75                 return;
76
77         for (k = l; *k; k++)
78                 free(*k);
79
80         *l = NULL;
81 }
82
83 char **strv_free(char **l) {
84         strv_clear(l);
85         free(l);
86         return NULL;
87 }
88
89 char **strv_copy(char * const *l) {
90         char **r, **k;
91
92         k = r = new(char*, strv_length(l) + 1);
93         if (!r)
94                 return NULL;
95
96         if (l)
97                 for (; *l; k++, l++) {
98                         *k = strdup(*l);
99                         if (!*k) {
100                                 strv_free(r);
101                                 return NULL;
102                         }
103                 }
104
105         *k = NULL;
106         return r;
107 }
108
109 unsigned strv_length(char * const *l) {
110         unsigned n = 0;
111
112         if (!l)
113                 return 0;
114
115         for (; *l; l++)
116                 n++;
117
118         return n;
119 }
120
121 char **strv_new_ap(const char *x, va_list ap) {
122         const char *s;
123         char **a;
124         unsigned n = 0, i = 0;
125         va_list aq;
126
127         /* As a special trick we ignore all listed strings that equal
128          * (const char*) -1. This is supposed to be used with the
129          * STRV_IFNOTNULL() macro to include possibly NULL strings in
130          * the string list. */
131
132         if (x) {
133                 n = x == (const char*) -1 ? 0 : 1;
134
135                 va_copy(aq, ap);
136                 while ((s = va_arg(aq, const char*))) {
137                         if (s == (const char*) -1)
138                                 continue;
139
140                         n++;
141                 }
142
143                 va_end(aq);
144         }
145
146         a = new(char*, n+1);
147         if (!a)
148                 return NULL;
149
150         if (x) {
151                 if (x != (const char*) -1) {
152                         a[i] = strdup(x);
153                         if (!a[i])
154                                 goto fail;
155                         i++;
156                 }
157
158                 while ((s = va_arg(ap, const char*))) {
159
160                         if (s == (const char*) -1)
161                                 continue;
162
163                         a[i] = strdup(s);
164                         if (!a[i])
165                                 goto fail;
166
167                         i++;
168                 }
169         }
170
171         a[i] = NULL;
172
173         return a;
174
175 fail:
176         strv_free(a);
177         return NULL;
178 }
179
180 char **strv_new(const char *x, ...) {
181         char **r;
182         va_list ap;
183
184         va_start(ap, x);
185         r = strv_new_ap(x, ap);
186         va_end(ap);
187
188         return r;
189 }
190
191 int strv_extend_strv(char ***a, char **b) {
192         int r;
193         char **s;
194
195         STRV_FOREACH(s, b) {
196                 r = strv_extend(a, *s);
197                 if (r < 0)
198                         return r;
199         }
200
201         return 0;
202 }
203
204 int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
205         int r;
206         char **s;
207
208         STRV_FOREACH(s, b) {
209                 char *v;
210
211                 v = strappend(*s, suffix);
212                 if (!v)
213                         return -ENOMEM;
214
215                 r = strv_push(a, v);
216                 if (r < 0) {
217                         free(v);
218                         return r;
219                 }
220         }
221
222         return 0;
223 }
224
225 char **strv_split(const char *s, const char *separator) {
226         const char *word, *state;
227         size_t l;
228         unsigned n, i;
229         char **r;
230
231         assert(s);
232
233         n = 0;
234         FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
235                 n++;
236
237         r = new(char*, n+1);
238         if (!r)
239                 return NULL;
240
241         i = 0;
242         FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
243                 r[i] = strndup(word, l);
244                 if (!r[i]) {
245                         strv_free(r);
246                         return NULL;
247                 }
248
249                 i++;
250         }
251
252         r[i] = NULL;
253         return r;
254 }
255
256 /// UNNEEDED by elogind
257 #if 0
258 char **strv_split_newlines(const char *s) {
259         char **l;
260         unsigned n;
261
262         assert(s);
263
264         /* Special version of strv_split() that splits on newlines and
265          * suppresses an empty string at the end */
266
267         l = strv_split(s, NEWLINE);
268         if (!l)
269                 return NULL;
270
271         n = strv_length(l);
272         if (n <= 0)
273                 return l;
274
275         if (isempty(l[n-1])) {
276                 free(l[n-1]);
277                 l[n-1] = NULL;
278         }
279
280         return l;
281 }
282 #endif // 0
283
284 int strv_split_quoted(char ***t, const char *s, UnquoteFlags flags) {
285         size_t n = 0, allocated = 0;
286         _cleanup_strv_free_ char **l = NULL;
287         int r;
288
289         assert(t);
290         assert(s);
291
292         for (;;) {
293                 _cleanup_free_ char *word = NULL;
294
295                 r = unquote_first_word(&s, &word, flags);
296                 if (r < 0)
297                         return r;
298                 if (r == 0)
299                         break;
300
301                 if (!GREEDY_REALLOC(l, allocated, n + 2))
302                         return -ENOMEM;
303
304                 l[n++] = word;
305                 word = NULL;
306
307                 l[n] = NULL;
308         }
309
310         if (!l)
311                 l = new0(char*, 1);
312
313         *t = l;
314         l = NULL;
315
316         return 0;
317 }
318
319 char *strv_join(char **l, const char *separator) {
320         char *r, *e;
321         char **s;
322         size_t n, k;
323
324         if (!separator)
325                 separator = " ";
326
327         k = strlen(separator);
328
329         n = 0;
330         STRV_FOREACH(s, l) {
331                 if (n != 0)
332                         n += k;
333                 n += strlen(*s);
334         }
335
336         r = new(char, n+1);
337         if (!r)
338                 return NULL;
339
340         e = r;
341         STRV_FOREACH(s, l) {
342                 if (e != r)
343                         e = stpcpy(e, separator);
344
345                 e = stpcpy(e, *s);
346         }
347
348         *e = 0;
349
350         return r;
351 }
352
353 char *strv_join_quoted(char **l) {
354         char *buf = NULL;
355         char **s;
356         size_t allocated = 0, len = 0;
357
358         STRV_FOREACH(s, l) {
359                 /* assuming here that escaped string cannot be more
360                  * than twice as long, and reserving space for the
361                  * separator and quotes.
362                  */
363                 _cleanup_free_ char *esc = NULL;
364                 size_t needed;
365
366                 if (!GREEDY_REALLOC(buf, allocated,
367                                     len + strlen(*s) * 2 + 3))
368                         goto oom;
369
370                 esc = cescape(*s);
371                 if (!esc)
372                         goto oom;
373
374                 needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
375                                   len > 0 ? " " : "", esc);
376                 assert(needed < allocated - len);
377                 len += needed;
378         }
379
380         if (!buf)
381                 buf = malloc0(1);
382
383         return buf;
384
385  oom:
386         free(buf);
387         return NULL;
388 }
389
390 int strv_push(char ***l, char *value) {
391         char **c;
392         unsigned n, m;
393
394         if (!value)
395                 return 0;
396
397         n = strv_length(*l);
398
399         /* Increase and check for overflow */
400         m = n + 2;
401         if (m < n)
402                 return -ENOMEM;
403
404         c = realloc_multiply(*l, sizeof(char*), m);
405         if (!c)
406                 return -ENOMEM;
407
408         c[n] = value;
409         c[n+1] = NULL;
410
411         *l = c;
412         return 0;
413 }
414
415 int strv_push_pair(char ***l, char *a, char *b) {
416         char **c;
417         unsigned n, m;
418
419         if (!a && !b)
420                 return 0;
421
422         n = strv_length(*l);
423
424         /* increase and check for overflow */
425         m = n + !!a + !!b + 1;
426         if (m < n)
427                 return -ENOMEM;
428
429         c = realloc_multiply(*l, sizeof(char*), m);
430         if (!c)
431                 return -ENOMEM;
432
433         if (a)
434                 c[n++] = a;
435         if (b)
436                 c[n++] = b;
437         c[n] = NULL;
438
439         *l = c;
440         return 0;
441 }
442
443 int strv_push_prepend(char ***l, char *value) {
444         char **c;
445         unsigned n, m, i;
446
447         if (!value)
448                 return 0;
449
450         n = strv_length(*l);
451
452         /* increase and check for overflow */
453         m = n + 2;
454         if (m < n)
455                 return -ENOMEM;
456
457         c = new(char*, m);
458         if (!c)
459                 return -ENOMEM;
460
461         for (i = 0; i < n; i++)
462                 c[i+1] = (*l)[i];
463
464         c[0] = value;
465         c[n+1] = NULL;
466
467         free(*l);
468         *l = c;
469
470         return 0;
471 }
472
473 int strv_consume(char ***l, char *value) {
474         int r;
475
476         r = strv_push(l, value);
477         if (r < 0)
478                 free(value);
479
480         return r;
481 }
482
483 /// UNNEEDED by elogind
484 #if 0
485 int strv_consume_pair(char ***l, char *a, char *b) {
486         int r;
487
488         r = strv_push_pair(l, a, b);
489         if (r < 0) {
490                 free(a);
491                 free(b);
492         }
493
494         return r;
495 }
496 #endif // 0
497
498 int strv_consume_prepend(char ***l, char *value) {
499         int r;
500
501         r = strv_push_prepend(l, value);
502         if (r < 0)
503                 free(value);
504
505         return r;
506 }
507
508 int strv_extend(char ***l, const char *value) {
509         char *v;
510
511         if (!value)
512                 return 0;
513
514         v = strdup(value);
515         if (!v)
516                 return -ENOMEM;
517
518         return strv_consume(l, v);
519 }
520
521 char **strv_uniq(char **l) {
522         char **i;
523
524         /* Drops duplicate entries. The first identical string will be
525          * kept, the others dropped */
526
527         STRV_FOREACH(i, l)
528                 strv_remove(i+1, *i);
529
530         return l;
531 }
532
533 /// UNNEEDED by elogind
534 #if 0
535 bool strv_is_uniq(char **l) {
536         char **i;
537
538         STRV_FOREACH(i, l)
539                 if (strv_find(i+1, *i))
540                         return false;
541
542         return true;
543 }
544 #endif // 0
545
546 char **strv_remove(char **l, const char *s) {
547         char **f, **t;
548
549         if (!l)
550                 return NULL;
551
552         assert(s);
553
554         /* Drops every occurrence of s in the string list, edits
555          * in-place. */
556
557         for (f = t = l; *f; f++)
558                 if (streq(*f, s))
559                         free(*f);
560                 else
561                         *(t++) = *f;
562
563         *t = NULL;
564         return l;
565 }
566
567 char **strv_parse_nulstr(const char *s, size_t l) {
568         const char *p;
569         unsigned c = 0, i = 0;
570         char **v;
571
572         assert(s || l <= 0);
573
574         if (l <= 0)
575                 return new0(char*, 1);
576
577         for (p = s; p < s + l; p++)
578                 if (*p == 0)
579                         c++;
580
581         if (s[l-1] != 0)
582                 c++;
583
584         v = new0(char*, c+1);
585         if (!v)
586                 return NULL;
587
588         p = s;
589         while (p < s + l) {
590                 const char *e;
591
592                 e = memchr(p, 0, s + l - p);
593
594                 v[i] = strndup(p, e ? e - p : s + l - p);
595                 if (!v[i]) {
596                         strv_free(v);
597                         return NULL;
598                 }
599
600                 i++;
601
602                 if (!e)
603                         break;
604
605                 p = e + 1;
606         }
607
608         assert(i == c);
609
610         return v;
611 }
612
613 char **strv_split_nulstr(const char *s) {
614         const char *i;
615         char **r = NULL;
616
617         NULSTR_FOREACH(i, s)
618                 if (strv_extend(&r, i) < 0) {
619                         strv_free(r);
620                         return NULL;
621                 }
622
623         if (!r)
624                 return strv_new(NULL, NULL);
625
626         return r;
627 }
628
629 bool strv_overlap(char **a, char **b) {
630         char **i;
631
632         STRV_FOREACH(i, a)
633                 if (strv_contains(b, *i))
634                         return true;
635
636         return false;
637 }
638
639 static int str_compare(const void *_a, const void *_b) {
640         const char **a = (const char**) _a, **b = (const char**) _b;
641
642         return strcmp(*a, *b);
643 }
644
645 char **strv_sort(char **l) {
646
647         if (strv_isempty(l))
648                 return l;
649
650         qsort(l, strv_length(l), sizeof(char*), str_compare);
651         return l;
652 }
653
654 /// UNNEEDED by elogind
655 #if 0
656 bool strv_equal(char **a, char **b) {
657         if (!a || !b)
658                 return a == b;
659
660         for ( ; *a || *b; ++a, ++b)
661                 if (!streq_ptr(*a, *b))
662                         return false;
663
664         return true;
665 }
666 #endif // 0
667
668 void strv_print(char **l) {
669         char **s;
670
671         STRV_FOREACH(s, l)
672                 puts(*s);
673 }
674
675 /// UNNEEDED by elogind
676 #if 0
677 int strv_extendf(char ***l, const char *format, ...) {
678         va_list ap;
679         char *x;
680         int r;
681
682         va_start(ap, format);
683         r = vasprintf(&x, format, ap);
684         va_end(ap);
685
686         if (r < 0)
687                 return -ENOMEM;
688
689         return strv_consume(l, x);
690 }
691
692 char **strv_reverse(char **l) {
693         unsigned n, i;
694
695         n = strv_length(l);
696         if (n <= 1)
697                 return l;
698
699         for (i = 0; i < n / 2; i++) {
700                 char *t;
701
702                 t = l[i];
703                 l[i] = l[n-1-i];
704                 l[n-1-i] = t;
705         }
706
707         return l;
708 }
709 #endif // 0
710
711 bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
712         char* const* p;
713
714         STRV_FOREACH(p, patterns)
715                 if (fnmatch(*p, s, 0) == 0)
716                         return true;
717
718         return false;
719 }