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