chiark / gitweb /
Assume that /proc/meminfo can be missing
[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_join_quoted(char **l) {
360         char *buf = NULL;
361         char **s;
362         size_t allocated = 0, len = 0;
363
364         STRV_FOREACH(s, l) {
365                 /* assuming here that escaped string cannot be more
366                  * than twice as long, and reserving space for the
367                  * separator and quotes.
368                  */
369                 _cleanup_free_ char *esc = NULL;
370                 size_t needed;
371
372                 if (!GREEDY_REALLOC(buf, allocated,
373                                     len + strlen(*s) * 2 + 3))
374                         goto oom;
375
376                 esc = cescape(*s);
377                 if (!esc)
378                         goto oom;
379
380                 needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
381                                   len > 0 ? " " : "", esc);
382                 assert(needed < allocated - len);
383                 len += needed;
384         }
385
386         if (!buf)
387                 buf = malloc0(1);
388
389         return buf;
390
391  oom:
392         free(buf);
393         return NULL;
394 }
395
396 char **strv_append(char **l, const char *s) {
397         char **r, **k;
398
399         if (!l)
400                 return strv_new(s, NULL);
401
402         if (!s)
403                 return strv_copy(l);
404
405         r = new(char*, strv_length(l)+2);
406         if (!r)
407                 return NULL;
408
409         for (k = r; *l; k++, l++) {
410                 *k = strdup(*l);
411                 if (!*k)
412                         goto fail;
413         }
414
415         k[0] = strdup(s);
416         if (!k[0])
417                 goto fail;
418
419         k[1] = NULL;
420         return r;
421
422 fail:
423         strv_free(r);
424         return NULL;
425 }
426
427 char **strv_appendf(char **l, const char *format, ...) {
428         va_list ap;
429         _cleanup_free_ char *s = NULL;
430         int r;
431
432         va_start(ap, format);
433         r = vasprintf(&s, format, ap);
434         va_end(ap);
435
436         if (r < 0)
437                 return NULL;
438
439         return strv_append(l, s);
440 }
441
442 int strv_push(char ***l, char *value) {
443         char **c;
444         unsigned n;
445
446         if (!value)
447                 return 0;
448
449         n = strv_length(*l);
450         c = realloc(*l, sizeof(char*) * (n + 2));
451         if (!c)
452                 return -ENOMEM;
453
454         c[n] = value;
455         c[n+1] = NULL;
456
457         *l = c;
458         return 0;
459 }
460
461 int strv_extend(char ***l, const char *value) {
462         char *v;
463         int r;
464
465         if (!value)
466                 return 0;
467
468         v = strdup(value);
469         if (!v)
470                 return -ENOMEM;
471
472         r = strv_push(l, v);
473         if (r < 0)
474                 free(v);
475
476         return r;
477 }
478
479 char **strv_uniq(char **l) {
480         char **i;
481
482         /* Drops duplicate entries. The first identical string will be
483          * kept, the others dropped */
484
485         STRV_FOREACH(i, l)
486                 strv_remove(i+1, *i);
487
488         return l;
489 }
490
491 char **strv_remove(char **l, const char *s) {
492         char **f, **t;
493
494         if (!l)
495                 return NULL;
496
497         assert(s);
498
499         /* Drops every occurrence of s in the string list, edits
500          * in-place. */
501
502         for (f = t = l; *f; f++) {
503
504                 if (streq(*f, s)) {
505                         free(*f);
506                         continue;
507                 }
508
509                 *(t++) = *f;
510         }
511
512         *t = NULL;
513         return l;
514 }
515
516 char **strv_remove_prefix(char **l, const char *s) {
517         char **f, **t;
518
519         if (!l)
520                 return NULL;
521
522         assert(s);
523
524         /* Drops every occurrence of a string prefixed with s in the
525          * string list, edits in-place. */
526
527         for (f = t = l; *f; f++) {
528
529                 if (startswith(*f, s)) {
530                         free(*f);
531                         continue;
532                 }
533
534                 *(t++) = *f;
535         }
536
537         *t = NULL;
538         return l;
539 }
540
541 char **strv_parse_nulstr(const char *s, size_t l) {
542         const char *p;
543         unsigned c = 0, i = 0;
544         char **v;
545
546         assert(s || l <= 0);
547
548         if (l <= 0)
549                 return strv_new(NULL, NULL);
550
551         for (p = s; p < s + l; p++)
552                 if (*p == 0)
553                         c++;
554
555         if (s[l-1] != 0)
556                 c++;
557
558         v = new0(char*, c+1);
559         if (!v)
560                 return NULL;
561
562         p = s;
563         while (p < s + l) {
564                 const char *e;
565
566                 e = memchr(p, 0, s + l - p);
567
568                 v[i] = strndup(p, e ? e - p : s + l - p);
569                 if (!v[i]) {
570                         strv_free(v);
571                         return NULL;
572                 }
573
574                 i++;
575
576                 if (!e)
577                         break;
578
579                 p = e + 1;
580         }
581
582         assert(i == c);
583
584         return v;
585 }
586
587 char **strv_split_nulstr(const char *s) {
588         const char *i;
589         char **r = NULL;
590
591         NULSTR_FOREACH(i, s)
592                 if (strv_extend(&r, i) < 0) {
593                         strv_free(r);
594                         return NULL;
595                 }
596
597         if (!r)
598                 return strv_new(NULL, NULL);
599
600         return r;
601 }
602
603 bool strv_overlap(char **a, char **b) {
604         char **i, **j;
605
606         STRV_FOREACH(i, a) {
607                 STRV_FOREACH(j, b) {
608                         if (streq(*i, *j))
609                                 return true;
610                 }
611         }
612
613         return false;
614 }
615
616 static int str_compare(const void *_a, const void *_b) {
617         const char **a = (const char**) _a, **b = (const char**) _b;
618
619         return strcmp(*a, *b);
620 }
621
622 char **strv_sort(char **l) {
623
624         if (strv_isempty(l))
625                 return l;
626
627         qsort(l, strv_length(l), sizeof(char*), str_compare);
628         return l;
629 }
630
631 void strv_print(char **l) {
632         char **s;
633
634         if (!l)
635                 return;
636
637         STRV_FOREACH(s, l)
638                 puts(*s);
639 }