list.c revision 8b165ca7
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
238b165ca7Smrg#ifdef HAVE_CONFIG_H
2412458b28Smrg#include "config.h"
258b165ca7Smrg#endif
2612458b28Smrg
27ea6ae205Smrg#include <stdlib.h>
28ea6ae205Smrg#include <stdio.h>
29ea6ae205Smrg#include <stdarg.h>
30ea6ae205Smrg#include <string.h>
31ea6ae205Smrg#include "list.h"
32ea6ae205Smrg
33ea6ae205Smrgint
34663cdc11SmrglistMember(const char *elt, ListPtr list)
35ea6ae205Smrg{
36ea6ae205Smrg    while(list != NULL) {
37ea6ae205Smrg        if(strcmp(elt, list->value) == 0)
38ea6ae205Smrg            return 1;
39ea6ae205Smrg        list = list->next;
40ea6ae205Smrg    }
41ea6ae205Smrg    return 0;
42ea6ae205Smrg}
43ea6ae205Smrg
44ea6ae205SmrgListPtr
45ea6ae205SmrglistCons(char *car, ListPtr cdr)
46ea6ae205Smrg{
47ea6ae205Smrg    ListPtr lcar = malloc(sizeof(ListRec));
48ea6ae205Smrg    if(!lcar)
49ea6ae205Smrg        return NULL;
50ea6ae205Smrg    lcar -> value = car;
51ea6ae205Smrg    lcar -> next = cdr;
52ea6ae205Smrg    return lcar;
53ea6ae205Smrg}
54ea6ae205Smrg
55ea6ae205SmrgListPtr
56ea6ae205SmrglistAdjoin(char *car, ListPtr cdr)
57ea6ae205Smrg{
58ea6ae205Smrg    if(listMember(car, cdr)) {
59ea6ae205Smrg        free(car);
60ea6ae205Smrg        return cdr;
61ea6ae205Smrg    }
62ea6ae205Smrg    return listCons(car, cdr);
63ea6ae205Smrg}
64ea6ae205Smrg
65ea6ae205Smrgchar *
66663cdc11Smrgdsprintf(const char *f, ...)
67ea6ae205Smrg{
68ea6ae205Smrg    va_list args;
69ea6ae205Smrg    char *string;
7012458b28Smrg#ifdef HAVE_VASPRINTF
7112458b28Smrg    va_start(args, f);
7212458b28Smrg    if (vasprintf(&string, f, args) == -1)
7312458b28Smrg        string = NULL;
7412458b28Smrg    va_end(args);
7512458b28Smrg    return string;
7612458b28Smrg#else
77ea6ae205Smrg    {
78ea6ae205Smrg	int n, size = 20;
79ea6ae205Smrg	while(1) {
80ea6ae205Smrg	    if(size > 4096)
81ea6ae205Smrg		return NULL;
82ea6ae205Smrg	    string = malloc(size);
83ea6ae205Smrg	    if(!string)
84ea6ae205Smrg		return NULL;
85ea6ae205Smrg	    va_start(args, f);
86ea6ae205Smrg	    n = vsnprintf(string, size, f, args);
87ea6ae205Smrg	    va_end(args);
88ea6ae205Smrg	    if(n >= 0 && n < size)
89ea6ae205Smrg                return string;
90ea6ae205Smrg	    else if(n >= size)
91ea6ae205Smrg		size = n + 1;
92ea6ae205Smrg	    else
93ea6ae205Smrg		size = size * 3 / 2 + 1;
94ea6ae205Smrg	    free(string);
95ea6ae205Smrg	}
96ea6ae205Smrg    }
9712458b28Smrg#endif
98ea6ae205Smrg}
99663cdc11Smrg
100ea6ae205Smrg
101ea6ae205SmrgListPtr
102663cdc11SmrglistConsF(ListPtr cdr, const char *f, ...)
103ea6ae205Smrg{
104ea6ae205Smrg    va_list args;
105ea6ae205Smrg    char *string;
106ea6ae205Smrg    {
107ea6ae205Smrg	int n, size = 20;
108ea6ae205Smrg	while(1) {
109ea6ae205Smrg	    if(size > 4096)
110ea6ae205Smrg		return NULL;
111ea6ae205Smrg	    string = malloc(size);
112ea6ae205Smrg	    if(!string)
113ea6ae205Smrg		return NULL;
114ea6ae205Smrg	    va_start(args, f);
115ea6ae205Smrg	    n = vsnprintf(string, size, f, args);
116ea6ae205Smrg	    va_end(args);
117ea6ae205Smrg	    if(n >= 0 && n < size)
118ea6ae205Smrg		return listCons(string, cdr);
119ea6ae205Smrg	    else if(n >= size)
120ea6ae205Smrg		size = n + 1;
121ea6ae205Smrg	    else
122ea6ae205Smrg		size = size * 3 / 2 + 1;
123ea6ae205Smrg	    free(string);
124ea6ae205Smrg	}
125ea6ae205Smrg    }
126ea6ae205Smrg}
127ea6ae205Smrg
128ea6ae205SmrgListPtr
129663cdc11SmrglistAdjoinF(ListPtr cdr, const char *f, ...)
130ea6ae205Smrg{
131ea6ae205Smrg    va_list args;
132ea6ae205Smrg    char *string;
133ea6ae205Smrg    {
134ea6ae205Smrg	int n, size = 20;
135ea6ae205Smrg	while(1) {
136ea6ae205Smrg	    if(size > 4096)
137ea6ae205Smrg		return NULL;
138ea6ae205Smrg	    string = malloc(size);
139ea6ae205Smrg	    if(!string)
140ea6ae205Smrg		return NULL;
141ea6ae205Smrg	    va_start(args, f);
142ea6ae205Smrg	    n = vsnprintf(string, size, f, args);
143ea6ae205Smrg	    va_end(args);
144ea6ae205Smrg	    if(n >= 0 && n < size)
145ea6ae205Smrg		return listAdjoin(string, cdr);
146ea6ae205Smrg	    else if(n >= size)
147ea6ae205Smrg		size = n + 1;
148ea6ae205Smrg	    else
149ea6ae205Smrg		size = size * 3 / 2 + 1;
150ea6ae205Smrg	    free(string);
151ea6ae205Smrg	}
152ea6ae205Smrg    }
153ea6ae205Smrg}
154ea6ae205Smrg
155ea6ae205Smrgint
156ea6ae205SmrglistLength(ListPtr list)
157ea6ae205Smrg{
158ea6ae205Smrg    int n = 0;
159ea6ae205Smrg    while(list) {
160ea6ae205Smrg        n++;
161ea6ae205Smrg        list = list->next;
162ea6ae205Smrg    }
163ea6ae205Smrg    return n;
164ea6ae205Smrg}
165ea6ae205Smrg
166663cdc11SmrgListPtr
167ea6ae205SmrgappendList(ListPtr first, ListPtr second)
168ea6ae205Smrg{
169ea6ae205Smrg    ListPtr current;
170ea6ae205Smrg
171ea6ae205Smrg    if(second == NULL)
172ea6ae205Smrg        return first;
173ea6ae205Smrg
174ea6ae205Smrg    if(first == NULL)
175ea6ae205Smrg        return second;
176ea6ae205Smrg
177ea6ae205Smrg    for(current = first; current->next; current = current->next)
178ea6ae205Smrg        ;
179ea6ae205Smrg
180ea6ae205Smrg    current->next = second;
181ea6ae205Smrg    return first;
182ea6ae205Smrg}
183ea6ae205Smrg
184ea6ae205SmrgListPtr
185ea6ae205SmrgmakeList(char **a, int n, ListPtr old, int begin)
186ea6ae205Smrg{
187ea6ae205Smrg    ListPtr first, current, next;
188ea6ae205Smrg    int i;
189ea6ae205Smrg
190ea6ae205Smrg    if(n == 0)
191ea6ae205Smrg        return old;
192ea6ae205Smrg
193ea6ae205Smrg    first = malloc(sizeof(ListRec));
194ea6ae205Smrg    if(!first)
195ea6ae205Smrg        return NULL;
196ea6ae205Smrg
197ea6ae205Smrg    first->value = a[0];
198ea6ae205Smrg    first->next = NULL;
199ea6ae205Smrg
200ea6ae205Smrg    current = first;
201ea6ae205Smrg    for(i = 1; i < n; i++) {
202ea6ae205Smrg        next = malloc(sizeof(ListRec));
203245f6787Smrg        if(!next) {
204245f6787Smrg            destroyList(first);
205ea6ae205Smrg            return NULL;
206245f6787Smrg        }
207ea6ae205Smrg        next->value = a[i];
208ea6ae205Smrg        next->next = NULL;
209ea6ae205Smrg
210ea6ae205Smrg        current->next = next;
211ea6ae205Smrg        current = next;
212ea6ae205Smrg    }
213ea6ae205Smrg    if(begin) {
214ea6ae205Smrg        current->next = old;
215ea6ae205Smrg        return first;
216ea6ae205Smrg    } else {
217ea6ae205Smrg        return appendList(old, first);
218ea6ae205Smrg    }
219ea6ae205Smrg}
220ea6ae205Smrg
221ea6ae205SmrgListPtr
222ea6ae205SmrgreverseList(ListPtr old)
223ea6ae205Smrg{
224ea6ae205Smrg    ListPtr new = NULL, current;
225ea6ae205Smrg    while(old) {
226ea6ae205Smrg        current = old;
227ea6ae205Smrg        old = old->next;
228ea6ae205Smrg        current->next = new;
229ea6ae205Smrg        new = current;
230ea6ae205Smrg    }
231ea6ae205Smrg    return new;
232ea6ae205Smrg}
233ea6ae205Smrg
234245f6787Smrg/* qsort helper for sorting list entries */
235245f6787Smrgstatic int
236245f6787SmrgcompareListEntries(const void *a, const void *b)
237245f6787Smrg{
238245f6787Smrg    const ListPtr lista = *(const ListPtr *) a;
239245f6787Smrg    const ListPtr listb = *(const ListPtr *) b;
240245f6787Smrg
241245f6787Smrg    return strcmp(lista->value, listb->value);
242245f6787Smrg}
243245f6787Smrg
244245f6787SmrgListPtr
245245f6787SmrgsortList(ListPtr old)
246245f6787Smrg{
247245f6787Smrg    int i;
248245f6787Smrg    int l = listLength(old);
249245f6787Smrg    ListPtr n;
25048f45e26Smrg    ListPtr *sorted;
25148f45e26Smrg
25248f45e26Smrg    if (l <= 0)
25348f45e26Smrg        return old;
25448f45e26Smrg
25548f45e26Smrg    sorted = malloc(l * sizeof(ListPtr));
256245f6787Smrg
257245f6787Smrg    if (sorted == NULL)
258245f6787Smrg        return old;
259245f6787Smrg
260245f6787Smrg    for (n = old, i = 0; n != NULL; n = n->next) {
261245f6787Smrg        sorted[i++] = n;
262245f6787Smrg    }
263245f6787Smrg    qsort(sorted, i, sizeof(ListPtr), compareListEntries);
264245f6787Smrg    n = sorted[0];
265245f6787Smrg    for (i = 0; i < (l - 1); i++) {
266245f6787Smrg        sorted[i]->next = sorted[i+1];
267245f6787Smrg    }
268245f6787Smrg    sorted[i]->next = NULL;
269245f6787Smrg    free(sorted);
270245f6787Smrg    return n;
271245f6787Smrg}
272245f6787Smrg
273ea6ae205Smrgvoid
274ea6ae205SmrgdestroyList(ListPtr old)
275ea6ae205Smrg{
276ea6ae205Smrg    ListPtr next;
277ea6ae205Smrg    if(!old)
278ea6ae205Smrg        return;
279ea6ae205Smrg    while(old) {
280ea6ae205Smrg        next = old->next;
281ea6ae205Smrg        free(old);
282ea6ae205Smrg        old = next;
283ea6ae205Smrg    }
284ea6ae205Smrg}
285ea6ae205Smrg
286ea6ae205Smrgvoid
287ea6ae205SmrgdeepDestroyList(ListPtr old)
288ea6ae205Smrg{
289ea6ae205Smrg    ListPtr next;
290ea6ae205Smrg    if(!old)
291ea6ae205Smrg        return;
292ea6ae205Smrg    while(old) {
293ea6ae205Smrg        next = old->next;
294ea6ae205Smrg        free(old->value);
295ea6ae205Smrg        free(old);
296ea6ae205Smrg        old = next;
297ea6ae205Smrg    }
298ea6ae205Smrg}
299