ec6c58162f7cff7aa4e5870646839f1b8d258765
[jelmer/samba4-debian.git] / source / lib / util / util_strlist.c
1 /* 
2    Unix SMB/CIFS implementation.
3    
4    Copyright (C) Andrew Tridgell 2005
5    Copyright (C) Jelmer Vernooij 2005
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 /*
25   build a null terminated list of strings from a input string and a
26   separator list. The separator list must contain characters less than
27   or equal to 0x2f for this to work correctly on multi-byte strings
28 */
29 const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
30 {
31         int num_elements = 0;
32         const char **ret = NULL;
33
34         if (sep == NULL) {
35                 sep = LIST_SEP;
36         }
37
38         ret = talloc_array(mem_ctx, const char *, 1);
39         if (ret == NULL) {
40                 return NULL;
41         }
42
43         while (string && *string) {
44                 size_t len = strcspn(string, sep);
45                 const char **ret2;
46                 
47                 if (len == 0) {
48                         string += strspn(string, sep);
49                         continue;
50                 }
51
52                 ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2);
53                 if (ret2 == NULL) {
54                         talloc_free(ret);
55                         return NULL;
56                 }
57                 ret = ret2;
58
59                 ret[num_elements] = talloc_strndup(ret, string, len);
60                 if (ret[num_elements] == NULL) {
61                         talloc_free(ret);
62                         return NULL;
63                 }
64
65                 num_elements++;
66                 string += len;
67         }
68
69         ret[num_elements] = NULL;
70
71         return ret;
72 }
73
74 /* build a null terminated list of strings from an argv-like input string 
75    Entries are seperated by spaces and can be enclosed by quotes. 
76    Does NOT support escaping
77  */
78 const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
79 {
80         int num_elements = 0;
81         const char **ret = NULL;
82
83         ret = talloc_array(mem_ctx, const char *, 1);
84         if (ret == NULL) {
85                 return NULL;
86         }
87
88         if (sep == NULL)
89                 sep = " \t\n\r";
90
91         while (string && *string) {
92                 size_t len = strcspn(string, sep);
93                 char *element;
94                 const char **ret2;
95                 
96                 if (len == 0) {
97                         string += strspn(string, sep);
98                         continue;
99                 }
100
101                 if (*string == '\"') {
102                         string++;
103                         len = strcspn(string, "\"");
104                         element = talloc_strndup(ret, string, len);
105                         string += len + 1;
106                 } else {
107                         element = talloc_strndup(ret, string, len);
108                         string += len;
109                 }
110
111                 if (element == NULL) {
112                         talloc_free(ret);
113                         return NULL;
114                 }
115
116                 ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2);
117                 if (ret2 == NULL) {
118                         talloc_free(ret);
119                         return NULL;
120                 }
121                 ret = ret2;
122
123                 ret[num_elements] = element;    
124
125                 num_elements++;
126         }
127
128         ret[num_elements] = NULL;
129
130         return ret;
131
132 }
133
134 /* join a list back to one string */
135 char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator)
136 {
137         char *ret = NULL;
138         int i;
139         
140         if (list[0] == NULL)
141                 return talloc_strdup(mem_ctx, "");
142
143         ret = talloc_strdup(mem_ctx, list[0]);
144
145         for (i = 1; list[i]; i++) {
146                 ret = talloc_asprintf_append(ret, "%c%s", seperator, list[i]);
147         }
148
149         return ret;
150 }
151
152 /* join a list back to one (shell-like) string; entries 
153  * seperated by spaces, using quotes where necessary */
154 char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep)
155 {
156         char *ret = NULL;
157         int i;
158         
159         if (list[0] == NULL)
160                 return talloc_strdup(mem_ctx, "");
161
162         if (strchr(list[0], ' ') || strlen(list[0]) == 0) 
163                 ret = talloc_asprintf(mem_ctx, "\"%s\"", list[0]);
164         else 
165                 ret = talloc_strdup(mem_ctx, list[0]);
166
167         for (i = 1; list[i]; i++) {
168                 if (strchr(list[i], ' ') || strlen(list[i]) == 0) 
169                         ret = talloc_asprintf_append(ret, "%c\"%s\"", sep, list[i]);
170                 else 
171                         ret = talloc_asprintf_append(ret, "%c%s", sep, list[i]);
172         }
173
174         return ret;
175 }
176
177 /*
178   return the number of elements in a string list
179 */
180 size_t str_list_length(const char **list)
181 {
182         size_t ret;
183         for (ret=0;list && list[ret];ret++) /* noop */ ;
184         return ret;
185 }
186
187
188 /*
189   copy a string list
190 */
191 const char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list)
192 {
193         int i;
194         const char **ret = talloc_array(mem_ctx, const char *, str_list_length(list)+1);
195         if (ret == NULL) return NULL;
196
197         for (i=0;list && list[i];i++) {
198                 ret[i] = talloc_strdup(ret, list[i]);
199                 if (ret[i] == NULL) {
200                         talloc_free(ret);
201                         return NULL;
202                 }
203         }
204         ret[i] = NULL;
205         return ret;
206 }
207
208 /*
209    Return true if all the elements of the list match exactly.
210  */
211 BOOL str_list_equal(const char **list1, const char **list2)
212 {
213         int i;
214         
215         if (list1 == NULL || list2 == NULL) {
216                 return (list1 == list2); 
217         }
218         
219         for (i=0;list1[i] && list2[i];i++) {
220                 if (strcmp(list1[i], list2[i]) != 0) {
221                         return False;
222                 }
223         }
224         if (list1[i] || list2[i]) {
225                 return False;
226         }
227         return True;
228 }
229
230
231 /*
232   add an entry to a string list
233 */
234 const char **str_list_add(const char **list, const char *s)
235 {
236         size_t len = str_list_length(list);
237         const char **ret;
238
239         ret = talloc_realloc(NULL, list, const char *, len+2);
240         if (ret == NULL) return NULL;
241
242         ret[len] = talloc_strdup(ret, s);
243         if (ret[len] == NULL) return NULL;
244
245         ret[len+1] = NULL;
246
247         return ret;
248 }
249
250 /*
251   remove an entry from a string list
252 */
253 void str_list_remove(const char **list, const char *s)
254 {
255         int i;
256
257         for (i=0;list[i];i++) {
258                 if (strcmp(list[i], s) == 0) break;
259         }
260         if (!list[i]) return;
261
262         for (;list[i];i++) {
263                 list[i] = list[i+1];
264         }
265 }
266
267
268 /*
269   return True if a string is in a list
270 */
271 BOOL str_list_check(const char **list, const char *s)
272 {
273         int i;
274
275         for (i=0;list[i];i++) {
276                 if (strcmp(list[i], s) == 0) return True;
277         }
278         return False;
279 }
280
281 /*
282   return True if a string is in a list, case insensitively
283 */
284 BOOL str_list_check_ci(const char **list, const char *s)
285 {
286         int i;
287
288         for (i=0;list[i];i++) {
289                 if (strcasecmp(list[i], s) == 0) return True;
290         }
291         return False;
292 }