list.c revision 12458b28
1/*
2  Copyright (c) 2002-2003 by Juliusz Chroboczek
3
4  Permission is hereby granted, free of charge, to any person obtaining a copy
5  of this software and associated documentation files (the "Software"), to deal
6  in the Software without restriction, including without limitation the rights
7  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  copies of the Software, and to permit persons to whom the Software is
9  furnished to do so, subject to the following conditions:
10
11  The above copyright notice and this permission notice shall be included in
12  all copies or substantial portions of the Software.
13
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  THE SOFTWARE.
21*/
22
23#include "config.h"
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <stdarg.h>
28#include <string.h>
29#include "list.h"
30
31int
32listMember(const char *elt, ListPtr list)
33{
34    while(list != NULL) {
35        if(strcmp(elt, list->value) == 0)
36            return 1;
37        list = list->next;
38    }
39    return 0;
40}
41
42ListPtr
43listCons(char *car, ListPtr cdr)
44{
45    ListPtr lcar = malloc(sizeof(ListRec));
46    if(!lcar)
47        return NULL;
48    lcar -> value = car;
49    lcar -> next = cdr;
50    return lcar;
51}
52
53ListPtr
54listAdjoin(char *car, ListPtr cdr)
55{
56    if(listMember(car, cdr)) {
57        free(car);
58        return cdr;
59    }
60    return listCons(car, cdr);
61}
62
63char *
64dsprintf(const char *f, ...)
65{
66    va_list args;
67    char *string;
68#ifdef HAVE_VASPRINTF
69    va_start(args, f);
70    if (vasprintf(&string, f, args) == -1)
71        string = NULL;
72    va_end(args);
73    return string;
74#else
75    {
76	int n, size = 20;
77	while(1) {
78	    if(size > 4096)
79		return NULL;
80	    string = malloc(size);
81	    if(!string)
82		return NULL;
83	    va_start(args, f);
84	    n = vsnprintf(string, size, f, args);
85	    va_end(args);
86	    if(n >= 0 && n < size)
87                return string;
88	    else if(n >= size)
89		size = n + 1;
90	    else
91		size = size * 3 / 2 + 1;
92	    free(string);
93	}
94    }
95#endif
96}
97
98
99ListPtr
100listConsF(ListPtr cdr, const char *f, ...)
101{
102    va_list args;
103    char *string;
104    {
105	int n, size = 20;
106	while(1) {
107	    if(size > 4096)
108		return NULL;
109	    string = malloc(size);
110	    if(!string)
111		return NULL;
112	    va_start(args, f);
113	    n = vsnprintf(string, size, f, args);
114	    va_end(args);
115	    if(n >= 0 && n < size)
116		return listCons(string, cdr);
117	    else if(n >= size)
118		size = n + 1;
119	    else
120		size = size * 3 / 2 + 1;
121	    free(string);
122	}
123    }
124}
125
126ListPtr
127listAdjoinF(ListPtr cdr, const char *f, ...)
128{
129    va_list args;
130    char *string;
131    {
132	int n, size = 20;
133	while(1) {
134	    if(size > 4096)
135		return NULL;
136	    string = malloc(size);
137	    if(!string)
138		return NULL;
139	    va_start(args, f);
140	    n = vsnprintf(string, size, f, args);
141	    va_end(args);
142	    if(n >= 0 && n < size)
143		return listAdjoin(string, cdr);
144	    else if(n >= size)
145		size = n + 1;
146	    else
147		size = size * 3 / 2 + 1;
148	    free(string);
149	}
150    }
151}
152
153int
154listLength(ListPtr list)
155{
156    int n = 0;
157    while(list) {
158        n++;
159        list = list->next;
160    }
161    return n;
162}
163
164ListPtr
165appendList(ListPtr first, ListPtr second)
166{
167    ListPtr current;
168
169    if(second == NULL)
170        return first;
171
172    if(first == NULL)
173        return second;
174
175    for(current = first; current->next; current = current->next)
176        ;
177
178    current->next = second;
179    return first;
180}
181
182ListPtr
183makeList(char **a, int n, ListPtr old, int begin)
184{
185    ListPtr first, current, next;
186    int i;
187
188    if(n == 0)
189        return old;
190
191    first = malloc(sizeof(ListRec));
192    if(!first)
193        return NULL;
194
195    first->value = a[0];
196    first->next = NULL;
197
198    current = first;
199    for(i = 1; i < n; i++) {
200        next = malloc(sizeof(ListRec));
201        if(!next) {
202            destroyList(first);
203            return NULL;
204        }
205        next->value = a[i];
206        next->next = NULL;
207
208        current->next = next;
209        current = next;
210    }
211    if(begin) {
212        current->next = old;
213        return first;
214    } else {
215        return appendList(old, first);
216    }
217}
218
219ListPtr
220reverseList(ListPtr old)
221{
222    ListPtr new = NULL, current;
223    while(old) {
224        current = old;
225        old = old->next;
226        current->next = new;
227        new = current;
228    }
229    return new;
230}
231
232/* qsort helper for sorting list entries */
233static int
234compareListEntries(const void *a, const void *b)
235{
236    const ListPtr lista = *(const ListPtr *) a;
237    const ListPtr listb = *(const ListPtr *) b;
238
239    return strcmp(lista->value, listb->value);
240}
241
242ListPtr
243sortList(ListPtr old)
244{
245    int i;
246    int l = listLength(old);
247    ListPtr n;
248    ListPtr *sorted;
249
250    if (l <= 0)
251        return old;
252
253    sorted = malloc(l * sizeof(ListPtr));
254
255    if (sorted == NULL)
256        return old;
257
258    for (n = old, i = 0; n != NULL; n = n->next) {
259        sorted[i++] = n;
260    }
261    qsort(sorted, i, sizeof(ListPtr), compareListEntries);
262    n = sorted[0];
263    for (i = 0; i < (l - 1); i++) {
264        sorted[i]->next = sorted[i+1];
265    }
266    sorted[i]->next = NULL;
267    free(sorted);
268    return n;
269}
270
271void
272destroyList(ListPtr old)
273{
274    ListPtr next;
275    if(!old)
276        return;
277    while(old) {
278        next = old->next;
279        free(old);
280        old = next;
281    }
282}
283
284void
285deepDestroyList(ListPtr old)
286{
287    ListPtr next;
288    if(!old)
289        return;
290    while(old) {
291        next = old->next;
292        free(old->value);
293        free(old);
294        old = next;
295    }
296}
297