1 
2 /*
3  * libEtPan! -- a mail stuff library
4  *
5  * clist - Implements simple generic double-linked pointer lists
6  *
7  * Copyright (c) 1999-2000, Ga�l Roualland <gael.roualland@iname.com>
8  * interface changes - 2002 - DINH Viet Hoa
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the libEtPan! project nor the names of its
20  *    contributors may be used to endorse or promote products derived
21  *    from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 /*
37  * $Id$
38  */
39 
40 #include <stdlib.h>
41 #include "clist.h"
42 
clist_new()43 clist * clist_new() {
44   clist * lst;
45 
46   lst = (clist *) malloc(sizeof(clist));
47   if (!lst) return NULL;
48 
49   lst->first = lst->last = NULL;
50   lst->count = 0;
51 
52   return lst;
53 }
54 
clist_free(clist * lst)55 void clist_free(clist * lst) {
56   clistcell * l1, * l2;
57 
58   l1 = lst->first;
59   while (l1) {
60     l2 = l1->next;
61     free(l1);
62     l1 = l2;
63   }
64 
65   free(lst);
66 }
67 
68 #ifdef NO_MACROS
clist_isempty(clist * lst)69 int clist_isempty(clist * lst) {
70   return ((lst->first==lst->last) && (lst->last==NULL));
71 }
72 
clist_begin(clist * lst)73 clistiter * clist_begin(clist * lst) {
74   return lst->first;
75 }
76 
clist_end(clist * lst)77 clistiter * clist_end(clist * lst) {
78   return lst->last;
79 }
80 
clist_next(clistiter * iter)81 clistiter * clist_next(clistiter * iter) {
82   if (iter)
83     return iter->next;
84   else
85     return NULL;
86 }
87 
clist_previous(clistiter * iter)88 clistiter * clist_previous(clistiter * iter) {
89   if (iter)
90     return iter->previous;
91   else
92     return NULL;
93 }
94 
clist_content(clistiter * iter)95 void * clist_content(clistiter * iter) {
96   if (iter)
97     return iter->data;
98   else
99     return NULL;
100 }
101 
clist_count(clist * lst)102 int clist_count(clist * lst) {
103   return lst->count;
104 }
105 
clist_prepend(clist * lst,void * data)106 int clist_prepend(clist * lst, void * data) {
107   return clist_insert_before(lst, lst->first, data);
108 }
109 
clist_append(clist * lst,void * data)110 int clist_append(clist * lst, void * data) {
111   return clist_insert_after(lst, lst->last, data);
112 }
113 #endif
114 
clist_insert_before(clist * lst,clistiter * iter,void * data)115 int clist_insert_before(clist * lst, clistiter * iter, void * data) {
116   clistcell * c;
117 
118   c = (clistcell *) malloc(sizeof(clistcell));
119   if (!c) return -1;
120 
121   c->data = data;
122   lst->count++;
123 
124   if (clist_isempty(lst)) {
125     c->previous = c->next = NULL;
126     lst->first = lst->last = c;
127     return 0;
128   }
129 
130   if (!iter) {
131     c->previous = lst->last;
132     c->previous->next = c;
133     c->next = NULL;
134     lst->last = c;
135     return 0;
136   }
137 
138   c->previous = iter->previous;
139   c->next = iter;
140   c->next->previous = c;
141   if (c->previous)
142     c->previous->next = c;
143   else
144     lst->first = c;
145 
146   return 0;
147 }
148 
clist_insert_after(clist * lst,clistiter * iter,void * data)149 int clist_insert_after(clist * lst, clistiter * iter, void * data) {
150   clistcell * c;
151 
152   c = (clistcell *) malloc(sizeof(clistcell));
153   if (!c) return -1;
154 
155   c->data = data;
156   lst->count++;
157 
158   if (clist_isempty(lst)) {
159     c->previous = c->next = NULL;
160     lst->first = lst->last = c;
161     return 0;
162   }
163 
164   if (!iter) {
165     c->previous = lst->last;
166     c->previous->next = c;
167     c->next = NULL;
168     lst->last = c;
169     return 0;
170   }
171 
172   c->previous = iter;
173   c->next = iter->next;
174   if (c->next)
175     c->next->previous = c;
176   else
177     lst->last = c;
178   c->previous->next = c;
179 
180   return 0;
181 }
182 
clist_delete(clist * lst,clistiter * iter)183 clistiter * clist_delete(clist * lst, clistiter * iter) {
184   clistiter * ret;
185 
186   if (!iter) return NULL;
187 
188   if (iter->previous)
189     iter->previous->next = iter->next;
190   else
191     lst->first = iter->next;
192 
193   if (iter->next) {
194     iter->next->previous = iter->previous;
195     ret = iter->next;
196   }  else {
197     lst->last = iter->previous;
198     ret = NULL;
199   }
200 
201   free(iter);
202   lst->count--;
203 
204   return ret;
205 }
206 
207 
208 
clist_foreach(clist * lst,clist_func func,void * data)209 void clist_foreach(clist * lst, clist_func func, void * data)
210 {
211   clistiter * cur;
212 
213   for(cur = clist_begin(lst) ; cur != NULL ; cur = cur->next)
214     func(cur->data, data);
215 }
216 
clist_concat(clist * dest,clist * src)217 void clist_concat(clist * dest, clist * src)
218 {
219   if (src->first == NULL) {
220     /* do nothing */
221   }
222   else if (dest->last == NULL) {
223     dest->first = src->first;
224     dest->last = src->last;
225   }
226   else {
227     dest->last->next = src->first;
228     src->first->previous = dest->last;
229     dest->last = src->last;
230   }
231 
232   dest->count += src->count;
233   src->last = src->first = NULL;
234 }
235 
internal_clist_nth(clist * lst,int index)236 static inline clistiter * internal_clist_nth(clist * lst, int index)
237 {
238   clistiter * cur;
239 
240   cur = clist_begin(lst);
241   while ((index > 0) && (cur != NULL)) {
242     cur = cur->next;
243     index --;
244   }
245 
246   if (cur == NULL)
247     return NULL;
248 
249   return cur;
250 }
251 
clist_nth_data(clist * lst,int index)252 void * clist_nth_data(clist * lst, int index)
253 {
254   clistiter * cur;
255 
256   cur = internal_clist_nth(lst, index);
257   if (cur == NULL)
258     return NULL;
259 
260   return cur->data;
261 }
262 
clist_nth(clist * lst,int index)263 clistiter * clist_nth(clist * lst, int index)
264 {
265   return internal_clist_nth(lst, index);
266 }
267