skipcpio: limit the local var scope
[dracut.git] / install / strv.c
blob152b70c17fc8bfef792c394543339850a9fdefe4
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
3 /***
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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 ***/
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <errno.h>
28 #include "util.h"
29 #include "strv.h"
31 char *strv_find(char **l, const char *name) {
32 char **i;
34 assert(name);
36 STRV_FOREACH(i, l)
37 if (streq(*i, name))
38 return *i;
40 return NULL;
43 char *strv_find_prefix(char **l, const char *name) {
44 char **i;
46 assert(name);
48 STRV_FOREACH(i, l)
49 if (startswith(*i, name))
50 return *i;
52 return NULL;
55 void strv_free(char **l) {
56 char **k;
58 if (!l)
59 return;
61 for (k = l; *k; k++)
62 free(*k);
64 free(l);
67 char **strv_copy(char * const *l) {
68 char **r, **k;
70 k = r = new(char*, strv_length(l) + 1);
71 if (!r)
72 return NULL;
74 if (l)
75 for (; *l; k++, l++) {
76 *k = strdup(*l);
77 if (!*k) {
78 strv_free(r);
79 return NULL;
83 *k = NULL;
84 return r;
87 unsigned strv_length(char * const *l) {
88 unsigned n = 0;
90 if (!l)
91 return 0;
93 for (; *l; l++)
94 n++;
96 return n;
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;
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. */
110 if (x) {
111 n = x == (const char*) -1 ? 0 : 1;
113 va_copy(aq, ap);
114 while ((s = va_arg(aq, const char*))) {
115 if (s == (const char*) -1)
116 continue;
118 n++;
121 va_end(aq);
124 a = new(char*, n+1);
125 if (!a)
126 return NULL;
128 if (x) {
129 if (x != (const char*) -1) {
130 a[i] = strdup(x);
131 if (!a[i])
132 goto fail;
133 i++;
136 while ((s = va_arg(ap, const char*))) {
138 if (s == (const char*) -1)
139 continue;
141 a[i] = strdup(s);
142 if (!a[i])
143 goto fail;
145 i++;
149 a[i] = NULL;
151 return a;
153 fail:
154 strv_free(a);
155 return NULL;
158 char **strv_new(const char *x, ...) {
159 char **r;
160 va_list ap;
162 va_start(ap, x);
163 r = strv_new_ap(x, ap);
164 va_end(ap);
166 return r;
169 char **strv_merge(char **a, char **b) {
170 char **r, **k;
172 if (!a)
173 return strv_copy(b);
175 if (!b)
176 return strv_copy(a);
178 r = new(char*, strv_length(a) + strv_length(b) + 1);
179 if (!r)
180 return NULL;
182 for (k = r; *a; k++, a++) {
183 *k = strdup(*a);
184 if (!*k)
185 goto fail;
188 for (; *b; k++, b++) {
189 *k = strdup(*b);
190 if (!*k)
191 goto fail;
194 *k = NULL;
195 return r;
197 fail:
198 strv_free(r);
199 return NULL;
202 char **strv_merge_concat(char **a, char **b, const char *suffix) {
203 char **r, **k;
205 /* Like strv_merge(), but appends suffix to all strings in b, before adding */
207 if (!b)
208 return strv_copy(a);
210 r = new(char*, strv_length(a) + strv_length(b) + 1);
211 if (!r)
212 return NULL;
214 k = r;
215 if (a)
216 for (; *a; k++, a++) {
217 *k = strdup(*a);
218 if (!*k)
219 goto fail;
222 for (; *b; k++, b++) {
223 *k = strappend(*b, suffix);
224 if (!*k)
225 goto fail;
228 *k = NULL;
229 return r;
231 fail:
232 strv_free(r);
233 return NULL;
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;
244 assert(s);
246 n = 0;
247 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
248 n++;
250 r = new(char*, n+1);
251 if (!r)
252 return NULL;
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;
262 i++;
265 r[i] = NULL;
266 return r;
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;
276 assert(s);
278 n = 0;
279 FOREACH_WORD_QUOTED(w, l, s, state)
280 n++;
282 r = new(char*, n+1);
283 if (!r)
284 return NULL;
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;
293 i++;
296 r[i] = NULL;
297 return r;
300 char **strv_split_newlines(const char *s) {
301 char **l;
302 unsigned n;
304 assert(s);
306 /* Special version of strv_split() that splits on newlines and
307 * suppresses an empty string at the end */
309 l = strv_split(s, NEWLINE);
310 if (!l)
311 return NULL;
313 n = strv_length(l);
314 if (n <= 0)
315 return l;
317 if (isempty(l[n-1])) {
318 free(l[n-1]);
319 l[n-1] = NULL;
322 return l;
325 char *strv_join(char **l, const char *separator) {
326 char *r, *e;
327 char **s;
328 size_t n, k;
330 if (!separator)
331 separator = " ";
333 k = strlen(separator);
335 n = 0;
336 STRV_FOREACH(s, l) {
337 if (n != 0)
338 n += k;
339 n += strlen(*s);
342 r = new(char, n+1);
343 if (!r)
344 return NULL;
346 e = r;
347 STRV_FOREACH(s, l) {
348 if (e != r)
349 e = stpcpy(e, separator);
351 e = stpcpy(e, *s);
354 *e = 0;
356 return r;
359 char **strv_append(char **l, const char *s) {
360 char **r, **k;
362 if (!l)
363 return strv_new(s, NULL);
365 if (!s)
366 return strv_copy(l);
368 r = new(char*, strv_length(l)+2);
369 if (!r)
370 return NULL;
372 for (k = r; *l; k++, l++) {
373 *k = strdup(*l);
374 if (!*k)
375 goto fail;
378 k[0] = strdup(s);
379 if (!k[0])
380 goto fail;
382 k[1] = NULL;
383 return r;
385 fail:
386 strv_free(r);
387 return NULL;
390 int strv_push(char ***l, char *value) {
391 char **c;
392 unsigned n;
394 if (!value)
395 return 0;
397 n = strv_length(*l);
398 c = realloc(*l, sizeof(char*) * (n + 2));
399 if (!c)
400 return -ENOMEM;
402 c[n] = value;
403 c[n+1] = NULL;
405 *l = c;
406 return 0;
409 int strv_extend(char ***l, const char *value) {
410 char *v;
411 int r;
413 if (!value)
414 return 0;
416 v = strdup(value);
417 if (!v)
418 return -ENOMEM;
420 r = strv_push(l, v);
421 if (r < 0)
422 free(v);
424 return r;
427 char **strv_uniq(char **l) {
428 char **i;
430 /* Drops duplicate entries. The first identical string will be
431 * kept, the others dropped */
433 STRV_FOREACH(i, l)
434 strv_remove(i+1, *i);
436 return l;
439 char **strv_remove(char **l, const char *s) {
440 char **f, **t;
442 if (!l)
443 return NULL;
445 assert(s);
447 /* Drops every occurrence of s in the string list, edits
448 * in-place. */
450 for (f = t = l; *f; f++) {
452 if (streq(*f, s)) {
453 free(*f);
454 continue;
457 *(t++) = *f;
460 *t = NULL;
461 return l;
464 char **strv_remove_prefix(char **l, const char *s) {
465 char **f, **t;
467 if (!l)
468 return NULL;
470 assert(s);
472 /* Drops every occurrence of a string prefixed with s in the
473 * string list, edits in-place. */
475 for (f = t = l; *f; f++) {
477 if (startswith(*f, s)) {
478 free(*f);
479 continue;
482 *(t++) = *f;
485 *t = NULL;
486 return l;
489 char **strv_parse_nulstr(const char *s, size_t l) {
490 const char *p;
491 unsigned c = 0, i = 0;
492 char **v;
494 assert(s || l <= 0);
496 if (l <= 0)
497 return new0(char*, 1);
499 for (p = s; p < s + l; p++)
500 if (*p == 0)
501 c++;
503 if (s[l-1] != 0)
504 c++;
506 v = new0(char*, c+1);
507 if (!v)
508 return NULL;
510 p = s;
511 while (p < s + l) {
512 const char *e;
514 e = memchr(p, 0, s + l - p);
516 v[i] = strndup(p, e ? e - p : s + l - p);
517 if (!v[i]) {
518 strv_free(v);
519 return NULL;
522 i++;
524 if (!e)
525 break;
527 p = e + 1;
530 assert(i == c);
532 return v;
535 char **strv_split_nulstr(const char *s) {
536 const char *i;
537 char **r = NULL;
539 NULSTR_FOREACH(i, s)
540 if (strv_extend(&r, i) < 0) {
541 strv_free(r);
542 return NULL;
545 if (!r)
546 return strv_new(NULL, NULL);
548 return r;
551 bool strv_overlap(char **a, char **b) {
552 char **i, **j;
554 STRV_FOREACH(i, a) {
555 STRV_FOREACH(j, b) {
556 if (streq(*i, *j))
557 return true;
561 return false;
564 static int str_compare(const void *_a, const void *_b) {
565 const char **a = (const char**) _a, **b = (const char**) _b;
567 return strcmp(*a, *b);
570 char **strv_sort(char **l) {
572 if (strv_isempty(l))
573 return l;
575 qsort(l, strv_length(l), sizeof(char*), str_compare);
576 return l;
579 void strv_print(char **l) {
580 char **s;
582 if (!l)
583 return;
585 STRV_FOREACH(s, l)
586 puts(*s);