2013-02-20 [colin] 3.9.0cvs95
[claws.git] / src / plugins / mailmbox / clist.c
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
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
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
69 int clist_isempty(clist * lst) {
70   return ((lst->first==lst->last) && (lst->last==NULL));
71 }
72
73 clistiter * clist_begin(clist * lst) {
74   return lst->first;
75 }
76
77 clistiter * clist_end(clist * lst) {
78   return lst->last;
79 }
80
81 clistiter * clist_next(clistiter * iter) {
82   if (iter)
83     return iter->next;
84   else
85     return NULL;
86 }
87
88 clistiter * clist_previous(clistiter * iter) {
89   if (iter)
90     return iter->previous;
91   else
92     return NULL;
93 }
94
95 void * clist_content(clistiter * iter) {
96   if (iter)
97     return iter->data;
98   else
99     return NULL;
100 }
101
102 int clist_count(clist * lst) {
103   return lst->count;
104 }
105
106 int clist_prepend(clist * lst, void * data) {
107   return clist_insert_before(lst, lst->first, data);
108 }
109
110 int clist_append(clist * lst, void * data) {
111   return clist_insert_after(lst, lst->last, data);
112 }
113 #endif
114
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
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
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
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
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
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
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
263 clistiter * clist_nth(clist * lst, int index)
264 {
265   return internal_clist_nth(lst, index);
266 }