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