chiark / gitweb /
Properly report invalid quoted strings
[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 int strv_extend_strv(char ***a, char **b) {
170         int r;
171         char **s;
172
173         STRV_FOREACH(s, b) {
174                 r = strv_extend(a, *s);
175                 if (r < 0)
176                         return r;
177         }
178
179         return 0;
180 }
181
182 int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
183         int r;
184         char **s;
185
186         STRV_FOREACH(s, b) {
187                 char *v;
188
189                 v = strappend(*s, suffix);
190                 if (!v)
191                         return -ENOMEM;
192
193                 r = strv_push(a, v);
194                 if (r < 0) {
195                         free(v);
196                         return r;
197                 }
198         }
199
200         return 0;
201 }
202
203 char **strv_split(const char *s, const char *separator) {
204         const char *word, *state;
205         size_t l;
206         unsigned n, i;
207         char **r;
208
209         assert(s);
210
211         n = 0;
212         FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
213                 n++;
214
215         r = new(char*, n+1);
216         if (!r)
217                 return NULL;
218
219         i = 0;
220         FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
221                 r[i] = strndup(word, l);
222                 if (!r[i]) {
223                         strv_free(r);
224                         return NULL;
225                 }
226
227                 i++;
228         }
229
230         r[i] = NULL;
231         return r;
232 }
233
234 int strv_split_quoted(char ***t, const char *s) {
235         const char *word, *state;
236         size_t l;
237         unsigned n, i;
238         char **r;
239
240         assert(s);
241
242         n = 0;
243         FOREACH_WORD_QUOTED(word, l, s, state)
244                 n++;
245         if (!isempty(state))
246                 /* bad syntax */
247                 return -EINVAL;
248
249         r = new(char*, n+1);
250         if (!r)
251                 return -ENOMEM;
252
253         i = 0;
254         FOREACH_WORD_QUOTED(word, l, s, state) {
255                 r[i] = cunescape_length(word, l);
256                 if (!r[i]) {
257                         strv_free(r);
258                         return -ENOMEM;
259                 }
260                 i++;
261         }
262
263         r[i] = NULL;
264         *t = r;
265         return 0;
266 }
267
268 char **strv_split_newlines(const char *s) {
269         char **l;
270         unsigned n;
271
272         assert(s);
273
274         /* Special version of strv_split() that splits on newlines and
275          * suppresses an empty string at the end */
276
277         l = strv_split(s, NEWLINE);
278         if (!l)
279                 return NULL;
280
281         n = strv_length(l);
282         if (n <= 0)
283                 return l;
284
285         if (isempty(l[n-1])) {
286                 free(l[n-1]);
287                 l[n-1] = NULL;
288         }
289
290         return l;
291 }
292
293 char *strv_join(char **l, const char *separator) {
294         char *r, *e;
295         char **s;
296         size_t n, k;
297
298         if (!separator)
299                 separator = " ";
300
301         k = strlen(separator);
302
303         n = 0;
304         STRV_FOREACH(s, l) {
305                 if (n != 0)
306                         n += k;
307                 n += strlen(*s);
308         }
309
310         r = new(char, n+1);
311         if (!r)
312                 return NULL;
313
314         e = r;
315         STRV_FOREACH(s, l) {
316                 if (e != r)
317                         e = stpcpy(e, separator);
318
319                 e = stpcpy(e, *s);
320         }
321
322         *e = 0;
323
324         return r;
325 }
326
327 char *strv_join_quoted(char **l) {
328         char *buf = NULL;
329         char **s;
330         size_t allocated = 0, len = 0;
331
332         STRV_FOREACH(s, l) {
333                 /* assuming here that escaped string cannot be more
334                  * than twice as long, and reserving space for the
335                  * separator and quotes.
336                  */
337                 _cleanup_free_ char *esc = NULL;
338                 size_t needed;
339
340                 if (!GREEDY_REALLOC(buf, allocated,
341                                     len + strlen(*s) * 2 + 3))
342                         goto oom;
343
344                 esc = cescape(*s);
345                 if (!esc)
346                         goto oom;
347
348                 needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
349                                   len > 0 ? " " : "", esc);
350                 assert(needed < allocated - len);
351                 len += needed;
352         }
353
354         if (!buf)
355                 buf = malloc0(1);
356
357         return buf;
358
359  oom:
360         free(buf);
361         return NULL;
362 }
363
364 int strv_push(char ***l, char *value) {
365         char **c;
366         unsigned n;
367
368         if (!value)
369                 return 0;
370
371         n = strv_length(*l);
372         c = realloc(*l, sizeof(char*) * (n + 2));
373         if (!c)
374                 return -ENOMEM;
375
376         c[n] = value;
377         c[n+1] = NULL;
378
379         *l = c;
380         return 0;
381 }
382
383 int strv_push_prepend(char ***l, char *value) {
384         char **c;
385         unsigned n, i;
386
387         if (!value)
388                 return 0;
389
390         n = strv_length(*l);
391         c = new(char*, n + 2);
392         if (!c)
393                 return -ENOMEM;
394
395         for (i = 0; i < n; i++)
396                 c[i+1] = (*l)[i];
397
398         c[0] = value;
399         c[n+1] = NULL;
400
401         free(*l);
402         *l = c;
403
404         return 0;
405 }
406
407 int strv_consume(char ***l, char *value) {
408         int r;
409
410         r = strv_push(l, value);
411         if (r < 0)
412                 free(value);
413
414         return r;
415 }
416
417 int strv_consume_prepend(char ***l, char *value) {
418         int r;
419
420         r = strv_push_prepend(l, value);
421         if (r < 0)
422                 free(value);
423
424         return r;
425 }
426
427 int strv_extend(char ***l, const char *value) {
428         char *v;
429
430         if (!value)
431                 return 0;
432
433         v = strdup(value);
434         if (!v)
435                 return -ENOMEM;
436
437         return strv_consume(l, v);
438 }
439
440 char **strv_uniq(char **l) {
441         char **i;
442
443         /* Drops duplicate entries. The first identical string will be
444          * kept, the others dropped */
445
446         STRV_FOREACH(i, l)
447                 strv_remove(i+1, *i);
448
449         return l;
450 }
451
452 char **strv_remove(char **l, const char *s) {
453         char **f, **t;
454
455         if (!l)
456                 return NULL;
457
458         assert(s);
459
460         /* Drops every occurrence of s in the string list, edits
461          * in-place. */
462
463         for (f = t = l; *f; f++)
464                 if (streq(*f, s))
465                         free(*f);
466                 else
467                         *(t++) = *f;
468
469         *t = NULL;
470         return l;
471 }
472
473 char **strv_parse_nulstr(const char *s, size_t l) {
474         const char *p;
475         unsigned c = 0, i = 0;
476         char **v;
477
478         assert(s || l <= 0);
479
480         if (l <= 0)
481                 return new0(char*, 1);
482
483         for (p = s; p < s + l; p++)
484                 if (*p == 0)
485                         c++;
486
487         if (s[l-1] != 0)
488                 c++;
489
490         v = new0(char*, c+1);
491         if (!v)
492                 return NULL;
493
494         p = s;
495         while (p < s + l) {
496                 const char *e;
497
498                 e = memchr(p, 0, s + l - p);
499
500                 v[i] = strndup(p, e ? e - p : s + l - p);
501                 if (!v[i]) {
502                         strv_free(v);
503                         return NULL;
504                 }
505
506                 i++;
507
508                 if (!e)
509                         break;
510
511                 p = e + 1;
512         }
513
514         assert(i == c);
515
516         return v;
517 }
518
519 char **strv_split_nulstr(const char *s) {
520         const char *i;
521         char **r = NULL;
522
523         NULSTR_FOREACH(i, s)
524                 if (strv_extend(&r, i) < 0) {
525                         strv_free(r);
526                         return NULL;
527                 }
528
529         if (!r)
530                 return strv_new(NULL, NULL);
531
532         return r;
533 }
534
535 bool strv_overlap(char **a, char **b) {
536         char **i;
537
538         STRV_FOREACH(i, a)
539                 if (strv_contains(b, *i))
540                         return true;
541
542         return false;
543 }
544
545 static int str_compare(const void *_a, const void *_b) {
546         const char **a = (const char**) _a, **b = (const char**) _b;
547
548         return strcmp(*a, *b);
549 }
550
551 char **strv_sort(char **l) {
552
553         if (strv_isempty(l))
554                 return l;
555
556         qsort(l, strv_length(l), sizeof(char*), str_compare);
557         return l;
558 }
559
560 void strv_print(char **l) {
561         char **s;
562
563         STRV_FOREACH(s, l)
564                 puts(*s);
565 }
566
567 int strv_extendf(char ***l, const char *format, ...) {
568         va_list ap;
569         char *x;
570         int r;
571
572         va_start(ap, format);
573         r = vasprintf(&x, format, ap);
574         va_end(ap);
575
576         if (r < 0)
577                 return -ENOMEM;
578
579         return strv_consume(l, x);
580 }