chiark / gitweb /
python-systemd: rename Journal to Reader
[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 char **strv_parse_nulstr(const char *s, size_t l) {
462         const char *p;
463         unsigned c = 0, i = 0;
464         char **v;
465
466         assert(s || l <= 0);
467
468         if (l <= 0)
469                 return strv_new(NULL, NULL);
470
471         for (p = s; p < s + l; p++)
472                 if (*p == 0)
473                         c++;
474
475         if (s[l-1] != 0)
476                 c++;
477
478         v = new0(char*, c+1);
479         if (!v)
480                 return NULL;
481
482         p = s;
483         while (p < s + l) {
484                 const char *e;
485
486                 e = memchr(p, 0, s + l - p);
487
488                 v[i] = strndup(p, e ? e - p : s + l - p);
489                 if (!v[i]) {
490                         strv_free(v);
491                         return NULL;
492                 }
493
494                 i++;
495
496                 if (!e)
497                         break;
498
499                 p = e + 1;
500         }
501
502         assert(i == c);
503
504         return v;
505 }
506
507 char **strv_split_nulstr(const char *s) {
508         const char *i;
509         char **r = NULL;
510
511         NULSTR_FOREACH(i, s)
512                 if (strv_extend(&r, i) < 0) {
513                         strv_free(r);
514                         return NULL;
515                 }
516
517         if (!r)
518                 return strv_new(NULL, NULL);
519
520         return r;
521 }
522
523 bool strv_overlap(char **a, char **b) {
524         char **i, **j;
525
526         STRV_FOREACH(i, a) {
527                 STRV_FOREACH(j, b) {
528                         if (streq(*i, *j))
529                                 return true;
530                 }
531         }
532
533         return false;
534 }
535
536 static int str_compare(const void *_a, const void *_b) {
537         const char **a = (const char**) _a, **b = (const char**) _b;
538
539         return strcmp(*a, *b);
540 }
541
542 char **strv_sort(char **l) {
543
544         if (strv_isempty(l))
545                 return l;
546
547         qsort(l, strv_length(l), sizeof(char*), str_compare);
548         return l;
549 }
550
551 void strv_print(char **l) {
552         char **s;
553
554         if (!l)
555                 return;
556
557         STRV_FOREACH(s, l)
558                 puts(*s);
559 }