list.c revision 663cdc11
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 <stdlib.h>
24#include <stdio.h>
25#include <stdarg.h>
26#include <string.h>
27#include "list.h"
28
29int
30listMember(const char *elt, ListPtr list)
31{
32    while(list != NULL) {
33        if(strcmp(elt, list->value) == 0)
34            return 1;
35        list = list->next;
36    }
37    return 0;
38}
39
40ListPtr
41listCons(char *car, ListPtr cdr)
42{
43    ListPtr lcar = malloc(sizeof(ListRec));
44    if(!lcar)
45        return NULL;
46    lcar -> value = car;
47    lcar -> next = cdr;
48    return lcar;
49}
50
51ListPtr
52listAdjoin(char *car, ListPtr cdr)
53{
54    if(listMember(car, cdr)) {
55        free(car);
56        return cdr;
57    }
58    return listCons(car, cdr);
59}
60
61char *
62dsprintf(const char *f, ...)
63{
64    va_list args;
65    char *string;
66    {
67	int n, size = 20;
68	while(1) {
69	    if(size > 4096)
70		return NULL;
71	    string = malloc(size);
72	    if(!string)
73		return NULL;
74	    va_start(args, f);
75	    n = vsnprintf(string, size, f, args);
76	    va_end(args);
77	    if(n >= 0 && n < size)
78                return string;
79	    else if(n >= size)
80		size = n + 1;
81	    else
82		size = size * 3 / 2 + 1;
83	    free(string);
84	}
85    }
86}
87
88
89ListPtr
90listConsF(ListPtr cdr, const char *f, ...)
91{
92    va_list args;
93    char *string;
94    {
95	int n, size = 20;
96	while(1) {
97	    if(size > 4096)
98		return NULL;
99	    string = malloc(size);
100	    if(!string)
101		return NULL;
102	    va_start(args, f);
103	    n = vsnprintf(string, size, f, args);
104	    va_end(args);
105	    if(n >= 0 && n < size)
106		return listCons(string, cdr);
107	    else if(n >= size)
108		size = n + 1;
109	    else
110		size = size * 3 / 2 + 1;
111	    free(string);
112	}
113    }
114}
115
116ListPtr
117listAdjoinF(ListPtr cdr, const char *f, ...)
118{
119    va_list args;
120    char *string;
121    {
122	int n, size = 20;
123	while(1) {
124	    if(size > 4096)
125		return NULL;
126	    string = malloc(size);
127	    if(!string)
128		return NULL;
129	    va_start(args, f);
130	    n = vsnprintf(string, size, f, args);
131	    va_end(args);
132	    if(n >= 0 && n < size)
133		return listAdjoin(string, cdr);
134	    else if(n >= size)
135		size = n + 1;
136	    else
137		size = size * 3 / 2 + 1;
138	    free(string);
139	}
140    }
141}
142
143int
144listLength(ListPtr list)
145{
146    int n = 0;
147    while(list) {
148        n++;
149        list = list->next;
150    }
151    return n;
152}
153
154ListPtr
155appendList(ListPtr first, ListPtr second)
156{
157    ListPtr current;
158
159    if(second == NULL)
160        return first;
161
162    if(first == NULL)
163        return second;
164
165    for(current = first; current->next; current = current->next)
166        ;
167
168    current->next = second;
169    return first;
170}
171
172ListPtr
173makeList(char **a, int n, ListPtr old, int begin)
174{
175    ListPtr first, current, next;
176    int i;
177
178    if(n == 0)
179        return old;
180
181    first = malloc(sizeof(ListRec));
182    if(!first)
183        return NULL;
184
185    first->value = a[0];
186    first->next = NULL;
187
188    current = first;
189    for(i = 1; i < n; i++) {
190        next = malloc(sizeof(ListRec));
191        if(!next) {
192            destroyList(first);
193            return NULL;
194        }
195        next->value = a[i];
196        next->next = NULL;
197
198        current->next = next;
199        current = next;
200    }
201    if(begin) {
202        current->next = old;
203        return first;
204    } else {
205        return appendList(old, first);
206    }
207}
208
209ListPtr
210reverseList(ListPtr old)
211{
212    ListPtr new = NULL, current;
213    while(old) {
214        current = old;
215        old = old->next;
216        current->next = new;
217        new = current;
218    }
219    return new;
220}
221
222/* qsort helper for sorting list entries */
223static int
224compareListEntries(const void *a, const void *b)
225{
226    const ListPtr lista = *(const ListPtr *) a;
227    const ListPtr listb = *(const ListPtr *) b;
228
229    return strcmp(lista->value, listb->value);
230}
231
232ListPtr
233sortList(ListPtr old)
234{
235    int i;
236    int l = listLength(old);
237    ListPtr n;
238    ListPtr *sorted = malloc(l * sizeof(ListPtr));
239
240    if (sorted == NULL)
241        return old;
242
243    for (n = old, i = 0; n != NULL; n = n->next) {
244        sorted[i++] = n;
245    }
246    qsort(sorted, i, sizeof(ListPtr), compareListEntries);
247    n = sorted[0];
248    for (i = 0; i < (l - 1); i++) {
249        sorted[i]->next = sorted[i+1];
250    }
251    sorted[i]->next = NULL;
252    free(sorted);
253    return n;
254}
255
256void
257destroyList(ListPtr old)
258{
259    ListPtr next;
260    if(!old)
261        return;
262    while(old) {
263        next = old->next;
264        free(old);
265        old = next;
266    }
267}
268
269void
270deepDestroyList(ListPtr old)
271{
272    ListPtr next;
273    if(!old)
274        return;
275    while(old) {
276        next = old->next;
277        free(old->value);
278        free(old);
279        old = next;
280    }
281}
282