chiark / gitweb /
1b8e27bc1b963aa6ccbe2a34d437880110bb6250
[elogind.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 void strv_free(char **l) {
56         char **k;
57
58         if (!l)
59                 return;
60
61         for (k = l; *k; k++)
62                 free(*k);
63
64         free(l);
65 }
66
67 void strv_freep(char ***l) {
68         if (!l)
69                 return;
70
71         strv_free(*l);
72         *l = NULL;
73 }
74
75 char **strv_copy(char **l) {
76         char **r, **k;
77
78         k = r = new(char*, strv_length(l)+1);
79         if (!k)
80                 return NULL;
81
82         if (l)
83                 for (; *l; k++, l++)
84                         if (!(*k = strdup(*l)))
85                                 goto fail;
86
87         *k = NULL;
88         return r;
89
90 fail:
91         for (k--; k >= r; k--)
92                 free(*k);
93
94         free(r);
95
96         return NULL;
97 }
98
99 unsigned strv_length(char **l) {
100         unsigned n = 0;
101
102         if (!l)
103                 return 0;
104
105         for (; *l; l++)
106                 n++;
107
108         return n;
109 }
110
111 char **strv_new_ap(const char *x, va_list ap) {
112         const char *s;
113         char **a;
114         unsigned n = 0, i = 0;
115         va_list aq;
116
117         /* As a special trick we ignore all listed strings that equal
118          * (const char*) -1. This is supposed to be used with the
119          * STRV_IFNOTNULL() macro to include possibly NULL strings in
120          * the string list. */
121
122         if (x) {
123                 n = x == (const char*) -1 ? 0 : 1;
124
125                 va_copy(aq, ap);
126                 while ((s = va_arg(aq, const char*))) {
127                         if (s == (const char*) -1)
128                                 continue;
129
130                         n++;
131                 }
132
133                 va_end(aq);
134         }
135
136         a = new(char*, n+1);
137         if (!a)
138                 return NULL;
139
140         if (x) {
141                 if (x != (const char*) -1) {
142                         a[i] = strdup(x);
143                         if (!a[i])
144                                 goto fail;
145                         i++;
146                 }
147
148                 while ((s = va_arg(ap, const char*))) {
149
150                         if (s == (const char*) -1)
151                                 continue;
152
153                         a[i] = strdup(s);
154                         if (!a[i])
155                                 goto fail;
156
157                         i++;
158                 }
159         }
160
161         a[i] = NULL;
162
163         return a;
164
165 fail:
166
167         for (; i > 0; i--)
168                 if (a[i-1])
169                         free(a[i-1]);
170
171         free(a);
172
173         return NULL;
174 }
175
176 char **strv_new(const char *x, ...) {
177         char **r;
178         va_list ap;
179
180         va_start(ap, x);
181         r = strv_new_ap(x, ap);
182         va_end(ap);
183
184         return r;
185 }
186
187 char **strv_merge(char **a, char **b) {
188         char **r, **k;
189
190         if (!a)
191                 return strv_copy(b);
192
193         if (!b)
194                 return strv_copy(a);
195
196         r = new(char*, strv_length(a) + strv_length(b) + 1);
197         if (!r)
198                 return NULL;
199
200         for (k = r; *a; k++, a++) {
201                 *k = strdup(*a);
202                 if (!*k)
203                         goto fail;
204         }
205
206         for (; *b; k++, b++) {
207                 *k = strdup(*b);
208                 if (!*k)
209                         goto fail;
210         }
211
212         *k = NULL;
213         return r;
214
215 fail:
216         strv_free(r);
217         return NULL;
218 }
219
220 char **strv_merge_concat(char **a, char **b, const char *suffix) {
221         char **r, **k;
222
223         /* Like strv_merge(), but appends suffix to all strings in b, before adding */
224
225         if (!b)
226                 return strv_copy(a);
227
228         r = new(char*, strv_length(a) + strv_length(b) + 1);
229         if (!r)
230                 return NULL;
231
232         k = r;
233         if (a)
234                 for (; *a; k++, a++) {
235                         *k = strdup(*a);
236                         if (!*k)
237                                 goto fail;
238                 }
239
240         for (; *b; k++, b++) {
241                 *k = strappend(*b, suffix);
242                 if (!*k)
243                         goto fail;
244         }
245
246         *k = NULL;
247         return r;
248
249 fail:
250         strv_free(r);
251         return NULL;
252
253 }
254
255 char **strv_split(const char *s, const char *separator) {
256         char *state;
257         char *w;
258         size_t l;
259         unsigned n, i;
260         char **r;
261
262         assert(s);
263
264         n = 0;
265         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
266                 n++;
267
268         if (!(r = new(char*, n+1)))
269                 return NULL;
270
271         i = 0;
272         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
273                 if (!(r[i++] = strndup(w, l))) {
274                         strv_free(r);
275                         return NULL;
276                 }
277
278         r[i] = NULL;
279         return r;
280 }
281
282 char **strv_split_quoted(const char *s) {
283         char *state;
284         char *w;
285         size_t l;
286         unsigned n, i;
287         char **r;
288
289         assert(s);
290
291         n = 0;
292         FOREACH_WORD_QUOTED(w, l, s, state)
293                 n++;
294
295         if (!(r = new(char*, n+1)))
296                 return NULL;
297
298         i = 0;
299         FOREACH_WORD_QUOTED(w, l, s, state)
300                 if (!(r[i++] = cunescape_length(w, l))) {
301                         strv_free(r);
302                         return NULL;
303                 }
304
305         r[i] = NULL;
306         return r;
307 }
308
309 char *strv_join(char **l, const char *separator) {
310         char *r, *e;
311         char **s;
312         size_t n, k;
313
314         if (!separator)
315                 separator = " ";
316
317         k = strlen(separator);
318
319         n = 0;
320         STRV_FOREACH(s, l) {
321                 if (n != 0)
322                         n += k;
323                 n += strlen(*s);
324         }
325
326         if (!(r = new(char, n+1)))
327                 return NULL;
328
329         e = r;
330         STRV_FOREACH(s, l) {
331                 if (e != r)
332                         e = stpcpy(e, separator);
333
334                 e = stpcpy(e, *s);
335         }
336
337         *e = 0;
338
339         return r;
340 }
341
342 char **strv_append(char **l, const char *s) {
343         char **r, **k;
344
345         if (!l)
346                 return strv_new(s, NULL);
347
348         if (!s)
349                 return strv_copy(l);
350
351         r = new(char*, strv_length(l)+2);
352         if (!r)
353                 return NULL;
354
355         for (k = r; *l; k++, l++)
356                 if (!(*k = strdup(*l)))
357                         goto fail;
358
359         if (!(*(k++) = strdup(s)))
360                 goto fail;
361
362         *k = NULL;
363         return r;
364
365 fail:
366         for (k--; k >= r; k--)
367                 free(*k);
368
369         free(r);
370
371         return NULL;
372 }
373
374 char **strv_uniq(char **l) {
375         char **i;
376
377         /* Drops duplicate entries. The first identical string will be
378          * kept, the others dropped */
379
380         STRV_FOREACH(i, l)
381                 strv_remove(i+1, *i);
382
383         return l;
384 }
385
386 char **strv_remove(char **l, const char *s) {
387         char **f, **t;
388
389         if (!l)
390                 return NULL;
391
392         assert(s);
393
394         /* Drops every occurrence of s in the string list, edits
395          * in-place. */
396
397         for (f = t = l; *f; f++) {
398
399                 if (streq(*f, s)) {
400                         free(*f);
401                         continue;
402                 }
403
404                 *(t++) = *f;
405         }
406
407         *t = NULL;
408         return l;
409 }
410
411 char **strv_remove_prefix(char **l, const char *s) {
412         char **f, **t;
413
414         if (!l)
415                 return NULL;
416
417         assert(s);
418
419         /* Drops every occurrence of a string prefixed with s in the
420          * string list, edits in-place. */
421
422         for (f = t = l; *f; f++) {
423
424                 if (startswith(*f, s)) {
425                         free(*f);
426                         continue;
427                 }
428
429                 *(t++) = *f;
430         }
431
432         *t = NULL;
433         return l;
434 }
435
436 static int env_append(char **r, char ***k, char **a) {
437         assert(r);
438         assert(k);
439
440         if (!a)
441                 return 0;
442
443         /* Add the entries of a to *k unless they already exist in *r
444          * in which case they are overridden instead. This assumes
445          * there is enough space in the r array. */
446
447         for (; *a; a++) {
448                 char **j;
449                 size_t n;
450
451                 n = strcspn(*a, "=");
452
453                 if ((*a)[n] == '=')
454                         n++;
455
456                 for (j = r; j < *k; j++)
457                         if (strncmp(*j, *a, n) == 0)
458                                 break;
459
460                 if (j >= *k)
461                         (*k)++;
462                 else
463                         free(*j);
464
465                 if (!(*j = strdup(*a)))
466                         return -ENOMEM;
467         }
468
469         return 0;
470 }
471
472 char **strv_env_merge(unsigned n_lists, ...) {
473         size_t n = 0;
474         char **l, **k, **r;
475         va_list ap;
476         unsigned i;
477
478         /* Merges an arbitrary number of environment sets */
479
480         va_start(ap, n_lists);
481         for (i = 0; i < n_lists; i++) {
482                 l = va_arg(ap, char**);
483                 n += strv_length(l);
484         }
485         va_end(ap);
486
487         if (!(r = new(char*, n+1)))
488                 return NULL;
489
490         k = r;
491
492         va_start(ap, n_lists);
493         for (i = 0; i < n_lists; i++) {
494                 l = va_arg(ap, char**);
495                 if (env_append(r, &k, l) < 0)
496                         goto fail;
497         }
498         va_end(ap);
499
500         *k = NULL;
501
502         return r;
503
504 fail:
505         va_end(ap);
506
507         for (k--; k >= r; k--)
508                 free(*k);
509
510         free(r);
511
512         return NULL;
513 }
514
515 static bool env_match(const char *t, const char *pattern) {
516         assert(t);
517         assert(pattern);
518
519         /* pattern a matches string a
520          *         a matches a=
521          *         a matches a=b
522          *         a= matches a=
523          *         a=b matches a=b
524          *         a= does not match a
525          *         a=b does not match a=
526          *         a=b does not match a
527          *         a=b does not match a=c */
528
529         if (streq(t, pattern))
530                 return true;
531
532         if (!strchr(pattern, '=')) {
533                 size_t l = strlen(pattern);
534
535                 return strncmp(t, pattern, l) == 0 && t[l] == '=';
536         }
537
538         return false;
539 }
540
541 char **strv_env_delete(char **x, unsigned n_lists, ...) {
542         size_t n, i = 0;
543         char **k, **r;
544         va_list ap;
545
546         /* Deletes every entry from x that is mentioned in the other
547          * string lists */
548
549         n = strv_length(x);
550
551         r = new(char*, n+1);
552         if (!r)
553                 return NULL;
554
555         STRV_FOREACH(k, x) {
556                 unsigned v;
557
558                 va_start(ap, n_lists);
559                 for (v = 0; v < n_lists; v++) {
560                         char **l, **j;
561
562                         l = va_arg(ap, char**);
563                         STRV_FOREACH(j, l)
564                                 if (env_match(*k, *j))
565                                         goto skip;
566                 }
567                 va_end(ap);
568
569                 r[i] = strdup(*k);
570                 if (!r[i]) {
571                         strv_free(r);
572                         return NULL;
573                 }
574
575                 i++;
576                 continue;
577
578         skip:
579                 va_end(ap);
580         }
581
582         r[i] = NULL;
583
584         assert(i <= n);
585
586         return r;
587 }
588
589 char **strv_env_unset(char **l, const char *p) {
590
591         char **f, **t;
592
593         if (!l)
594                 return NULL;
595
596         assert(p);
597
598         /* Drops every occurrence of the env var setting p in the
599          * string list. edits in-place. */
600
601         for (f = t = l; *f; f++) {
602
603                 if (env_match(*f, p)) {
604                         free(*f);
605                         continue;
606                 }
607
608                 *(t++) = *f;
609         }
610
611         *t = NULL;
612         return l;
613 }
614
615 char **strv_env_set(char **x, const char *p) {
616
617         char **k, **r;
618         char* m[2] = { (char*) p, NULL };
619
620         /* Overrides the env var setting of p, returns a new copy */
621
622         if (!(r = new(char*, strv_length(x)+2)))
623                 return NULL;
624
625         k = r;
626         if (env_append(r, &k, x) < 0)
627                 goto fail;
628
629         if (env_append(r, &k, m) < 0)
630                 goto fail;
631
632         *k = NULL;
633
634         return r;
635
636 fail:
637         for (k--; k >= r; k--)
638                 free(*k);
639
640         free(r);
641
642         return NULL;
643
644 }
645
646 char *strv_env_get_with_length(char **l, const char *name, size_t k) {
647         char **i;
648
649         assert(name);
650
651         STRV_FOREACH(i, l)
652                 if (strncmp(*i, name, k) == 0 &&
653                     (*i)[k] == '=')
654                         return *i + k + 1;
655
656         return NULL;
657 }
658
659 char *strv_env_get(char **l, const char *name) {
660         return strv_env_get_with_length(l, name, strlen(name));
661 }
662
663 char **strv_env_clean(char **l) {
664         char **r, **ret;
665
666         for (r = ret = l; *l; l++) {
667                 const char *equal;
668
669                 equal = strchr(*l, '=');
670
671                 if (equal && equal[1] == 0) {
672                         free(*l);
673                         continue;
674                 }
675
676                 *(r++) = *l;
677         }
678
679         *r = NULL;
680
681         return ret;
682 }
683
684 char **strv_parse_nulstr(const char *s, size_t l) {
685         const char *p;
686         unsigned c = 0, i = 0;
687         char **v;
688
689         assert(s || l <= 0);
690
691         if (l <= 0)
692                 return strv_new(NULL, NULL);
693
694         for (p = s; p < s + l; p++)
695                 if (*p == 0)
696                         c++;
697
698         if (s[l-1] != 0)
699                 c++;
700
701         if (!(v = new0(char*, c+1)))
702                 return NULL;
703
704         p = s;
705         while (p < s + l) {
706                 const char *e;
707
708                 e = memchr(p, 0, s + l - p);
709
710                 if (!(v[i++] = strndup(p, e ? e - p : s + l - p))) {
711                         strv_free(v);
712                         return NULL;
713                 }
714
715                 if (!e)
716                         break;
717
718                 p = e + 1;
719         }
720
721         assert(i == c);
722
723         return v;
724 }
725
726 bool strv_overlap(char **a, char **b) {
727         char **i, **j;
728
729         STRV_FOREACH(i, a) {
730                 STRV_FOREACH(j, b) {
731                         if (streq(*i, *j))
732                                 return true;
733                 }
734         }
735
736         return false;
737 }
738
739 static int str_compare(const void *_a, const void *_b) {
740         const char **a = (const char**) _a, **b = (const char**) _b;
741
742         return strcmp(*a, *b);
743 }
744
745 char **strv_sort(char **l) {
746
747         if (strv_isempty(l))
748                 return l;
749
750         qsort(l, strv_length(l), sizeof(char*), str_compare);
751         return l;
752 }