]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/strv.c
networkd: listen to changes to the MAC address
[thirdparty/systemd.git] / src / shared / strv.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60918275 2
a7334b09
LP
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
5430f7f2
LP
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
a7334b09
LP
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
60918275
LP
22#include <assert.h>
23#include <stdlib.h>
24#include <stdarg.h>
25#include <string.h>
2e6c9e6b 26#include <errno.h>
60918275
LP
27
28#include "util.h"
29#include "strv.h"
30
31char *strv_find(char **l, const char *name) {
5f9a22c3
LP
32 char **i;
33
60918275
LP
34 assert(name);
35
5f9a22c3
LP
36 STRV_FOREACH(i, l)
37 if (streq(*i, name))
38 return *i;
60918275
LP
39
40 return NULL;
41}
42
a4bfb399
LP
43char *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
60918275
LP
55void 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
2fd9ae2e 67char **strv_copy(char * const *l) {
60918275
LP
68 char **r, **k;
69
1fd8d04e
LP
70 k = r = new(char*, strv_length(l) + 1);
71 if (!r)
60918275
LP
72 return NULL;
73
ede27aab 74 if (l)
1fd8d04e
LP
75 for (; *l; k++, l++) {
76 *k = strdup(*l);
77 if (!*k) {
78 strv_free(r);
79 return NULL;
80 }
81 }
60918275
LP
82
83 *k = NULL;
84 return r;
60918275
LP
85}
86
2fd9ae2e 87unsigned strv_length(char * const *l) {
60918275
LP
88 unsigned n = 0;
89
90 if (!l)
91 return 0;
92
93 for (; *l; l++)
94 n++;
95
96 return n;
97}
98
257eca1a 99char **strv_new_ap(const char *x, va_list ap) {
60918275
LP
100 const char *s;
101 char **a;
102 unsigned n = 0, i = 0;
257eca1a
LP
103 va_list aq;
104
07719a21
LP
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
60918275 110 if (x) {
07719a21 111 n = x == (const char*) -1 ? 0 : 1;
60918275 112
257eca1a 113 va_copy(aq, ap);
07719a21
LP
114 while ((s = va_arg(aq, const char*))) {
115 if (s == (const char*) -1)
116 continue;
117
60918275 118 n++;
07719a21
LP
119 }
120
257eca1a 121 va_end(aq);
60918275
LP
122 }
123
07719a21
LP
124 a = new(char*, n+1);
125 if (!a)
60918275
LP
126 return NULL;
127
128 if (x) {
07719a21
LP
129 if (x != (const char*) -1) {
130 a[i] = strdup(x);
131 if (!a[i])
132 goto fail;
133 i++;
60918275
LP
134 }
135
60918275 136 while ((s = va_arg(ap, const char*))) {
07719a21
LP
137
138 if (s == (const char*) -1)
139 continue;
140
141 a[i] = strdup(s);
142 if (!a[i])
60918275
LP
143 goto fail;
144
145 i++;
146 }
60918275
LP
147 }
148
149 a[i] = NULL;
257eca1a 150
60918275
LP
151 return a;
152
153fail:
1fd8d04e 154 strv_free(a);
60918275
LP
155 return NULL;
156}
034c6ed7 157
257eca1a
LP
158char **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
e3e45d4f
SP
169int strv_extend_strv(char ***a, char **b) {
170 int r;
171 char **s;
07719a21 172
e3e45d4f
SP
173 STRV_FOREACH(s, b) {
174 r = strv_extend(a, *s);
175 if (r < 0)
176 return r;
07719a21 177 }
034c6ed7 178
e3e45d4f 179 return 0;
5f9a22c3
LP
180}
181
e3e45d4f
SP
182int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
183 int r;
184 char **s;
5f9a22c3 185
e3e45d4f
SP
186 STRV_FOREACH(s, b) {
187 char *v;
5f9a22c3 188
e3e45d4f
SP
189 v = strappend(*s, suffix);
190 if (!v)
191 return -ENOMEM;
5f9a22c3 192
e3e45d4f
SP
193 r = strv_push(a, v);
194 if (r < 0) {
195 free(v);
196 return r;
8ea913b2 197 }
8ea913b2 198 }
5f9a22c3 199
e3e45d4f 200 return 0;
5f9a22c3
LP
201}
202
203char **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
1fd8d04e
LP
216 r = new(char*, n+1);
217 if (!r)
5f9a22c3
LP
218 return NULL;
219
220 i = 0;
1fd8d04e
LP
221 FOREACH_WORD_SEPARATOR(w, l, s, separator, state) {
222 r[i] = strndup(w, l);
223 if (!r[i]) {
5f9a22c3
LP
224 strv_free(r);
225 return NULL;
226 }
227
1fd8d04e
LP
228 i++;
229 }
230
5f9a22c3
LP
231 r[i] = NULL;
232 return r;
233}
234
235char **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
1fd8d04e
LP
248 r = new(char*, n+1);
249 if (!r)
5f9a22c3
LP
250 return NULL;
251
252 i = 0;
1fd8d04e
LP
253 FOREACH_WORD_QUOTED(w, l, s, state) {
254 r[i] = cunescape_length(w, l);
255 if (!r[i]) {
5f9a22c3
LP
256 strv_free(r);
257 return NULL;
258 }
1fd8d04e
LP
259 i++;
260 }
5f9a22c3
LP
261
262 r[i] = NULL;
263 return r;
264}
265
26d04f86
LP
266char **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
5f9a22c3
LP
291char *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
1fd8d04e
LP
308 r = new(char, n+1);
309 if (!r)
5f9a22c3
LP
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
8d49745c
LP
320 *e = 0;
321
5f9a22c3
LP
322 return r;
323}
324
a6fde353
ZJS
325char *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
4468addc 362int strv_push(char ***l, char *value) {
5926ccca 363 char **c;
82dde599 364 unsigned n;
5926ccca
LP
365
366 if (!value)
367 return 0;
368
82dde599
LP
369 n = strv_length(*l);
370 c = realloc(*l, sizeof(char*) * (n + 2));
4468addc 371 if (!c)
82dde599 372 return -ENOMEM;
82dde599 373
4468addc 374 c[n] = value;
82dde599
LP
375 c[n+1] = NULL;
376
5926ccca
LP
377 *l = c;
378 return 0;
379}
380
6e18964d
ZJS
381int strv_consume(char ***l, char *value) {
382 int r;
383
384 r = strv_push(l, value);
385 if (r < 0)
386 free(value);
387
388 return r;
389}
390
4468addc
LP
391int strv_extend(char ***l, const char *value) {
392 char *v;
4468addc
LP
393
394 if (!value)
395 return 0;
396
397 v = strdup(value);
398 if (!v)
399 return -ENOMEM;
400
6e18964d 401 return strv_consume(l, v);
4468addc
LP
402}
403
5f9a22c3 404char **strv_uniq(char **l) {
cba8922f
LP
405 char **i;
406
5f9a22c3
LP
407 /* Drops duplicate entries. The first identical string will be
408 * kept, the others dropped */
409
cba8922f 410 STRV_FOREACH(i, l)
5f9a22c3
LP
411 strv_remove(i+1, *i);
412
413 return l;
414}
415
416char **strv_remove(char **l, const char *s) {
417 char **f, **t;
418
419 if (!l)
420 return NULL;
421
5d6ab905
LP
422 assert(s);
423
424 /* Drops every occurrence of s in the string list, edits
425 * in-place. */
5f9a22c3 426
e3e45d4f
SP
427 for (f = t = l; *f; f++)
428 if (streq(*f, s))
71ecc858 429 free(*f);
e3e45d4f
SP
430 else
431 *(t++) = *f;
71ecc858
LP
432
433 *t = NULL;
434 return l;
435}
436
21bc923a
LP
437char **strv_parse_nulstr(const char *s, size_t l) {
438 const char *p;
439 unsigned c = 0, i = 0;
440 char **v;
441
442 assert(s || l <= 0);
443
444 if (l <= 0)
49b832c5 445 return new0(char*, 1);
21bc923a
LP
446
447 for (p = s; p < s + l; p++)
448 if (*p == 0)
449 c++;
450
451 if (s[l-1] != 0)
452 c++;
453
1fd8d04e
LP
454 v = new0(char*, c+1);
455 if (!v)
21bc923a
LP
456 return NULL;
457
458 p = s;
459 while (p < s + l) {
460 const char *e;
461
462 e = memchr(p, 0, s + l - p);
463
1fd8d04e
LP
464 v[i] = strndup(p, e ? e - p : s + l - p);
465 if (!v[i]) {
21bc923a
LP
466 strv_free(v);
467 return NULL;
468 }
469
1fd8d04e
LP
470 i++;
471
21bc923a
LP
472 if (!e)
473 break;
474
475 p = e + 1;
476 }
477
478 assert(i == c);
479
480 return v;
481}
0c85a4f3 482
fabe5c0e
LP
483char **strv_split_nulstr(const char *s) {
484 const char *i;
485 char **r = NULL;
486
487 NULSTR_FOREACH(i, s)
488 if (strv_extend(&r, i) < 0) {
489 strv_free(r);
490 return NULL;
491 }
492
493 if (!r)
494 return strv_new(NULL, NULL);
495
496 return r;
497}
498
0c85a4f3 499bool strv_overlap(char **a, char **b) {
e3e45d4f 500 char **i;
0c85a4f3 501
e3e45d4f
SP
502 STRV_FOREACH(i, a)
503 if (strv_contains(b, *i))
504 return true;
0c85a4f3
LP
505
506 return false;
507}
857a493d
LP
508
509static int str_compare(const void *_a, const void *_b) {
510 const char **a = (const char**) _a, **b = (const char**) _b;
511
512 return strcmp(*a, *b);
513}
514
515char **strv_sort(char **l) {
516
517 if (strv_isempty(l))
518 return l;
519
520 qsort(l, strv_length(l), sizeof(char*), str_compare);
521 return l;
522}
7c2d8094
TA
523
524void strv_print(char **l) {
525 char **s;
526
7c2d8094
TA
527 STRV_FOREACH(s, l)
528 puts(*s);
529}