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