1 /* strlist.c - string helpers
2 * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc.
3 * Copyright (C) 2015 g10 Code GmbH
4 *
5 * This file is part of GnuPG.
6 *
7 * GnuPG is free software; you can redistribute and/or modify this
8 * part of GnuPG under the terms of either
9 *
10 * - the GNU Lesser General Public License as published by the Free
11 * Software Foundation; either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * or
15 *
16 * - the GNU General Public License as published by the Free
17 * Software Foundation; either version 2 of the License, or (at
18 * your option) any later version.
19 *
20 * or both in parallel, as here.
21 *
22 * GnuPG is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copies of the GNU General Public License
28 * and the GNU Lesser General Public License along with this program;
29 * if not, see <https://www.gnu.org/licenses/>.
30 */
31
32 #include <config.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdarg.h>
36 #include <ctype.h>
37
38 #include "util.h"
39 #include "common-defs.h"
40 #include "strlist.h"
41 #include "utf8conv.h"
42 #include "mischelp.h"
43
44 void
free_strlist(strlist_t sl)45 free_strlist( strlist_t sl )
46 {
47 strlist_t sl2;
48
49 for(; sl; sl = sl2 ) {
50 sl2 = sl->next;
51 xfree(sl);
52 }
53 }
54
55
56 void
free_strlist_wipe(strlist_t sl)57 free_strlist_wipe (strlist_t sl)
58 {
59 strlist_t sl2;
60
61 for(; sl; sl = sl2 ) {
62 sl2 = sl->next;
63 wipememory (sl, sizeof *sl + strlen (sl->d));
64 xfree(sl);
65 }
66 }
67
68
69 /* Add STRING to the LIST at the front. This function terminates the
70 process on memory shortage. */
71 strlist_t
add_to_strlist(strlist_t * list,const char * string)72 add_to_strlist( strlist_t *list, const char *string )
73 {
74 strlist_t sl;
75
76 sl = xmalloc( sizeof *sl + strlen(string));
77 sl->flags = 0;
78 strcpy(sl->d, string);
79 sl->next = *list;
80 *list = sl;
81 return sl;
82 }
83
84
85 /* Add STRING to the LIST at the front. This function returns NULL
86 and sets ERRNO on memory shortage. */
87 strlist_t
add_to_strlist_try(strlist_t * list,const char * string)88 add_to_strlist_try (strlist_t *list, const char *string)
89 {
90 strlist_t sl;
91
92 sl = xtrymalloc (sizeof *sl + strlen (string));
93 if (sl)
94 {
95 sl->flags = 0;
96 strcpy (sl->d, string);
97 sl->next = *list;
98 *list = sl;
99 }
100 return sl;
101 }
102
103
104 /* Same as add_to_strlist() but if IS_UTF8 is *not* set, a conversion
105 to UTF-8 is done. This function terminates the process on memory
106 shortage. */
107 strlist_t
add_to_strlist2(strlist_t * list,const char * string,int is_utf8)108 add_to_strlist2( strlist_t *list, const char *string, int is_utf8 )
109 {
110 strlist_t sl;
111
112 if (is_utf8)
113 sl = add_to_strlist( list, string );
114 else
115 {
116 char *p = native_to_utf8( string );
117 sl = add_to_strlist( list, p );
118 xfree ( p );
119 }
120 return sl;
121 }
122
123
124 /* Add STRING to the LIST at the end. This function terminates the
125 process on memory shortage. */
126 strlist_t
append_to_strlist(strlist_t * list,const char * string)127 append_to_strlist( strlist_t *list, const char *string )
128 {
129 strlist_t sl;
130 sl = append_to_strlist_try (list, string);
131 if (!sl)
132 xoutofcore ();
133 return sl;
134 }
135
136
137 /* Add STRING to the LIST at the end. */
138 strlist_t
append_to_strlist_try(strlist_t * list,const char * string)139 append_to_strlist_try (strlist_t *list, const char *string)
140 {
141 strlist_t r, sl;
142
143 sl = xtrymalloc( sizeof *sl + strlen(string));
144 if (sl == NULL)
145 return NULL;
146
147 sl->flags = 0;
148 strcpy(sl->d, string);
149 sl->next = NULL;
150 if( !*list )
151 *list = sl;
152 else {
153 for( r = *list; r->next; r = r->next )
154 ;
155 r->next = sl;
156 }
157 return sl;
158 }
159
160
161 strlist_t
append_to_strlist2(strlist_t * list,const char * string,int is_utf8)162 append_to_strlist2( strlist_t *list, const char *string, int is_utf8 )
163 {
164 strlist_t sl;
165
166 if( is_utf8 )
167 sl = append_to_strlist( list, string );
168 else
169 {
170 char *p = native_to_utf8 (string);
171 sl = append_to_strlist( list, p );
172 xfree( p );
173 }
174 return sl;
175 }
176
177
178 /* Return a copy of LIST. This function terminates the process on
179 memory shortage.*/
180 strlist_t
strlist_copy(strlist_t list)181 strlist_copy (strlist_t list)
182 {
183 strlist_t newlist = NULL, sl, *last;
184
185 last = &newlist;
186 for (; list; list = list->next)
187 {
188 sl = xmalloc (sizeof *sl + strlen (list->d));
189 sl->flags = list->flags;
190 strcpy(sl->d, list->d);
191 sl->next = NULL;
192 *last = sl;
193 last = &sl;
194 }
195 return newlist;
196 }
197
198
199
200 strlist_t
strlist_prev(strlist_t head,strlist_t node)201 strlist_prev( strlist_t head, strlist_t node )
202 {
203 strlist_t n;
204
205 for(n=NULL; head && head != node; head = head->next )
206 n = head;
207 return n;
208 }
209
210 strlist_t
strlist_last(strlist_t node)211 strlist_last( strlist_t node )
212 {
213 if( node )
214 for( ; node->next ; node = node->next )
215 ;
216 return node;
217 }
218
219
220 /* Remove the first item from LIST and return its content in an
221 allocated buffer. This function terminates the process on memory
222 shortage. */
223 char *
strlist_pop(strlist_t * list)224 strlist_pop (strlist_t *list)
225 {
226 char *str=NULL;
227 strlist_t sl=*list;
228
229 if(sl)
230 {
231 str = xmalloc(strlen(sl->d)+1);
232 strcpy(str,sl->d);
233
234 *list=sl->next;
235 xfree(sl);
236 }
237
238 return str;
239 }
240
241 /* Return the first element of the string list HAYSTACK whose string
242 matches NEEDLE. If no elements match, return NULL. */
243 strlist_t
strlist_find(strlist_t haystack,const char * needle)244 strlist_find (strlist_t haystack, const char *needle)
245 {
246 for (;
247 haystack;
248 haystack = haystack->next)
249 if (strcmp (haystack->d, needle) == 0)
250 return haystack;
251 return NULL;
252 }
253
254 int
strlist_length(strlist_t list)255 strlist_length (strlist_t list)
256 {
257 int i;
258 for (i = 0; list; list = list->next)
259 i ++;
260
261 return i;
262 }
263
264 /* Reverse the list *LIST in place. */
265 strlist_t
strlist_rev(strlist_t * list)266 strlist_rev (strlist_t *list)
267 {
268 strlist_t l = *list;
269 strlist_t lrev = NULL;
270
271 while (l)
272 {
273 strlist_t tail = l->next;
274 l->next = lrev;
275 lrev = l;
276 l = tail;
277 }
278
279 *list = lrev;
280 return lrev;
281 }
282