list.c revision 12458b28
1ea6ae205Smrg/*
2ea6ae205Smrg  Copyright (c) 2002-2003 by Juliusz Chroboczek
3ea6ae205Smrg
4ea6ae205Smrg  Permission is hereby granted, free of charge, to any person obtaining a copy
5ea6ae205Smrg  of this software and associated documentation files (the "Software"), to deal
6ea6ae205Smrg  in the Software without restriction, including without limitation the rights
7ea6ae205Smrg  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8ea6ae205Smrg  copies of the Software, and to permit persons to whom the Software is
9ea6ae205Smrg  furnished to do so, subject to the following conditions:
10ea6ae205Smrg
11ea6ae205Smrg  The above copyright notice and this permission notice shall be included in
12ea6ae205Smrg  all copies or substantial portions of the Software.
13ea6ae205Smrg
14ea6ae205Smrg  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15ea6ae205Smrg  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16ea6ae205Smrg  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17ea6ae205Smrg  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18ea6ae205Smrg  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19ea6ae205Smrg  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20ea6ae205Smrg  THE SOFTWARE.
21ea6ae205Smrg*/
22ea6ae205Smrg
2312458b28Smrg#include "config.h"
2412458b28Smrg
25ea6ae205Smrg#include <stdlib.h>
26ea6ae205Smrg#include <stdio.h>
27ea6ae205Smrg#include <stdarg.h>
28ea6ae205Smrg#include <string.h>
29ea6ae205Smrg#include "list.h"
30ea6ae205Smrg
31ea6ae205Smrgint
32663cdc11SmrglistMember(const char *elt, ListPtr list)
33ea6ae205Smrg{
34ea6ae205Smrg    while(list != NULL) {
35ea6ae205Smrg        if(strcmp(elt, list->value) == 0)
36ea6ae205Smrg            return 1;
37ea6ae205Smrg        list = list->next;
38ea6ae205Smrg    }
39ea6ae205Smrg    return 0;
40ea6ae205Smrg}
41ea6ae205Smrg
42ea6ae205SmrgListPtr
43ea6ae205SmrglistCons(char *car, ListPtr cdr)
44ea6ae205Smrg{
45ea6ae205Smrg    ListPtr lcar = malloc(sizeof(ListRec));
46ea6ae205Smrg    if(!lcar)
47ea6ae205Smrg        return NULL;
48ea6ae205Smrg    lcar -> value = car;
49ea6ae205Smrg    lcar -> next = cdr;
50ea6ae205Smrg    return lcar;
51ea6ae205Smrg}
52ea6ae205Smrg
53ea6ae205SmrgListPtr
54ea6ae205SmrglistAdjoin(char *car, ListPtr cdr)
55ea6ae205Smrg{
56ea6ae205Smrg    if(listMember(car, cdr)) {
57ea6ae205Smrg        free(car);
58ea6ae205Smrg        return cdr;
59ea6ae205Smrg    }
60ea6ae205Smrg    return listCons(car, cdr);
61ea6ae205Smrg}
62ea6ae205Smrg
63ea6ae205Smrgchar *
64663cdc11Smrgdsprintf(const char *f, ...)
65ea6ae205Smrg{
66ea6ae205Smrg    va_list args;
67ea6ae205Smrg    char *string;
6812458b28Smrg#ifdef HAVE_VASPRINTF
6912458b28Smrg    va_start(args, f);
7012458b28Smrg    if (vasprintf(&string, f, args) == -1)
7112458b28Smrg        string = NULL;
7212458b28Smrg    va_end(args);
7312458b28Smrg    return string;
7412458b28Smrg#else
75ea6ae205Smrg    {
76ea6ae205Smrg	int n, size = 20;
77ea6ae205Smrg	while(1) {
78ea6ae205Smrg	    if(size > 4096)
79ea6ae205Smrg		return NULL;
80ea6ae205Smrg	    string = malloc(size);
81ea6ae205Smrg	    if(!string)
82ea6ae205Smrg		return NULL;
83ea6ae205Smrg	    va_start(args, f);
84ea6ae205Smrg	    n = vsnprintf(string, size, f, args);
85ea6ae205Smrg	    va_end(args);
86ea6ae205Smrg	    if(n >= 0 && n < size)
87ea6ae205Smrg                return string;
88ea6ae205Smrg	    else if(n >= size)
89ea6ae205Smrg		size = n + 1;
90ea6ae205Smrg	    else
91ea6ae205Smrg		size = size * 3 / 2 + 1;
92ea6ae205Smrg	    free(string);
93ea6ae205Smrg	}
94ea6ae205Smrg    }
9512458b28Smrg#endif
96ea6ae205Smrg}
97663cdc11Smrg
98ea6ae205Smrg
99ea6ae205SmrgListPtr
100663cdc11SmrglistConsF(ListPtr cdr, const char *f, ...)
101ea6ae205Smrg{
102ea6ae205Smrg    va_list args;
103ea6ae205Smrg    char *string;
104ea6ae205Smrg    {
105ea6ae205Smrg	int n, size = 20;
106ea6ae205Smrg	while(1) {
107ea6ae205Smrg	    if(size > 4096)
108ea6ae205Smrg		return NULL;
109ea6ae205Smrg	    string = malloc(size);
110ea6ae205Smrg	    if(!string)
111ea6ae205Smrg		return NULL;
112ea6ae205Smrg	    va_start(args, f);
113ea6ae205Smrg	    n = vsnprintf(string, size, f, args);
114ea6ae205Smrg	    va_end(args);
115ea6ae205Smrg	    if(n >= 0 && n < size)
116ea6ae205Smrg		return listCons(string, cdr);
117ea6ae205Smrg	    else if(n >= size)
118ea6ae205Smrg		size = n + 1;
119ea6ae205Smrg	    else
120ea6ae205Smrg		size = size * 3 / 2 + 1;
121ea6ae205Smrg	    free(string);
122ea6ae205Smrg	}
123ea6ae205Smrg    }
124ea6ae205Smrg}
125ea6ae205Smrg
126ea6ae205SmrgListPtr
127663cdc11SmrglistAdjoinF(ListPtr cdr, const char *f, ...)
128ea6ae205Smrg{
129ea6ae205Smrg    va_list args;
130ea6ae205Smrg    char *string;
131ea6ae205Smrg    {
132ea6ae205Smrg	int n, size = 20;
133ea6ae205Smrg	while(1) {
134ea6ae205Smrg	    if(size > 4096)
135ea6ae205Smrg		return NULL;
136ea6ae205Smrg	    string = malloc(size);
137ea6ae205Smrg	    if(!string)
138ea6ae205Smrg		return NULL;
139ea6ae205Smrg	    va_start(args, f);
140ea6ae205Smrg	    n = vsnprintf(string, size, f, args);
141ea6ae205Smrg	    va_end(args);
142ea6ae205Smrg	    if(n >= 0 && n < size)
143ea6ae205Smrg		return listAdjoin(string, cdr);
144ea6ae205Smrg	    else if(n >= size)
145ea6ae205Smrg		size = n + 1;
146ea6ae205Smrg	    else
147ea6ae205Smrg		size = size * 3 / 2 + 1;
148ea6ae205Smrg	    free(string);
149ea6ae205Smrg	}
150ea6ae205Smrg    }
151ea6ae205Smrg}
152ea6ae205Smrg
153ea6ae205Smrgint
154ea6ae205SmrglistLength(ListPtr list)
155ea6ae205Smrg{
156ea6ae205Smrg    int n = 0;
157ea6ae205Smrg    while(list) {
158ea6ae205Smrg        n++;
159ea6ae205Smrg        list = list->next;
160ea6ae205Smrg    }
161ea6ae205Smrg    return n;
162ea6ae205Smrg}
163ea6ae205Smrg
164663cdc11SmrgListPtr
165ea6ae205SmrgappendList(ListPtr first, ListPtr second)
166ea6ae205Smrg{
167ea6ae205Smrg    ListPtr current;
168ea6ae205Smrg
169ea6ae205Smrg    if(second == NULL)
170ea6ae205Smrg        return first;
171ea6ae205Smrg
172ea6ae205Smrg    if(first == NULL)
173ea6ae205Smrg        return second;
174ea6ae205Smrg
175ea6ae205Smrg    for(current = first; current->next; current = current->next)
176ea6ae205Smrg        ;
177ea6ae205Smrg
178ea6ae205Smrg    current->next = second;
179ea6ae205Smrg    return first;
180ea6ae205Smrg}
181ea6ae205Smrg
182ea6ae205SmrgListPtr
183ea6ae205SmrgmakeList(char **a, int n, ListPtr old, int begin)
184ea6ae205Smrg{
185ea6ae205Smrg    ListPtr first, current, next;
186ea6ae205Smrg    int i;
187ea6ae205Smrg
188ea6ae205Smrg    if(n == 0)
189ea6ae205Smrg        return old;
190ea6ae205Smrg
191ea6ae205Smrg    first = malloc(sizeof(ListRec));
192ea6ae205Smrg    if(!first)
193ea6ae205Smrg        return NULL;
194ea6ae205Smrg
195ea6ae205Smrg    first->value = a[0];
196ea6ae205Smrg    first->next = NULL;
197ea6ae205Smrg
198ea6ae205Smrg    current = first;
199ea6ae205Smrg    for(i = 1; i < n; i++) {
200ea6ae205Smrg        next = malloc(sizeof(ListRec));
201245f6787Smrg        if(!next) {
202245f6787Smrg            destroyList(first);
203ea6ae205Smrg            return NULL;
204245f6787Smrg        }
205ea6ae205Smrg        next->value = a[i];
206ea6ae205Smrg        next->next = NULL;
207ea6ae205Smrg
208ea6ae205Smrg        current->next = next;
209ea6ae205Smrg        current = next;
210ea6ae205Smrg    }
211ea6ae205Smrg    if(begin) {
212ea6ae205Smrg        current->next = old;
213ea6ae205Smrg        return first;
214ea6ae205Smrg    } else {
215ea6ae205Smrg        return appendList(old, first);
216ea6ae205Smrg    }
217ea6ae205Smrg}
218ea6ae205Smrg
219ea6ae205SmrgListPtr
220ea6ae205SmrgreverseList(ListPtr old)
221ea6ae205Smrg{
222ea6ae205Smrg    ListPtr new = NULL, current;
223ea6ae205Smrg    while(old) {
224ea6ae205Smrg        current = old;
225ea6ae205Smrg        old = old->next;
226ea6ae205Smrg        current->next = new;
227ea6ae205Smrg        new = current;
228ea6ae205Smrg    }
229ea6ae205Smrg    return new;
230ea6ae205Smrg}
231ea6ae205Smrg
232245f6787Smrg/* qsort helper for sorting list entries */
233245f6787Smrgstatic int
234245f6787SmrgcompareListEntries(const void *a, const void *b)
235245f6787Smrg{
236245f6787Smrg    const ListPtr lista = *(const ListPtr *) a;
237245f6787Smrg    const ListPtr listb = *(const ListPtr *) b;
238245f6787Smrg
239245f6787Smrg    return strcmp(lista->value, listb->value);
240245f6787Smrg}
241245f6787Smrg
242245f6787SmrgListPtr
243245f6787SmrgsortList(ListPtr old)
244245f6787Smrg{
245245f6787Smrg    int i;
246245f6787Smrg    int l = listLength(old);
247245f6787Smrg    ListPtr n;
24848f45e26Smrg    ListPtr *sorted;
24948f45e26Smrg
25048f45e26Smrg    if (l <= 0)
25148f45e26Smrg        return old;
25248f45e26Smrg
25348f45e26Smrg    sorted = malloc(l * sizeof(ListPtr));
254245f6787Smrg
255245f6787Smrg    if (sorted == NULL)
256245f6787Smrg        return old;
257245f6787Smrg
258245f6787Smrg    for (n = old, i = 0; n != NULL; n = n->next) {
259245f6787Smrg        sorted[i++] = n;
260245f6787Smrg    }
261245f6787Smrg    qsort(sorted, i, sizeof(ListPtr), compareListEntries);
262245f6787Smrg    n = sorted[0];
263245f6787Smrg    for (i = 0; i < (l - 1); i++) {
264245f6787Smrg        sorted[i]->next = sorted[i+1];
265245f6787Smrg    }
266245f6787Smrg    sorted[i]->next = NULL;
267245f6787Smrg    free(sorted);
268245f6787Smrg    return n;
269245f6787Smrg}
270245f6787Smrg
271ea6ae205Smrgvoid
272ea6ae205SmrgdestroyList(ListPtr old)
273ea6ae205Smrg{
274ea6ae205Smrg    ListPtr next;
275ea6ae205Smrg    if(!old)
276ea6ae205Smrg        return;
277ea6ae205Smrg    while(old) {
278ea6ae205Smrg        next = old->next;
279ea6ae205Smrg        free(old);
280ea6ae205Smrg        old = next;
281ea6ae205Smrg    }
282ea6ae205Smrg}
283ea6ae205Smrg
284ea6ae205Smrgvoid
285ea6ae205SmrgdeepDestroyList(ListPtr old)
286ea6ae205Smrg{
287ea6ae205Smrg    ListPtr next;
288ea6ae205Smrg    if(!old)
289ea6ae205Smrg        return;
290ea6ae205Smrg    while(old) {
291ea6ae205Smrg        next = old->next;
292ea6ae205Smrg        free(old->value);
293ea6ae205Smrg        free(old);
294ea6ae205Smrg        old = next;
295ea6ae205Smrg    }
296ea6ae205Smrg}
297