chiark / gitweb /
bus: reuse more code
[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 **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 **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_extend(char ***l, const char *value) {
391         char **c;
392         char *v;
393         unsigned n;
394
395         if (!value)
396                 return 0;
397
398         v = strdup(value);
399         if (!v)
400                 return -ENOMEM;
401
402         n = strv_length(*l);
403         c = realloc(*l, sizeof(char*) * (n + 2));
404         if (!c) {
405                 free(v);
406                 return -ENOMEM;
407         }
408
409         c[n] = v;
410         c[n+1] = NULL;
411
412         *l = c;
413         return 0;
414 }
415
416 char **strv_uniq(char **l) {
417         char **i;
418
419         /* Drops duplicate entries. The first identical string will be
420          * kept, the others dropped */
421
422         STRV_FOREACH(i, l)
423                 strv_remove(i+1, *i);
424
425         return l;
426 }
427
428 char **strv_remove(char **l, const char *s) {
429         char **f, **t;
430
431         if (!l)
432                 return NULL;
433
434         assert(s);
435
436         /* Drops every occurrence of s in the string list, edits
437          * in-place. */
438
439         for (f = t = l; *f; f++) {
440
441                 if (streq(*f, s)) {
442                         free(*f);
443                         continue;
444                 }
445
446                 *(t++) = *f;
447         }
448
449         *t = NULL;
450         return l;
451 }
452
453 char **strv_remove_prefix(char **l, const char *s) {
454         char **f, **t;
455
456         if (!l)
457                 return NULL;
458
459         assert(s);
460
461         /* Drops every occurrence of a string prefixed with s in the
462          * string list, edits in-place. */
463
464         for (f = t = l; *f; f++) {
465
466                 if (startswith(*f, s)) {
467                         free(*f);
468                         continue;
469                 }
470
471                 *(t++) = *f;
472         }
473
474         *t = NULL;
475         return l;
476 }
477
478 char **strv_parse_nulstr(const char *s, size_t l) {
479         const char *p;
480         unsigned c = 0, i = 0;
481         char **v;
482
483         assert(s || l <= 0);
484
485         if (l <= 0)
486                 return strv_new(NULL, NULL);
487
488         for (p = s; p < s + l; p++)
489                 if (*p == 0)
490                         c++;
491
492         if (s[l-1] != 0)
493                 c++;
494
495         v = new0(char*, c+1);
496         if (!v)
497                 return NULL;
498
499         p = s;
500         while (p < s + l) {
501                 const char *e;
502
503                 e = memchr(p, 0, s + l - p);
504
505                 v[i] = strndup(p, e ? e - p : s + l - p);
506                 if (!v[i]) {
507                         strv_free(v);
508                         return NULL;
509                 }
510
511                 i++;
512
513                 if (!e)
514                         break;
515
516                 p = e + 1;
517         }
518
519         assert(i == c);
520
521         return v;
522 }
523
524 char **strv_split_nulstr(const char *s) {
525         const char *i;
526         char **r = NULL;
527
528         NULSTR_FOREACH(i, s)
529                 if (strv_extend(&r, i) < 0) {
530                         strv_free(r);
531                         return NULL;
532                 }
533
534         if (!r)
535                 return strv_new(NULL, NULL);
536
537         return r;
538 }
539
540 bool strv_overlap(char **a, char **b) {
541         char **i, **j;
542
543         STRV_FOREACH(i, a) {
544                 STRV_FOREACH(j, b) {
545                         if (streq(*i, *j))
546                                 return true;
547                 }
548         }
549
550         return false;
551 }
552
553 static int str_compare(const void *_a, const void *_b) {
554         const char **a = (const char**) _a, **b = (const char**) _b;
555
556         return strcmp(*a, *b);
557 }
558
559 char **strv_sort(char **l) {
560
561         if (strv_isempty(l))
562                 return l;
563
564         qsort(l, strv_length(l), sizeof(char*), str_compare);
565         return l;
566 }
567
568 void strv_print(char **l) {
569         char **s;
570
571         if (!l)
572                 return;
573
574         STRV_FOREACH(s, l)
575                 puts(*s);
576 }