chiark / gitweb /
units: wording fix
[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         assert(s);
362
363         /* Drops every occurrence of s in the string list, edits
364          * in-place. */
365
366         for (f = t = l; *f; f++) {
367
368                 if (streq(*f, s)) {
369                         free(*f);
370                         continue;
371                 }
372
373                 *(t++) = *f;
374         }
375
376         *t = NULL;
377         return l;
378 }
379
380 static int env_append(char **r, char ***k, char **a) {
381         assert(r);
382         assert(k);
383
384         if (!a)
385                 return 0;
386
387         /* Add the entries of a to *k unless they already exist in *r
388          * in which case they are overridden instead. This assumes
389          * there is enough space in the r array. */
390
391         for (; *a; a++) {
392                 char **j;
393                 size_t n;
394
395                 n = strcspn(*a, "=");
396
397                 if ((*a)[n] == '=')
398                         n++;
399
400                 for (j = r; j < *k; j++)
401                         if (strncmp(*j, *a, n) == 0)
402                                 break;
403
404                 if (j >= *k)
405                         (*k)++;
406                 else
407                         free(*j);
408
409                 if (!(*j = strdup(*a)))
410                         return -ENOMEM;
411         }
412
413         return 0;
414 }
415
416 char **strv_env_merge(unsigned n_lists, ...) {
417         size_t n = 0;
418         char **l, **k, **r;
419         va_list ap;
420         unsigned i;
421
422         /* Merges an arbitrary number of environment sets */
423
424         va_start(ap, n_lists);
425         for (i = 0; i < n_lists; i++) {
426                 l = va_arg(ap, char**);
427                 n += strv_length(l);
428         }
429         va_end(ap);
430
431         if (!(r = new(char*, n+1)))
432                 return NULL;
433
434         k = r;
435
436         va_start(ap, n_lists);
437         for (i = 0; i < n_lists; i++) {
438                 l = va_arg(ap, char**);
439                 if (env_append(r, &k, l) < 0)
440                         goto fail;
441         }
442         va_end(ap);
443
444         *k = NULL;
445
446         return r;
447
448 fail:
449         va_end(ap);
450
451         for (k--; k >= r; k--)
452                 free(*k);
453
454         free(r);
455
456         return NULL;
457 }
458
459 static bool env_match(const char *t, const char *pattern) {
460         assert(t);
461         assert(pattern);
462
463         /* pattern a matches string a
464          *         a matches a=
465          *         a matches a=b
466          *         a= matches a=
467          *         a=b matches a=b
468          *         a= does not match a
469          *         a=b does not match a=
470          *         a=b does not match a
471          *         a=b does not match a=c */
472
473         if (streq(t, pattern))
474                 return true;
475
476         if (!strchr(pattern, '=')) {
477                 size_t l = strlen(pattern);
478
479                 return strncmp(t, pattern, l) == 0 && t[l] == '=';
480         }
481
482         return false;
483 }
484
485 char **strv_env_delete(char **x, unsigned n_lists, ...) {
486         size_t n = 0, i = 0;
487         char **l, **k, **r, **j;
488         va_list ap;
489
490         /* Deletes every entry from x that is mentioned in the other
491          * string lists */
492
493         n = strv_length(x);
494
495         if (!(r = new(char*, n+1)))
496                 return NULL;
497
498         STRV_FOREACH(k, x) {
499                 va_start(ap, n_lists);
500
501                 for (i = 0; i < n_lists; i++) {
502                         l = va_arg(ap, char**);
503                         STRV_FOREACH(j, l)
504                                 if (env_match(*k, *j))
505                                         goto delete;
506                 }
507
508                 va_end(ap);
509
510                 if (!(r[i++] = strdup(*k))) {
511                         strv_free(r);
512                         return NULL;
513                 }
514
515                 continue;
516
517         delete:
518                 va_end(ap);
519         }
520
521         r[i] = NULL;
522
523         assert(i <= n);
524
525         return r;
526 }
527
528 char **strv_env_set(char **x, const char *p) {
529
530         char **k, **r;
531         char* m[2] = { (char*) p, NULL };
532
533         /* Overrides the env var setting of p, returns a new copy */
534
535         if (!(r = new(char*, strv_length(x)+2)))
536                 return NULL;
537
538         k = r;
539         if (env_append(r, &k, x) < 0)
540                 goto fail;
541
542         if (env_append(r, &k, m) < 0)
543                 goto fail;
544
545         *k = NULL;
546
547         return r;
548
549 fail:
550         for (k--; k >= r; k--)
551                 free(*k);
552
553         free(r);
554
555         return NULL;
556
557 }
558
559 char *strv_env_get_with_length(char **l, const char *name, size_t k) {
560         char **i;
561
562         assert(name);
563
564         STRV_FOREACH(i, l)
565                 if (strncmp(*i, name, k) == 0 &&
566                     (*i)[k] == '=')
567                         return *i + k + 1;
568
569         return NULL;
570 }
571
572 char *strv_env_get(char **l, const char *name) {
573         return strv_env_get_with_length(l, name, strlen(name));
574 }
575
576 char **strv_env_clean(char **l) {
577         char **r, **ret;
578
579         for (r = ret = l; *l; l++) {
580                 const char *equal;
581
582                 equal = strchr(*l, '=');
583
584                 if (equal && equal[1] == 0) {
585                         free(*l);
586                         continue;
587                 }
588
589                 *(r++) = *l;
590         }
591
592         *r = NULL;
593
594         return ret;
595 }
596
597 char **strv_parse_nulstr(const char *s, size_t l) {
598         const char *p;
599         unsigned c = 0, i = 0;
600         char **v;
601
602         assert(s || l <= 0);
603
604         if (l <= 0)
605                 return strv_new(NULL, NULL);
606
607         for (p = s; p < s + l; p++)
608                 if (*p == 0)
609                         c++;
610
611         if (s[l-1] != 0)
612                 c++;
613
614         if (!(v = new0(char*, c+1)))
615                 return NULL;
616
617         p = s;
618         while (p < s + l) {
619                 const char *e;
620
621                 e = memchr(p, 0, s + l - p);
622
623                 if (!(v[i++] = strndup(p, e ? e - p : s + l - p))) {
624                         strv_free(v);
625                         return NULL;
626                 }
627
628                 if (!e)
629                         break;
630
631                 p = e + 1;
632         }
633
634         assert(i == c);
635
636         return v;
637 }