chiark / gitweb /
gpg agent threading bugs: Add some `xxx' comments.
[gnupg2.git] / common / strlist.c
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 it and/or modify it
8  * 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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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 }