chiark / gitweb /
update TODO
[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 char **strv_uniq(char **l) {
374         char **i;
375
376         /* Drops duplicate entries. The first identical string will be
377          * kept, the others dropped */
378
379         STRV_FOREACH(i, l)
380                 strv_remove(i+1, *i);
381
382         return l;
383 }
384
385 char **strv_remove(char **l, const char *s) {
386         char **f, **t;
387
388         if (!l)
389                 return NULL;
390
391         assert(s);
392
393         /* Drops every occurrence of s in the string list, edits
394          * in-place. */
395
396         for (f = t = l; *f; f++) {
397
398                 if (streq(*f, s)) {
399                         free(*f);
400                         continue;
401                 }
402
403                 *(t++) = *f;
404         }
405
406         *t = NULL;
407         return l;
408 }
409
410 char **strv_remove_prefix(char **l, const char *s) {
411         char **f, **t;
412
413         if (!l)
414                 return NULL;
415
416         assert(s);
417
418         /* Drops every occurrence of a string prefixed with s in the
419          * string list, edits in-place. */
420
421         for (f = t = l; *f; f++) {
422
423                 if (startswith(*f, s)) {
424                         free(*f);
425                         continue;
426                 }
427
428                 *(t++) = *f;
429         }
430
431         *t = NULL;
432         return l;
433 }
434
435 static int env_append(char **r, char ***k, char **a) {
436         assert(r);
437         assert(k);
438
439         if (!a)
440                 return 0;
441
442         /* Add the entries of a to *k unless they already exist in *r
443          * in which case they are overridden instead. This assumes
444          * there is enough space in the r array. */
445
446         for (; *a; a++) {
447                 char **j;
448                 size_t n;
449
450                 n = strcspn(*a, "=");
451
452                 if ((*a)[n] == '=')
453                         n++;
454
455                 for (j = r; j < *k; j++)
456                         if (strncmp(*j, *a, n) == 0)
457                                 break;
458
459                 if (j >= *k)
460                         (*k)++;
461                 else
462                         free(*j);
463
464                 *j = strdup(*a);
465                 if (!*j)
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         r = new(char*, n+1);
488         if (!r)
489                 return NULL;
490
491         k = r;
492
493         va_start(ap, n_lists);
494         for (i = 0; i < n_lists; i++) {
495                 l = va_arg(ap, char**);
496                 if (env_append(r, &k, l) < 0)
497                         goto fail;
498         }
499         va_end(ap);
500
501         *k = NULL;
502
503         return r;
504
505 fail:
506         va_end(ap);
507         strv_free(r);
508
509         return NULL;
510 }
511
512 static bool env_match(const char *t, const char *pattern) {
513         assert(t);
514         assert(pattern);
515
516         /* pattern a matches string a
517          *         a matches a=
518          *         a matches a=b
519          *         a= matches a=
520          *         a=b matches a=b
521          *         a= does not match a
522          *         a=b does not match a=
523          *         a=b does not match a
524          *         a=b does not match a=c */
525
526         if (streq(t, pattern))
527                 return true;
528
529         if (!strchr(pattern, '=')) {
530                 size_t l = strlen(pattern);
531
532                 return strncmp(t, pattern, l) == 0 && t[l] == '=';
533         }
534
535         return false;
536 }
537
538 char **strv_env_delete(char **x, unsigned n_lists, ...) {
539         size_t n, i = 0;
540         char **k, **r;
541         va_list ap;
542
543         /* Deletes every entry from x that is mentioned in the other
544          * string lists */
545
546         n = strv_length(x);
547
548         r = new(char*, n+1);
549         if (!r)
550                 return NULL;
551
552         STRV_FOREACH(k, x) {
553                 unsigned v;
554
555                 va_start(ap, n_lists);
556                 for (v = 0; v < n_lists; v++) {
557                         char **l, **j;
558
559                         l = va_arg(ap, char**);
560                         STRV_FOREACH(j, l)
561                                 if (env_match(*k, *j))
562                                         goto skip;
563                 }
564                 va_end(ap);
565
566                 r[i] = strdup(*k);
567                 if (!r[i]) {
568                         strv_free(r);
569                         return NULL;
570                 }
571
572                 i++;
573                 continue;
574
575         skip:
576                 va_end(ap);
577         }
578
579         r[i] = NULL;
580
581         assert(i <= n);
582
583         return r;
584 }
585
586 char **strv_env_unset(char **l, const char *p) {
587
588         char **f, **t;
589
590         if (!l)
591                 return NULL;
592
593         assert(p);
594
595         /* Drops every occurrence of the env var setting p in the
596          * string list. edits in-place. */
597
598         for (f = t = l; *f; f++) {
599
600                 if (env_match(*f, p)) {
601                         free(*f);
602                         continue;
603                 }
604
605                 *(t++) = *f;
606         }
607
608         *t = NULL;
609         return l;
610 }
611
612 char **strv_env_set(char **x, const char *p) {
613
614         char **k, **r;
615         char* m[2] = { (char*) p, NULL };
616
617         /* Overrides the env var setting of p, returns a new copy */
618
619         r = new(char*, strv_length(x)+2);
620         if (!r)
621                 return NULL;
622
623         k = r;
624         if (env_append(r, &k, x) < 0)
625                 goto fail;
626
627         if (env_append(r, &k, m) < 0)
628                 goto fail;
629
630         *k = NULL;
631
632         return r;
633
634 fail:
635         strv_free(r);
636         return NULL;
637
638 }
639
640 char *strv_env_get_with_length(char **l, const char *name, size_t k) {
641         char **i;
642
643         assert(name);
644
645         STRV_FOREACH(i, l)
646                 if (strncmp(*i, name, k) == 0 &&
647                     (*i)[k] == '=')
648                         return *i + k + 1;
649
650         return NULL;
651 }
652
653 char *strv_env_get(char **l, const char *name) {
654         return strv_env_get_with_length(l, name, strlen(name));
655 }
656
657 char **strv_env_clean(char **l) {
658         char **r, **ret;
659
660         for (r = ret = l; *l; l++) {
661                 const char *equal;
662
663                 equal = strchr(*l, '=');
664
665                 if (equal && equal[1] == 0) {
666                         free(*l);
667                         continue;
668                 }
669
670                 *(r++) = *l;
671         }
672
673         *r = NULL;
674
675         return ret;
676 }
677
678 char **strv_parse_nulstr(const char *s, size_t l) {
679         const char *p;
680         unsigned c = 0, i = 0;
681         char **v;
682
683         assert(s || l <= 0);
684
685         if (l <= 0)
686                 return strv_new(NULL, NULL);
687
688         for (p = s; p < s + l; p++)
689                 if (*p == 0)
690                         c++;
691
692         if (s[l-1] != 0)
693                 c++;
694
695         v = new0(char*, c+1);
696         if (!v)
697                 return NULL;
698
699         p = s;
700         while (p < s + l) {
701                 const char *e;
702
703                 e = memchr(p, 0, s + l - p);
704
705                 v[i] = strndup(p, e ? e - p : s + l - p);
706                 if (!v[i]) {
707                         strv_free(v);
708                         return NULL;
709                 }
710
711                 i++;
712
713                 if (!e)
714                         break;
715
716                 p = e + 1;
717         }
718
719         assert(i == c);
720
721         return v;
722 }
723
724 bool strv_overlap(char **a, char **b) {
725         char **i, **j;
726
727         STRV_FOREACH(i, a) {
728                 STRV_FOREACH(j, b) {
729                         if (streq(*i, *j))
730                                 return true;
731                 }
732         }
733
734         return false;
735 }
736
737 static int str_compare(const void *_a, const void *_b) {
738         const char **a = (const char**) _a, **b = (const char**) _b;
739
740         return strcmp(*a, *b);
741 }
742
743 char **strv_sort(char **l) {
744
745         if (strv_isempty(l))
746                 return l;
747
748         qsort(l, strv_length(l), sizeof(char*), str_compare);
749         return l;
750 }