chiark / gitweb /
pager: add K to less environment
[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_split_newlines(const char *s) {
309         char **l;
310         unsigned n;
311
312         assert(s);
313
314         /* Special version of strv_split() that splits on newlines and
315          * suppresses an empty string at the end */
316
317         l = strv_split(s, NEWLINE);
318         if (!l)
319                 return NULL;
320
321         n = strv_length(l);
322         if (n <= 0)
323                 return l;
324
325         if (isempty(l[n-1])) {
326                 free(l[n-1]);
327                 l[n-1] = NULL;
328         }
329
330         return l;
331 }
332
333 char *strv_join(char **l, const char *separator) {
334         char *r, *e;
335         char **s;
336         size_t n, k;
337
338         if (!separator)
339                 separator = " ";
340
341         k = strlen(separator);
342
343         n = 0;
344         STRV_FOREACH(s, l) {
345                 if (n != 0)
346                         n += k;
347                 n += strlen(*s);
348         }
349
350         r = new(char, n+1);
351         if (!r)
352                 return NULL;
353
354         e = r;
355         STRV_FOREACH(s, l) {
356                 if (e != r)
357                         e = stpcpy(e, separator);
358
359                 e = stpcpy(e, *s);
360         }
361
362         *e = 0;
363
364         return r;
365 }
366
367 char **strv_append(char **l, const char *s) {
368         char **r, **k;
369
370         if (!l)
371                 return strv_new(s, NULL);
372
373         if (!s)
374                 return strv_copy(l);
375
376         r = new(char*, strv_length(l)+2);
377         if (!r)
378                 return NULL;
379
380         for (k = r; *l; k++, l++) {
381                 *k = strdup(*l);
382                 if (!*k)
383                         goto fail;
384         }
385
386         k[0] = strdup(s);
387         if (!k[0])
388                 goto fail;
389
390         k[1] = NULL;
391         return r;
392
393 fail:
394         strv_free(r);
395         return NULL;
396 }
397
398 int strv_extend(char ***l, const char *value) {
399         char **c;
400         char *v;
401         unsigned n;
402
403         if (!value)
404                 return 0;
405
406         v = strdup(value);
407         if (!v)
408                 return -ENOMEM;
409
410         n = strv_length(*l);
411         c = realloc(*l, sizeof(char*) * (n + 2));
412         if (!c) {
413                 free(v);
414                 return -ENOMEM;
415         }
416
417         c[n] = v;
418         c[n+1] = NULL;
419
420         *l = c;
421         return 0;
422 }
423
424 char **strv_uniq(char **l) {
425         char **i;
426
427         /* Drops duplicate entries. The first identical string will be
428          * kept, the others dropped */
429
430         STRV_FOREACH(i, l)
431                 strv_remove(i+1, *i);
432
433         return l;
434 }
435
436 char **strv_remove(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 s in the string list, edits
445          * in-place. */
446
447         for (f = t = l; *f; f++) {
448
449                 if (streq(*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_remove_prefix(char **l, const char *s) {
462         char **f, **t;
463
464         if (!l)
465                 return NULL;
466
467         assert(s);
468
469         /* Drops every occurrence of a string prefixed with s in the
470          * string list, edits in-place. */
471
472         for (f = t = l; *f; f++) {
473
474                 if (startswith(*f, s)) {
475                         free(*f);
476                         continue;
477                 }
478
479                 *(t++) = *f;
480         }
481
482         *t = NULL;
483         return l;
484 }
485
486 char **strv_parse_nulstr(const char *s, size_t l) {
487         const char *p;
488         unsigned c = 0, i = 0;
489         char **v;
490
491         assert(s || l <= 0);
492
493         if (l <= 0)
494                 return strv_new(NULL, NULL);
495
496         for (p = s; p < s + l; p++)
497                 if (*p == 0)
498                         c++;
499
500         if (s[l-1] != 0)
501                 c++;
502
503         v = new0(char*, c+1);
504         if (!v)
505                 return NULL;
506
507         p = s;
508         while (p < s + l) {
509                 const char *e;
510
511                 e = memchr(p, 0, s + l - p);
512
513                 v[i] = strndup(p, e ? e - p : s + l - p);
514                 if (!v[i]) {
515                         strv_free(v);
516                         return NULL;
517                 }
518
519                 i++;
520
521                 if (!e)
522                         break;
523
524                 p = e + 1;
525         }
526
527         assert(i == c);
528
529         return v;
530 }
531
532 char **strv_split_nulstr(const char *s) {
533         const char *i;
534         char **r = NULL;
535
536         NULSTR_FOREACH(i, s)
537                 if (strv_extend(&r, i) < 0) {
538                         strv_free(r);
539                         return NULL;
540                 }
541
542         if (!r)
543                 return strv_new(NULL, NULL);
544
545         return r;
546 }
547
548 bool strv_overlap(char **a, char **b) {
549         char **i, **j;
550
551         STRV_FOREACH(i, a) {
552                 STRV_FOREACH(j, b) {
553                         if (streq(*i, *j))
554                                 return true;
555                 }
556         }
557
558         return false;
559 }
560
561 static int str_compare(const void *_a, const void *_b) {
562         const char **a = (const char**) _a, **b = (const char**) _b;
563
564         return strcmp(*a, *b);
565 }
566
567 char **strv_sort(char **l) {
568
569         if (strv_isempty(l))
570                 return l;
571
572         qsort(l, strv_length(l), sizeof(char*), str_compare);
573         return l;
574 }
575
576 void strv_print(char **l) {
577         char **s;
578
579         if (!l)
580                 return;
581
582         STRV_FOREACH(s, l)
583                 puts(*s);
584 }