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