chiark / gitweb /
Do no isolate in case of emergency or severe problems
[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 char **strv_copy(char * const *l) {
68         char **r, **k;
69
70         k = r = new(char*, strv_length(l) + 1);
71         if (!r)
72                 return NULL;
73
74         if (l)
75                 for (; *l; k++, l++) {
76                         *k = strdup(*l);
77                         if (!*k) {
78                                 strv_free(r);
79                                 return NULL;
80                         }
81                 }
82
83         *k = NULL;
84         return r;
85 }
86
87 unsigned strv_length(char * const *l) {
88         unsigned n = 0;
89
90         if (!l)
91                 return 0;
92
93         for (; *l; l++)
94                 n++;
95
96         return n;
97 }
98
99 char **strv_new_ap(const char *x, va_list ap) {
100         const char *s;
101         char **a;
102         unsigned n = 0, i = 0;
103         va_list aq;
104
105         /* As a special trick we ignore all listed strings that equal
106          * (const char*) -1. This is supposed to be used with the
107          * STRV_IFNOTNULL() macro to include possibly NULL strings in
108          * the string list. */
109
110         if (x) {
111                 n = x == (const char*) -1 ? 0 : 1;
112
113                 va_copy(aq, ap);
114                 while ((s = va_arg(aq, const char*))) {
115                         if (s == (const char*) -1)
116                                 continue;
117
118                         n++;
119                 }
120
121                 va_end(aq);
122         }
123
124         a = new(char*, n+1);
125         if (!a)
126                 return NULL;
127
128         if (x) {
129                 if (x != (const char*) -1) {
130                         a[i] = strdup(x);
131                         if (!a[i])
132                                 goto fail;
133                         i++;
134                 }
135
136                 while ((s = va_arg(ap, const char*))) {
137
138                         if (s == (const char*) -1)
139                                 continue;
140
141                         a[i] = strdup(s);
142                         if (!a[i])
143                                 goto fail;
144
145                         i++;
146                 }
147         }
148
149         a[i] = NULL;
150
151         return a;
152
153 fail:
154         strv_free(a);
155         return NULL;
156 }
157
158 char **strv_new(const char *x, ...) {
159         char **r;
160         va_list ap;
161
162         va_start(ap, x);
163         r = strv_new_ap(x, ap);
164         va_end(ap);
165
166         return r;
167 }
168
169 char **strv_merge(char **a, char **b) {
170         char **r, **k;
171
172         if (!a)
173                 return strv_copy(b);
174
175         if (!b)
176                 return strv_copy(a);
177
178         r = new(char*, strv_length(a) + strv_length(b) + 1);
179         if (!r)
180                 return NULL;
181
182         for (k = r; *a; k++, a++) {
183                 *k = strdup(*a);
184                 if (!*k)
185                         goto fail;
186         }
187
188         for (; *b; k++, b++) {
189                 *k = strdup(*b);
190                 if (!*k)
191                         goto fail;
192         }
193
194         *k = NULL;
195         return r;
196
197 fail:
198         strv_free(r);
199         return NULL;
200 }
201
202 char **strv_merge_concat(char **a, char **b, const char *suffix) {
203         char **r, **k;
204
205         /* Like strv_merge(), but appends suffix to all strings in b, before adding */
206
207         if (!b)
208                 return strv_copy(a);
209
210         r = new(char*, strv_length(a) + strv_length(b) + 1);
211         if (!r)
212                 return NULL;
213
214         k = r;
215         if (a)
216                 for (; *a; k++, a++) {
217                         *k = strdup(*a);
218                         if (!*k)
219                                 goto fail;
220                 }
221
222         for (; *b; k++, b++) {
223                 *k = strappend(*b, suffix);
224                 if (!*k)
225                         goto fail;
226         }
227
228         *k = NULL;
229         return r;
230
231 fail:
232         strv_free(r);
233         return NULL;
234
235 }
236
237 char **strv_split(const char *s, const char *separator) {
238         char *state;
239         char *w;
240         size_t l;
241         unsigned n, i;
242         char **r;
243
244         assert(s);
245
246         n = 0;
247         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
248                 n++;
249
250         r = new(char*, n+1);
251         if (!r)
252                 return NULL;
253
254         i = 0;
255         FOREACH_WORD_SEPARATOR(w, l, s, separator, state) {
256                 r[i] = strndup(w, l);
257                 if (!r[i]) {
258                         strv_free(r);
259                         return NULL;
260                 }
261
262                 i++;
263         }
264
265         r[i] = NULL;
266         return r;
267 }
268
269 char **strv_split_quoted(const char *s) {
270         char *state;
271         char *w;
272         size_t l;
273         unsigned n, i;
274         char **r;
275
276         assert(s);
277
278         n = 0;
279         FOREACH_WORD_QUOTED(w, l, s, state)
280                 n++;
281
282         r = new(char*, n+1);
283         if (!r)
284                 return NULL;
285
286         i = 0;
287         FOREACH_WORD_QUOTED(w, l, s, state) {
288                 r[i] = cunescape_length(w, l);
289                 if (!r[i]) {
290                         strv_free(r);
291                         return NULL;
292                 }
293                 i++;
294         }
295
296         r[i] = NULL;
297         return r;
298 }
299
300 char **strv_split_newlines(const char *s) {
301         char **l;
302         unsigned n;
303
304         assert(s);
305
306         /* Special version of strv_split() that splits on newlines and
307          * suppresses an empty string at the end */
308
309         l = strv_split(s, NEWLINE);
310         if (!l)
311                 return NULL;
312
313         n = strv_length(l);
314         if (n <= 0)
315                 return l;
316
317         if (isempty(l[n-1])) {
318                 free(l[n-1]);
319                 l[n-1] = NULL;
320         }
321
322         return l;
323 }
324
325 char *strv_join(char **l, const char *separator) {
326         char *r, *e;
327         char **s;
328         size_t n, k;
329
330         if (!separator)
331                 separator = " ";
332
333         k = strlen(separator);
334
335         n = 0;
336         STRV_FOREACH(s, l) {
337                 if (n != 0)
338                         n += k;
339                 n += strlen(*s);
340         }
341
342         r = new(char, n+1);
343         if (!r)
344                 return NULL;
345
346         e = r;
347         STRV_FOREACH(s, l) {
348                 if (e != r)
349                         e = stpcpy(e, separator);
350
351                 e = stpcpy(e, *s);
352         }
353
354         *e = 0;
355
356         return r;
357 }
358
359 char **strv_append(char **l, const char *s) {
360         char **r, **k;
361
362         if (!l)
363                 return strv_new(s, NULL);
364
365         if (!s)
366                 return strv_copy(l);
367
368         r = new(char*, strv_length(l)+2);
369         if (!r)
370                 return NULL;
371
372         for (k = r; *l; k++, l++) {
373                 *k = strdup(*l);
374                 if (!*k)
375                         goto fail;
376         }
377
378         k[0] = strdup(s);
379         if (!k[0])
380                 goto fail;
381
382         k[1] = NULL;
383         return r;
384
385 fail:
386         strv_free(r);
387         return NULL;
388 }
389
390 int strv_push(char ***l, char *value) {
391         char **c;
392         unsigned n;
393
394         if (!value)
395                 return 0;
396
397         n = strv_length(*l);
398         c = realloc(*l, sizeof(char*) * (n + 2));
399         if (!c)
400                 return -ENOMEM;
401
402         c[n] = value;
403         c[n+1] = NULL;
404
405         *l = c;
406         return 0;
407 }
408
409 int strv_extend(char ***l, const char *value) {
410         char *v;
411         int r;
412
413         if (!value)
414                 return 0;
415
416         v = strdup(value);
417         if (!v)
418                 return -ENOMEM;
419
420         r = strv_push(l, v);
421         if (r < 0)
422                 free(v);
423
424         return r;
425 }
426
427 char **strv_uniq(char **l) {
428         char **i;
429
430         /* Drops duplicate entries. The first identical string will be
431          * kept, the others dropped */
432
433         STRV_FOREACH(i, l)
434                 strv_remove(i+1, *i);
435
436         return l;
437 }
438
439 char **strv_remove(char **l, const char *s) {
440         char **f, **t;
441
442         if (!l)
443                 return NULL;
444
445         assert(s);
446
447         /* Drops every occurrence of s in the string list, edits
448          * in-place. */
449
450         for (f = t = l; *f; f++) {
451
452                 if (streq(*f, s)) {
453                         free(*f);
454                         continue;
455                 }
456
457                 *(t++) = *f;
458         }
459
460         *t = NULL;
461         return l;
462 }
463
464 char **strv_remove_prefix(char **l, const char *s) {
465         char **f, **t;
466
467         if (!l)
468                 return NULL;
469
470         assert(s);
471
472         /* Drops every occurrence of a string prefixed with s in the
473          * string list, edits in-place. */
474
475         for (f = t = l; *f; f++) {
476
477                 if (startswith(*f, s)) {
478                         free(*f);
479                         continue;
480                 }
481
482                 *(t++) = *f;
483         }
484
485         *t = NULL;
486         return l;
487 }
488
489 char **strv_parse_nulstr(const char *s, size_t l) {
490         const char *p;
491         unsigned c = 0, i = 0;
492         char **v;
493
494         assert(s || l <= 0);
495
496         if (l <= 0)
497                 return strv_new(NULL, NULL);
498
499         for (p = s; p < s + l; p++)
500                 if (*p == 0)
501                         c++;
502
503         if (s[l-1] != 0)
504                 c++;
505
506         v = new0(char*, c+1);
507         if (!v)
508                 return NULL;
509
510         p = s;
511         while (p < s + l) {
512                 const char *e;
513
514                 e = memchr(p, 0, s + l - p);
515
516                 v[i] = strndup(p, e ? e - p : s + l - p);
517                 if (!v[i]) {
518                         strv_free(v);
519                         return NULL;
520                 }
521
522                 i++;
523
524                 if (!e)
525                         break;
526
527                 p = e + 1;
528         }
529
530         assert(i == c);
531
532         return v;
533 }
534
535 char **strv_split_nulstr(const char *s) {
536         const char *i;
537         char **r = NULL;
538
539         NULSTR_FOREACH(i, s)
540                 if (strv_extend(&r, i) < 0) {
541                         strv_free(r);
542                         return NULL;
543                 }
544
545         if (!r)
546                 return strv_new(NULL, NULL);
547
548         return r;
549 }
550
551 bool strv_overlap(char **a, char **b) {
552         char **i, **j;
553
554         STRV_FOREACH(i, a) {
555                 STRV_FOREACH(j, b) {
556                         if (streq(*i, *j))
557                                 return true;
558                 }
559         }
560
561         return false;
562 }
563
564 static int str_compare(const void *_a, const void *_b) {
565         const char **a = (const char**) _a, **b = (const char**) _b;
566
567         return strcmp(*a, *b);
568 }
569
570 char **strv_sort(char **l) {
571
572         if (strv_isempty(l))
573                 return l;
574
575         qsort(l, strv_length(l), sizeof(char*), str_compare);
576         return l;
577 }
578
579 void strv_print(char **l) {
580         char **s;
581
582         if (!l)
583                 return;
584
585         STRV_FOREACH(s, l)
586                 puts(*s);
587 }