• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of eudev, forked from systemd.
3 
4   Copyright 2010 Lennart Poettering
5 
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10 
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15 
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19 
20 #include <assert.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 
26 #include "util.h"
27 #include "strv.h"
28 
strv_clear(char ** l)29 void strv_clear(char **l) {
30         char **k;
31 
32         if (!l)
33                 return;
34 
35         for (k = l; *k; k++)
36                 free(*k);
37 
38         *l = NULL;
39 }
40 
strv_free(char ** l)41 char **strv_free(char **l) {
42         strv_clear(l);
43         free(l);
44         return NULL;
45 }
46 
strv_copy(char * const * l)47 char **strv_copy(char * const *l) {
48         char **r, **k;
49 
50         k = r = new(char*, strv_length(l) + 1);
51         if (!r)
52                 return NULL;
53 
54         if (l)
55                 for (; *l; k++, l++) {
56                         *k = strdup(*l);
57                         if (!*k) {
58                                 strv_free(r);
59                                 return NULL;
60                         }
61                 }
62 
63         *k = NULL;
64         return r;
65 }
66 
strv_length(char * const * l)67 unsigned strv_length(char * const *l) {
68         unsigned n = 0;
69 
70         if (!l)
71                 return 0;
72 
73         for (; *l; l++)
74                 n++;
75 
76         return n;
77 }
78 
strv_new_ap(const char * x,va_list ap)79 char **strv_new_ap(const char *x, va_list ap) {
80         const char *s;
81         char **a;
82         unsigned n = 0, i = 0;
83         va_list aq;
84 
85         /* As a special trick we ignore all listed strings that equal
86          * (const char*) -1. This is supposed to be used with the
87          * STRV_IFNOTNULL() macro to include possibly NULL strings in
88          * the string list. */
89 
90         if (x) {
91                 n = x == (const char*) -1 ? 0 : 1;
92 
93                 va_copy(aq, ap);
94                 while ((s = va_arg(aq, const char*))) {
95                         if (s == (const char*) -1)
96                                 continue;
97 
98                         n++;
99                 }
100 
101                 va_end(aq);
102         }
103 
104         a = new(char*, n+1);
105         if (!a)
106                 return NULL;
107 
108         if (x) {
109                 if (x != (const char*) -1) {
110                         a[i] = strdup(x);
111                         if (!a[i])
112                                 goto fail;
113                         i++;
114                 }
115 
116                 while ((s = va_arg(ap, const char*))) {
117 
118                         if (s == (const char*) -1)
119                                 continue;
120 
121                         a[i] = strdup(s);
122                         if (!a[i])
123                                 goto fail;
124 
125                         i++;
126                 }
127         }
128 
129         a[i] = NULL;
130 
131         return a;
132 
133 fail:
134         strv_free(a);
135         return NULL;
136 }
137 
strv_new(const char * x,...)138 char **strv_new(const char *x, ...) {
139         char **r;
140         va_list ap;
141 
142         va_start(ap, x);
143         r = strv_new_ap(x, ap);
144         va_end(ap);
145 
146         return r;
147 }
148 
strv_push(char *** l,char * value)149 int strv_push(char ***l, char *value) {
150         char **c;
151         unsigned n, m;
152 
153         if (!value)
154                 return 0;
155 
156         n = strv_length(*l);
157 
158         /* increase and check for overflow */
159         m = n + 2;
160         if (m < n)
161                 return -ENOMEM;
162 
163         c = realloc_multiply(*l, sizeof(char*), m);
164         if (!c)
165                 return -ENOMEM;
166 
167         c[n] = value;
168         c[n+1] = NULL;
169 
170         *l = c;
171         return 0;
172 }
173 
strv_consume(char *** l,char * value)174 int strv_consume(char ***l, char *value) {
175         int r;
176 
177         r = strv_push(l, value);
178         if (r < 0)
179                 free(value);
180 
181         return r;
182 }
183 
strv_extend(char *** l,const char * value)184 int strv_extend(char ***l, const char *value) {
185         char *v;
186 
187         if (!value)
188                 return 0;
189 
190         v = strdup(value);
191         if (!v)
192                 return -ENOMEM;
193 
194         return strv_consume(l, v);
195 }
196 
strv_uniq(char ** l)197 char **strv_uniq(char **l) {
198         char **i;
199 
200         /* Drops duplicate entries. The first identical string will be
201          * kept, the others dropped */
202 
203         STRV_FOREACH(i, l)
204                 strv_remove(i+1, *i);
205 
206         return l;
207 }
208 
strv_remove(char ** l,const char * s)209 char **strv_remove(char **l, const char *s) {
210         char **f, **t;
211 
212         if (!l)
213                 return NULL;
214 
215         assert(s);
216 
217         /* Drops every occurrence of s in the string list, edits
218          * in-place. */
219 
220         for (f = t = l; *f; f++)
221                 if (streq(*f, s))
222                         free(*f);
223                 else
224                         *(t++) = *f;
225 
226         *t = NULL;
227         return l;
228 }
229