common: Add 'append_to_strlist_try' which can fail.
[gnupg.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 <http://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
43 void
44 free_strlist( strlist_t sl )
45 {
46     strlist_t sl2;
47
48     for(; sl; sl = sl2 ) {
49         sl2 = sl->next;
50         xfree(sl);
51     }
52 }
53
54
55 /* Add STRING to the LIST at the front.  This function terminates the
56    process on memory shortage.  */
57 strlist_t
58 add_to_strlist( strlist_t *list, const char *string )
59 {
60     strlist_t sl;
61
62     sl = xmalloc( sizeof *sl + strlen(string));
63     sl->flags = 0;
64     strcpy(sl->d, string);
65     sl->next = *list;
66     *list = sl;
67     return sl;
68 }
69
70
71 /* Add STRING to the LIST at the front.  This function returns NULL
72    and sets ERRNO on memory shortage.  */
73 strlist_t
74 add_to_strlist_try (strlist_t *list, const char *string)
75 {
76   strlist_t sl;
77
78   sl = xtrymalloc (sizeof *sl + strlen (string));
79   if (sl)
80     {
81       sl->flags = 0;
82       strcpy (sl->d, string);
83       sl->next = *list;
84       *list = sl;
85     }
86   return sl;
87 }
88
89
90 /* Same as add_to_strlist() but if IS_UTF8 is *not* set, a conversion
91    to UTF-8 is done.  This function terminates the process on memory
92    shortage.  */
93 strlist_t
94 add_to_strlist2( strlist_t *list, const char *string, int is_utf8 )
95 {
96   strlist_t sl;
97
98   if (is_utf8)
99     sl = add_to_strlist( list, string );
100   else
101     {
102       char *p = native_to_utf8( string );
103       sl = add_to_strlist( list, p );
104       xfree ( p );
105     }
106   return sl;
107 }
108
109
110 /* Add STRING to the LIST at the end.  This function terminates the
111    process on memory shortage.  */
112 strlist_t
113 append_to_strlist( strlist_t *list, const char *string )
114 {
115   strlist_t sl;
116   sl = append_to_strlist_try (list, string);
117   if (sl == NULL)
118     abort ();
119   return sl;
120 }
121
122
123 /* Add STRING to the LIST at the end.  */
124 strlist_t
125 append_to_strlist_try (strlist_t *list, const char *string)
126 {
127     strlist_t r, sl;
128
129     sl = xmalloc( sizeof *sl + strlen(string));
130     if (sl == NULL)
131       return NULL;
132
133     sl->flags = 0;
134     strcpy(sl->d, string);
135     sl->next = NULL;
136     if( !*list )
137         *list = sl;
138     else {
139         for( r = *list; r->next; r = r->next )
140             ;
141         r->next = sl;
142     }
143     return sl;
144 }
145
146
147 strlist_t
148 append_to_strlist2( strlist_t *list, const char *string, int is_utf8 )
149 {
150   strlist_t sl;
151
152   if( is_utf8 )
153     sl = append_to_strlist( list, string );
154   else
155     {
156       char *p = native_to_utf8 (string);
157       sl = append_to_strlist( list, p );
158       xfree( p );
159     }
160   return sl;
161 }
162
163
164 /* Return a copy of LIST.  This function terminates the process on
165    memory shortage.*/
166 strlist_t
167 strlist_copy (strlist_t list)
168 {
169   strlist_t newlist = NULL, sl, *last;
170
171   last = &newlist;
172   for (; list; list = list->next)
173     {
174       sl = xmalloc (sizeof *sl + strlen (list->d));
175       sl->flags = list->flags;
176       strcpy(sl->d, list->d);
177       sl->next = NULL;
178       *last = sl;
179       last = &sl;
180     }
181   return newlist;
182 }
183
184
185
186 strlist_t
187 strlist_prev( strlist_t head, strlist_t node )
188 {
189     strlist_t n;
190
191     for(n=NULL; head && head != node; head = head->next )
192         n = head;
193     return n;
194 }
195
196 strlist_t
197 strlist_last( strlist_t node )
198 {
199     if( node )
200         for( ; node->next ; node = node->next )
201             ;
202     return node;
203 }
204
205
206 /* Remove the first item from LIST and return its content in an
207    allocated buffer.  This function terminates the process on memory
208    shortage.  */
209 char *
210 strlist_pop (strlist_t *list)
211 {
212   char *str=NULL;
213   strlist_t sl=*list;
214
215   if(sl)
216     {
217       str = xmalloc(strlen(sl->d)+1);
218       strcpy(str,sl->d);
219
220       *list=sl->next;
221       xfree(sl);
222     }
223
224   return str;
225 }
226
227 /* Return the first element of the string list HAYSTACK whose string
228    matches NEEDLE.  If no elements match, return NULL.  */
229 strlist_t
230 strlist_find (strlist_t haystack, const char *needle)
231 {
232   for (;
233        haystack;
234        haystack = haystack->next)
235     if (strcmp (haystack->d, needle) == 0)
236       return haystack;
237   return NULL;
238 }
239
240 int
241 strlist_length (strlist_t list)
242 {
243   int i;
244   for (i = 0; list; list = list->next)
245     i ++;
246
247   return i;
248 }
249
250 /* Reverse the list *LIST in place.  */
251 strlist_t
252 strlist_rev (strlist_t *list)
253 {
254   strlist_t l = *list;
255   strlist_t lrev = NULL;
256
257   while (l)
258     {
259       strlist_t tail = l->next;
260       l->next = lrev;
261       lrev = l;
262       l = tail;
263     }
264
265   *list = lrev;
266   return lrev;
267 }