blkdeactivate.sh: Add PATH environment variable into script
[platform/upstream/device-mapper.git] / lib / datastruct / str_list.c
1 /*
2  * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
3  * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
4  *
5  * This file is part of LVM2.
6  *
7  * This copyrighted material is made available to anyone wishing to use,
8  * modify, copy, or redistribute it subject to the terms and conditions
9  * of the GNU Lesser General Public License v.2.1.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, write to the Free Software Foundation,
13  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14  */
15
16 #include "lib/misc/lib.h"
17 #include "lib/datastruct/str_list.h"
18
19 struct dm_list *str_list_create(struct dm_pool *mem)
20 {
21         struct dm_list *sl;
22
23         if (!(sl = dm_pool_alloc(mem, sizeof(struct dm_list)))) {
24                 log_errno(ENOMEM, "str_list allocation failed");
25                 return NULL;
26         }
27
28         dm_list_init(sl);
29
30         return sl;
31 }
32
33 static int _str_list_add_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str, int as_first)
34 {
35         struct dm_str_list *sln;
36
37         if (!str)
38                 return_0;
39
40         if (!(sln = dm_pool_alloc(mem, sizeof(*sln))))
41                 return_0;
42
43         sln->str = str;
44         if (as_first)
45                 dm_list_add_h(sll, &sln->list);
46         else
47                 dm_list_add(sll, &sln->list);
48
49         return 1;
50 }
51
52 int str_list_add_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str)
53 {
54         return _str_list_add_no_dup_check(mem, sll, str, 0);
55 }
56
57 int str_list_add_h_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str)
58 {
59         return _str_list_add_no_dup_check(mem, sll, str, 1);
60 }
61
62 int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str)
63 {
64         if (!str)
65                 return_0;
66
67         /* Already in list? */
68         if (str_list_match_item(sll, str))
69                 return 1;
70
71         return str_list_add_no_dup_check(mem, sll, str);
72 }
73
74 /* Add contents of sll2 to sll */
75 int str_list_add_list(struct dm_pool *mem, struct dm_list *sll, struct dm_list *sll2)
76 {
77         struct dm_str_list *sl;
78
79         if (!sll2)
80                 return_0;
81
82         dm_list_iterate_items(sl, sll2)
83                 if (!str_list_add(mem, sll, sl->str))
84                         return_0;
85
86         return 1;
87 }
88
89 void str_list_del(struct dm_list *sll, const char *str)
90 {
91         struct dm_list *slh, *slht;
92
93         dm_list_iterate_safe(slh, slht, sll)
94                 if (!strcmp(str, dm_list_item(slh, struct dm_str_list)->str))
95                         dm_list_del(slh);
96 }
97
98 void str_list_wipe(struct dm_list *sll)
99 {
100         struct dm_list *slh, *slht;
101
102         dm_list_iterate_safe(slh, slht, sll)
103                 dm_list_del(slh);
104 }
105
106 int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
107                  const struct dm_list *sllold)
108 {
109         struct dm_str_list *sl;
110
111         dm_list_init(sllnew);
112
113         dm_list_iterate_items(sl, sllold) {
114                 if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str)))
115                         return_0;
116         }
117
118         return 1;
119 }
120
121 /*
122  * Is item on list?
123  */
124 int str_list_match_item(const struct dm_list *sll, const char *str)
125 {
126         struct dm_str_list *sl;
127
128         dm_list_iterate_items(sl, sll)
129                 if (!strcmp(str, sl->str))
130                         return 1;
131
132         return 0;
133 }
134
135 /*
136  * Is at least one item on both lists?
137  * If tag_matched is non-NULL, it is set to the tag that matched.
138  */
139 int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2, const char **tag_matched)
140 {
141         struct dm_str_list *sl;
142
143         dm_list_iterate_items(sl, sll)
144                 if (str_list_match_item(sll2, sl->str)) {
145                         if (tag_matched)
146                                 *tag_matched = sl->str;
147                         return 1;
148                 }
149
150         return 0;
151 }
152
153 /*
154  * Do both lists contain the same set of items?
155  */
156 int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2)
157 {
158         struct dm_str_list *sl;
159
160         if (dm_list_size(sll) != dm_list_size(sll2))
161                 return 0;
162
163         dm_list_iterate_items(sl, sll)
164                 if (!str_list_match_item(sll2, sl->str))
165                         return 0;
166
167         return 1;
168 }
169
170 char *str_list_to_str(struct dm_pool *mem, const struct dm_list *list,
171                       const char *delim)
172 {
173         size_t delim_len = strlen(delim);
174         unsigned list_size = dm_list_size(list);
175         struct dm_str_list *sl;
176         char *str, *p;
177         size_t len = 0;
178         unsigned i = 0;
179
180         dm_list_iterate_items(sl, list)
181                 len += strlen(sl->str);
182         if (list_size > 1)
183                 len += ((list_size - 1) * delim_len);
184
185         str = dm_pool_alloc(mem, len+1);
186         if (!str) {
187                 log_error("str_list_to_str: string allocation failed.");
188                 return NULL;
189         }
190         str[len] = '\0';
191         p = str;
192
193         dm_list_iterate_items(sl, list) {
194                 len = strlen(sl->str);
195                 memcpy(p, sl->str, len);
196                 p += len;
197
198                 if (++i != list_size) {
199                         memcpy(p, delim, delim_len);
200                         p += delim_len;
201                 }
202         }
203
204         return str;
205 }
206
207 struct dm_list *str_to_str_list(struct dm_pool *mem, const char *str,
208                                 const char *delim, int ignore_multiple_delim)
209 {
210         size_t delim_len = strlen(delim);
211         struct dm_list *list;
212         const char *p1, *p2, *next;
213         char *str_item;
214         size_t len;
215
216         if (!(list = str_list_create(mem))) {
217                 log_error("str_to_str_list: string list allocation failed.");
218                 return NULL;
219         }
220
221         p1 = str;
222         while (*p1) {
223                 if (!(p2 = strstr(p1, delim)))
224                         next = p2 = str + strlen(str);
225                 else
226                         next = p2 + delim_len;
227
228                 len = p2 - p1;
229                 str_item = dm_pool_alloc(mem, len+1);
230                 if (!str_item) {
231                         log_error("str_to_str_list: string list item allocation failed.");
232                         goto bad;
233                 }
234                 memcpy(str_item, p1, len);
235                 str_item[len] = '\0';
236
237                 if (!str_list_add_no_dup_check(mem, list, str_item))
238                         goto_bad;
239
240                 if (ignore_multiple_delim) {
241                         while (!strncmp(next, delim, delim_len))
242                                 next += delim_len;
243                 }
244
245                 p1 = next;
246         }
247
248         return list;
249 bad:
250         dm_pool_free(mem, list);
251
252         return NULL;
253 }