list.c revision 245f6787
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
23ea6ae205Smrg#include <stdlib.h>
24ea6ae205Smrg#include <stdio.h>
25ea6ae205Smrg#include <stdarg.h>
26ea6ae205Smrg#include <string.h>
27ea6ae205Smrg#include "list.h"
28ea6ae205Smrg
29ea6ae205Smrgint
30ea6ae205SmrglistMember(char *elt, ListPtr list)
31ea6ae205Smrg{
32ea6ae205Smrg    while(list != NULL) {
33ea6ae205Smrg        if(strcmp(elt, list->value) == 0)
34ea6ae205Smrg            return 1;
35ea6ae205Smrg        list = list->next;
36ea6ae205Smrg    }
37ea6ae205Smrg    return 0;
38ea6ae205Smrg}
39ea6ae205Smrg
40ea6ae205SmrgListPtr
41ea6ae205SmrglistCons(char *car, ListPtr cdr)
42ea6ae205Smrg{
43ea6ae205Smrg    ListPtr lcar = malloc(sizeof(ListRec));
44ea6ae205Smrg    if(!lcar)
45ea6ae205Smrg        return NULL;
46ea6ae205Smrg    lcar -> value = car;
47ea6ae205Smrg    lcar -> next = cdr;
48ea6ae205Smrg    return lcar;
49ea6ae205Smrg}
50ea6ae205Smrg
51ea6ae205SmrgListPtr
52ea6ae205SmrglistAdjoin(char *car, ListPtr cdr)
53ea6ae205Smrg{
54ea6ae205Smrg    if(listMember(car, cdr)) {
55ea6ae205Smrg        free(car);
56ea6ae205Smrg        return cdr;
57ea6ae205Smrg    }
58ea6ae205Smrg    return listCons(car, cdr);
59ea6ae205Smrg}
60ea6ae205Smrg
61ea6ae205Smrgchar *
62ea6ae205Smrgdsprintf(char *f, ...)
63ea6ae205Smrg{
64ea6ae205Smrg    va_list args;
65ea6ae205Smrg    char *string;
66ea6ae205Smrg    {
67ea6ae205Smrg	int n, size = 20;
68ea6ae205Smrg	while(1) {
69ea6ae205Smrg	    if(size > 4096)
70ea6ae205Smrg		return NULL;
71ea6ae205Smrg	    string = malloc(size);
72ea6ae205Smrg	    if(!string)
73ea6ae205Smrg		return NULL;
74ea6ae205Smrg	    va_start(args, f);
75ea6ae205Smrg	    n = vsnprintf(string, size, f, args);
76ea6ae205Smrg	    va_end(args);
77ea6ae205Smrg	    if(n >= 0 && n < size)
78ea6ae205Smrg                return string;
79ea6ae205Smrg	    else if(n >= size)
80ea6ae205Smrg		size = n + 1;
81ea6ae205Smrg	    else
82ea6ae205Smrg		size = size * 3 / 2 + 1;
83ea6ae205Smrg	    free(string);
84ea6ae205Smrg	}
85ea6ae205Smrg    }
86ea6ae205Smrg}
87ea6ae205Smrg
88ea6ae205Smrg
89ea6ae205SmrgListPtr
90ea6ae205SmrglistConsF(ListPtr cdr, char *f, ...)
91ea6ae205Smrg{
92ea6ae205Smrg    va_list args;
93ea6ae205Smrg    char *string;
94ea6ae205Smrg    {
95ea6ae205Smrg	int n, size = 20;
96ea6ae205Smrg	while(1) {
97ea6ae205Smrg	    if(size > 4096)
98ea6ae205Smrg		return NULL;
99ea6ae205Smrg	    string = malloc(size);
100ea6ae205Smrg	    if(!string)
101ea6ae205Smrg		return NULL;
102ea6ae205Smrg	    va_start(args, f);
103ea6ae205Smrg	    n = vsnprintf(string, size, f, args);
104ea6ae205Smrg	    va_end(args);
105ea6ae205Smrg	    if(n >= 0 && n < size)
106ea6ae205Smrg		return listCons(string, cdr);
107ea6ae205Smrg	    else if(n >= size)
108ea6ae205Smrg		size = n + 1;
109ea6ae205Smrg	    else
110ea6ae205Smrg		size = size * 3 / 2 + 1;
111ea6ae205Smrg	    free(string);
112ea6ae205Smrg	}
113ea6ae205Smrg    }
114ea6ae205Smrg}
115ea6ae205Smrg
116ea6ae205SmrgListPtr
117ea6ae205SmrglistAdjoinF(ListPtr cdr, char *f, ...)
118ea6ae205Smrg{
119ea6ae205Smrg    va_list args;
120ea6ae205Smrg    char *string;
121ea6ae205Smrg    {
122ea6ae205Smrg	int n, size = 20;
123ea6ae205Smrg	while(1) {
124ea6ae205Smrg	    if(size > 4096)
125ea6ae205Smrg		return NULL;
126ea6ae205Smrg	    string = malloc(size);
127ea6ae205Smrg	    if(!string)
128ea6ae205Smrg		return NULL;
129ea6ae205Smrg	    va_start(args, f);
130ea6ae205Smrg	    n = vsnprintf(string, size, f, args);
131ea6ae205Smrg	    va_end(args);
132ea6ae205Smrg	    if(n >= 0 && n < size)
133ea6ae205Smrg		return listAdjoin(string, cdr);
134ea6ae205Smrg	    else if(n >= size)
135ea6ae205Smrg		size = n + 1;
136ea6ae205Smrg	    else
137ea6ae205Smrg		size = size * 3 / 2 + 1;
138ea6ae205Smrg	    free(string);
139ea6ae205Smrg	}
140ea6ae205Smrg    }
141ea6ae205Smrg}
142ea6ae205Smrg
143ea6ae205Smrgint
144ea6ae205SmrglistLength(ListPtr list)
145ea6ae205Smrg{
146ea6ae205Smrg    int n = 0;
147ea6ae205Smrg    while(list) {
148ea6ae205Smrg        n++;
149ea6ae205Smrg        list = list->next;
150ea6ae205Smrg    }
151ea6ae205Smrg    return n;
152ea6ae205Smrg}
153ea6ae205Smrg
154ea6ae205SmrgListPtr
155ea6ae205SmrgappendList(ListPtr first, ListPtr second)
156ea6ae205Smrg{
157ea6ae205Smrg    ListPtr current;
158ea6ae205Smrg
159ea6ae205Smrg    if(second == NULL)
160ea6ae205Smrg        return first;
161ea6ae205Smrg
162ea6ae205Smrg    if(first == NULL)
163ea6ae205Smrg        return second;
164ea6ae205Smrg
165ea6ae205Smrg    for(current = first; current->next; current = current->next)
166ea6ae205Smrg        ;
167ea6ae205Smrg
168ea6ae205Smrg    current->next = second;
169ea6ae205Smrg    return first;
170ea6ae205Smrg}
171ea6ae205Smrg
172ea6ae205SmrgListPtr
173ea6ae205SmrgmakeList(char **a, int n, ListPtr old, int begin)
174ea6ae205Smrg{
175ea6ae205Smrg    ListPtr first, current, next;
176ea6ae205Smrg    int i;
177ea6ae205Smrg
178ea6ae205Smrg    if(n == 0)
179ea6ae205Smrg        return old;
180ea6ae205Smrg
181ea6ae205Smrg    first = malloc(sizeof(ListRec));
182ea6ae205Smrg    if(!first)
183ea6ae205Smrg        return NULL;
184ea6ae205Smrg
185ea6ae205Smrg    first->value = a[0];
186ea6ae205Smrg    first->next = NULL;
187ea6ae205Smrg
188ea6ae205Smrg    current = first;
189ea6ae205Smrg    for(i = 1; i < n; i++) {
190ea6ae205Smrg        next = malloc(sizeof(ListRec));
191245f6787Smrg        if(!next) {
192245f6787Smrg            destroyList(first);
193ea6ae205Smrg            return NULL;
194245f6787Smrg        }
195ea6ae205Smrg        next->value = a[i];
196ea6ae205Smrg        next->next = NULL;
197ea6ae205Smrg
198ea6ae205Smrg        current->next = next;
199ea6ae205Smrg        current = next;
200ea6ae205Smrg    }
201ea6ae205Smrg    if(begin) {
202ea6ae205Smrg        current->next = old;
203ea6ae205Smrg        return first;
204ea6ae205Smrg    } else {
205ea6ae205Smrg        return appendList(old, first);
206ea6ae205Smrg    }
207ea6ae205Smrg}
208ea6ae205Smrg
209ea6ae205SmrgListPtr
210ea6ae205SmrgreverseList(ListPtr old)
211ea6ae205Smrg{
212ea6ae205Smrg    ListPtr new = NULL, current;
213ea6ae205Smrg    while(old) {
214ea6ae205Smrg        current = old;
215ea6ae205Smrg        old = old->next;
216ea6ae205Smrg        current->next = new;
217ea6ae205Smrg        new = current;
218ea6ae205Smrg    }
219ea6ae205Smrg    return new;
220ea6ae205Smrg}
221ea6ae205Smrg
222245f6787Smrg/* qsort helper for sorting list entries */
223245f6787Smrgstatic int
224245f6787SmrgcompareListEntries(const void *a, const void *b)
225245f6787Smrg{
226245f6787Smrg    const ListPtr lista = *(const ListPtr *) a;
227245f6787Smrg    const ListPtr listb = *(const ListPtr *) b;
228245f6787Smrg
229245f6787Smrg    return strcmp(lista->value, listb->value);
230245f6787Smrg}
231245f6787Smrg
232245f6787SmrgListPtr
233245f6787SmrgsortList(ListPtr old)
234245f6787Smrg{
235245f6787Smrg    int i;
236245f6787Smrg    int l = listLength(old);
237245f6787Smrg    ListPtr n;
238245f6787Smrg    ListPtr *sorted = malloc(l * sizeof(ListPtr));
239245f6787Smrg
240245f6787Smrg    if (sorted == NULL)
241245f6787Smrg        return old;
242245f6787Smrg
243245f6787Smrg    for (n = old, i = 0; n != NULL; n = n->next) {
244245f6787Smrg        sorted[i++] = n;
245245f6787Smrg    }
246245f6787Smrg    qsort(sorted, i, sizeof(ListPtr), compareListEntries);
247245f6787Smrg    n = sorted[0];
248245f6787Smrg    for (i = 0; i < (l - 1); i++) {
249245f6787Smrg        sorted[i]->next = sorted[i+1];
250245f6787Smrg    }
251245f6787Smrg    sorted[i]->next = NULL;
252245f6787Smrg    free(sorted);
253245f6787Smrg    return n;
254245f6787Smrg}
255245f6787Smrg
256ea6ae205Smrgvoid
257ea6ae205SmrgdestroyList(ListPtr old)
258ea6ae205Smrg{
259ea6ae205Smrg    ListPtr next;
260ea6ae205Smrg    if(!old)
261ea6ae205Smrg        return;
262ea6ae205Smrg    while(old) {
263ea6ae205Smrg        next = old->next;
264ea6ae205Smrg        free(old);
265ea6ae205Smrg        old = next;
266ea6ae205Smrg    }
267ea6ae205Smrg}
268ea6ae205Smrg
269ea6ae205Smrgvoid
270ea6ae205SmrgdeepDestroyList(ListPtr old)
271ea6ae205Smrg{
272ea6ae205Smrg    ListPtr next;
273ea6ae205Smrg    if(!old)
274ea6ae205Smrg        return;
275ea6ae205Smrg    while(old) {
276ea6ae205Smrg        next = old->next;
277ea6ae205Smrg        free(old->value);
278ea6ae205Smrg        free(old);
279ea6ae205Smrg        old = next;
280ea6ae205Smrg    }
281ea6ae205Smrg}
282