chiark / gitweb /
strv: handle empty lists in strv_copy() properly
[elogind.git] / src / 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 General Public License as published by
10   the Free Software Foundation; either version 2 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   General Public License for more details.
17
18   You should have received a copy of the GNU 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         if (!(r = new(char*, strv_length(l)+1)))
71                 return NULL;
72
73         if (l)
74                 for (k = r; *l; k++, l++)
75                         if (!(*k = strdup(*l)))
76                                 goto fail;
77
78         *k = NULL;
79         return r;
80
81 fail:
82         for (k--; k >= r; k--)
83                 free(*k);
84
85         free(r);
86
87         return NULL;
88 }
89
90 unsigned strv_length(char **l) {
91         unsigned n = 0;
92
93         if (!l)
94                 return 0;
95
96         for (; *l; l++)
97                 n++;
98
99         return n;
100 }
101
102 char **strv_new_ap(const char *x, va_list ap) {
103         const char *s;
104         char **a;
105         unsigned n = 0, i = 0;
106         va_list aq;
107
108
109         if (x) {
110                 n = 1;
111
112                 va_copy(aq, ap);
113                 while (va_arg(aq, const char*))
114                         n++;
115                 va_end(aq);
116         }
117
118         if (!(a = new(char*, n+1)))
119                 return NULL;
120
121         if (x) {
122                 if (!(a[i] = strdup(x))) {
123                         free(a);
124                         return NULL;
125                 }
126
127                 i++;
128
129                 while ((s = va_arg(ap, const char*))) {
130                         if (!(a[i] = strdup(s)))
131                                 goto fail;
132
133                         i++;
134                 }
135         }
136
137         a[i] = NULL;
138
139         return a;
140
141 fail:
142
143         for (; i > 0; i--)
144                 if (a[i-1])
145                         free(a[i-1]);
146
147         free(a);
148
149         return NULL;
150 }
151
152 char **strv_new(const char *x, ...) {
153         char **r;
154         va_list ap;
155
156         va_start(ap, x);
157         r = strv_new_ap(x, ap);
158         va_end(ap);
159
160         return r;
161 }
162
163 char **strv_merge(char **a, char **b) {
164         char **r, **k;
165
166         if (!a)
167                 return strv_copy(b);
168
169         if (!b)
170                 return strv_copy(a);
171
172         if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
173                 return NULL;
174
175         for (k = r; *a; k++, a++)
176                 if (!(*k = strdup(*a)))
177                         goto fail;
178         for (; *b; k++, b++)
179                 if (!(*k = strdup(*b)))
180                         goto fail;
181
182         *k = NULL;
183         return r;
184
185 fail:
186         for (k--; k >= r; k--)
187                 free(*k);
188
189         free(r);
190
191         return NULL;
192 }
193
194 char **strv_merge_concat(char **a, char **b, const char *suffix) {
195         char **r, **k;
196
197         /* Like strv_merge(), but appends suffix to all strings in b, before adding */
198
199         if (!b)
200                 return strv_copy(a);
201
202         if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
203                 return NULL;
204
205         for (k = r; *a; k++, a++)
206                 if (!(*k = strdup(*a)))
207                         goto fail;
208         for (; *b; k++, b++)
209                 if (!(*k = strappend(*b, suffix)))
210                         goto fail;
211
212         *k = NULL;
213         return r;
214
215 fail:
216         for (k--; k >= r; k--)
217                 free(*k);
218
219         free(r);
220
221         return NULL;
222
223 }
224
225 char **strv_split(const char *s, const char *separator) {
226         char *state;
227         char *w;
228         size_t l;
229         unsigned n, i;
230         char **r;
231
232         assert(s);
233
234         n = 0;
235         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
236                 n++;
237
238         if (!(r = new(char*, n+1)))
239                 return NULL;
240
241         i = 0;
242         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
243                 if (!(r[i++] = strndup(w, l))) {
244                         strv_free(r);
245                         return NULL;
246                 }
247
248         r[i] = NULL;
249         return r;
250 }
251
252 char **strv_split_quoted(const char *s) {
253         char *state;
254         char *w;
255         size_t l;
256         unsigned n, i;
257         char **r;
258
259         assert(s);
260
261         n = 0;
262         FOREACH_WORD_QUOTED(w, l, s, state)
263                 n++;
264
265         if (!(r = new(char*, n+1)))
266                 return NULL;
267
268         i = 0;
269         FOREACH_WORD_QUOTED(w, l, s, state)
270                 if (!(r[i++] = cunescape_length(w, l))) {
271                         strv_free(r);
272                         return NULL;
273                 }
274
275         r[i] = NULL;
276         return r;
277 }
278
279 char *strv_join(char **l, const char *separator) {
280         char *r, *e;
281         char **s;
282         size_t n, k;
283
284         if (!separator)
285                 separator = " ";
286
287         k = strlen(separator);
288
289         n = 0;
290         STRV_FOREACH(s, l) {
291                 if (n != 0)
292                         n += k;
293                 n += strlen(*s);
294         }
295
296         if (!(r = new(char, n+1)))
297                 return NULL;
298
299         e = r;
300         STRV_FOREACH(s, l) {
301                 if (e != r)
302                         e = stpcpy(e, separator);
303
304                 e = stpcpy(e, *s);
305         }
306
307         *e = 0;
308
309         return r;
310 }
311
312 char **strv_append(char **l, const char *s) {
313         char **r, **k;
314
315         if (!l)
316                 return strv_new(s, NULL);
317
318         if (!s)
319                 return strv_copy(l);
320
321         if (!(r = new(char*, strv_length(l)+2)))
322                 return NULL;
323
324         for (k = r; *l; k++, l++)
325                 if (!(*k = strdup(*l)))
326                         goto fail;
327
328         if (!(*(k++) = strdup(s)))
329                 goto fail;
330
331         *k = NULL;
332         return r;
333
334 fail:
335         for (k--; k >= r; k--)
336                 free(*k);
337
338         free(r);
339
340         return NULL;
341 }
342
343 char **strv_uniq(char **l) {
344         char **i;
345
346         /* Drops duplicate entries. The first identical string will be
347          * kept, the others dropped */
348
349         STRV_FOREACH(i, l)
350                 strv_remove(i+1, *i);
351
352         return l;
353 }
354
355 char **strv_remove(char **l, const char *s) {
356         char **f, **t;
357
358         if (!l)
359                 return NULL;
360
361         /* Drops every occurrence of s in the string list */
362
363         for (f = t = l; *f; f++) {
364
365                 if (streq(*f, s)) {
366                         free(*f);
367                         continue;
368                 }
369
370                 *(t++) = *f;
371         }
372
373         *t = NULL;
374         return l;
375 }
376
377 static int env_append(char **r, char ***k, char **a) {
378         assert(r);
379         assert(k);
380
381         if (!a)
382                 return 0;
383
384         /* Add the entries of a to *k unless they already exist in *r
385          * in which case they are overridden instead. This assumes
386          * there is enough space in the r array. */
387
388         for (; *a; a++) {
389                 char **j;
390                 size_t n = strcspn(*a, "=") + 1;
391
392                 for (j = r; j < *k; j++)
393                         if (strncmp(*j, *a, n) == 0)
394                                 break;
395
396                 if (j >= *k)
397                         (*k)++;
398                 else
399                         free(*j);
400
401                 if (!(*j = strdup(*a)))
402                         return -ENOMEM;
403         }
404
405         return 0;
406 }
407
408 char **strv_env_merge(unsigned n_lists, ...) {
409         size_t n = 0;
410         char **l, **k, **r;
411         va_list ap;
412         unsigned i;
413
414         /* Merges an arbitrary number of environment sets */
415
416         va_start(ap, n_lists);
417         for (i = 0; i < n_lists; i++) {
418                 l = va_arg(ap, char**);
419                 n += strv_length(l);
420         }
421         va_end(ap);
422
423         if (!(r = new(char*, n+1)))
424                 return NULL;
425
426         k = r;
427
428         va_start(ap, n_lists);
429         for (i = 0; i < n_lists; i++) {
430                 l = va_arg(ap, char**);
431                 if (env_append(r, &k, l) < 0)
432                         goto fail;
433         }
434         va_end(ap);
435
436         *k = NULL;
437
438         return r;
439
440 fail:
441         va_end(ap);
442
443         for (k--; k >= r; k--)
444                 free(*k);
445
446         free(r);
447
448         return NULL;
449 }
450
451 static bool env_match(const char *t, const char *pattern) {
452         assert(t);
453         assert(pattern);
454
455         /* pattern a matches string a
456          *         a matches a=
457          *         a matches a=b
458          *         a= matches a=
459          *         a=b matches a=b
460          *         a= does not match a
461          *         a=b does not match a=
462          *         a=b does not match a
463          *         a=b does not match a=c */
464
465         if (streq(t, pattern))
466                 return true;
467
468         if (!strchr(pattern, '=')) {
469                 size_t l = strlen(pattern);
470
471                 return strncmp(t, pattern, l) == 0 && t[l] == '=';
472         }
473
474         return false;
475 }
476
477 char **strv_env_delete(char **x, unsigned n_lists, ...) {
478         size_t n = 0, i = 0;
479         char **l, **k, **r, **j;
480         va_list ap;
481
482         /* Deletes every entry from x that is mentioned in the other
483          * string lists */
484
485         n = strv_length(x);
486
487         if (!(r = new(char*, n+1)))
488                 return NULL;
489
490         STRV_FOREACH(k, x) {
491                 va_start(ap, n_lists);
492
493                 for (i = 0; i < n_lists; i++) {
494                         l = va_arg(ap, char**);
495                         STRV_FOREACH(j, l)
496                                 if (env_match(*k, *j))
497                                         goto delete;
498                 }
499
500                 va_end(ap);
501
502                 if (!(r[i++] = strdup(*k))) {
503                         strv_free(r);
504                         return NULL;
505                 }
506
507                 continue;
508
509         delete:
510                 va_end(ap);
511         }
512
513         r[i] = NULL;
514
515         assert(i <= n);
516
517         return r;
518 }
519
520 char **strv_env_set(char **x, const char *p) {
521
522         char **k, **r;
523
524         if (!(r = new(char*, strv_length(x)+2)))
525                 return NULL;
526
527         k = r;
528         if (env_append(r, &k, x) < 0)
529                 goto fail;
530
531         if (!(*(k++) = strdup(p)))
532                 goto fail;
533
534         *k = NULL;
535
536         return r;
537
538 fail:
539         for (k--; k >= r; k--)
540                 free(*k);
541
542         free(r);
543
544         return NULL;
545
546 }
547
548 char *strv_env_get_with_length(char **l, const char *name, size_t k) {
549         char **i;
550
551         assert(name);
552
553         STRV_FOREACH(i, l)
554                 if (strncmp(*i, name, k) == 0 &&
555                     (*i)[k] == '=')
556                         return *i + k + 1;
557
558         return NULL;
559 }
560
561 char *strv_env_get(char **l, const char *name) {
562         return strv_env_get_with_length(l, name, strlen(name));
563 }
564
565 char **strv_env_clean(char **l) {
566         char **r, **ret;
567
568         for (r = ret = l; *l; l++) {
569                 const char *equal;
570
571                 equal = strchr(*l, '=');
572
573                 if (equal && equal[1] == 0) {
574                         free(*l);
575                         continue;
576                 }
577
578                 *(r++) = *l;
579         }
580
581         *r = NULL;
582
583         return ret;
584 }
585
586 char **strv_parse_nulstr(const char *s, size_t l) {
587         const char *p;
588         unsigned c = 0, i = 0;
589         char **v;
590
591         assert(s || l <= 0);
592
593         if (l <= 0)
594                 return strv_new(NULL, NULL);
595
596         for (p = s; p < s + l; p++)
597                 if (*p == 0)
598                         c++;
599
600         if (s[l-1] != 0)
601                 c++;
602
603         if (!(v = new0(char*, c+1)))
604                 return NULL;
605
606         p = s;
607         while (p < s + l) {
608                 const char *e;
609
610                 e = memchr(p, 0, s + l - p);
611
612                 if (!(v[i++] = strndup(p, e ? e - p : s + l - p))) {
613                         strv_free(v);
614                         return NULL;
615                 }
616
617                 if (!e)
618                         break;
619
620                 p = e + 1;
621         }
622
623         assert(i == c);
624
625         return v;
626 }