1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <errno.h>
23 #include <stdlib.h>
24
25 #include <mailutils/sys/list.h>
26 #include <mailutils/sys/iterator.h>
27 #include <mailutils/errno.h>
28
29 int
mu_iterator_create(mu_iterator_t * piterator,void * owner)30 mu_iterator_create (mu_iterator_t *piterator, void *owner)
31 {
32 mu_iterator_t iterator;
33 if (piterator == NULL)
34 return MU_ERR_OUT_PTR_NULL;
35 if (owner == NULL)
36 return EINVAL;
37 iterator = calloc (1, sizeof (*iterator));
38 if (iterator == NULL)
39 return ENOMEM;
40 iterator->owner = owner;
41 *piterator = iterator;
42 return 0;
43 }
44
45 int
mu_iterator_set_first(mu_iterator_t itr,int (* first)(void *))46 mu_iterator_set_first (mu_iterator_t itr, int (*first) (void *))
47 {
48 if (!itr)
49 return EINVAL;
50 itr->first = first;
51 return 0;
52 }
53
54 int
mu_iterator_set_next(mu_iterator_t itr,int (* next)(void *))55 mu_iterator_set_next (mu_iterator_t itr, int (*next) (void *))
56 {
57 if (!itr)
58 return EINVAL;
59 itr->next = next;
60 return 0;
61 }
62
63 int
mu_iterator_set_getitem(mu_iterator_t itr,int (* getitem)(void *,void **,const void **))64 mu_iterator_set_getitem (mu_iterator_t itr,
65 int (*getitem) (void *, void **, const void **))
66 {
67 if (!itr)
68 return EINVAL;
69 itr->getitem = getitem;
70 return 0;
71 }
72
73 int
mu_iterator_set_finished_p(mu_iterator_t itr,int (* finished_p)(void *))74 mu_iterator_set_finished_p (mu_iterator_t itr, int (*finished_p) (void *))
75 {
76 if (!itr)
77 return EINVAL;
78 itr->finished_p = finished_p;
79 return 0;
80 }
81
82 int
mu_iterator_set_delitem(mu_iterator_t itr,int (* delitem)(void *,void *))83 mu_iterator_set_delitem (mu_iterator_t itr,
84 int (*delitem) (void *, void *))
85 {
86 if (!itr)
87 return EINVAL;
88 itr->delitem = delitem;
89 return 0;
90 }
91
92 int
mu_iterator_set_itrctl(mu_iterator_t itr,int (* itrctl)(void *,enum mu_itrctl_req,void *))93 mu_iterator_set_itrctl (mu_iterator_t itr,
94 int (*itrctl) (void *,
95 enum mu_itrctl_req,
96 void *))
97 {
98 if (!itr)
99 return EINVAL;
100 itr->itrctl = itrctl;
101 return 0;
102 }
103
104 int
mu_iterator_set_dataptr(mu_iterator_t itr,void * (* dataptr)(void *))105 mu_iterator_set_dataptr (mu_iterator_t itr, void *(*dataptr) (void *))
106 {
107 if (!itr)
108 return EINVAL;
109 itr->dataptr = dataptr;
110 return 0;
111 }
112
113 int
mu_iterator_set_destroy(mu_iterator_t itr,int (* destroy)(mu_iterator_t,void *))114 mu_iterator_set_destroy (mu_iterator_t itr, int (*destroy) (mu_iterator_t, void *))
115 {
116 if (!itr)
117 return EINVAL;
118 itr->destroy = destroy;
119 return 0;
120 }
121
122 int
mu_iterator_set_dup(mu_iterator_t itr,int (* dup)(void ** ptr,void * data))123 mu_iterator_set_dup (mu_iterator_t itr, int (*dup) (void **ptr, void *data))
124 {
125 if (!itr)
126 return EINVAL;
127 itr->dup = dup;
128 return 0;
129 }
130
131
132
133 int
mu_iterator_dup(mu_iterator_t * piterator,mu_iterator_t orig)134 mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig)
135 {
136 mu_iterator_t iterator;
137 int status;
138
139 if (piterator == NULL)
140 return MU_ERR_OUT_PTR_NULL;
141 if (orig == NULL)
142 return EINVAL;
143
144 status = mu_iterator_create (&iterator, orig->owner);
145 if (status)
146 return status;
147
148 status = orig->dup (&iterator->owner, orig->owner);
149 if (status)
150 {
151 free (iterator);
152 return status;
153 }
154 iterator->is_advanced = orig->is_advanced;
155 iterator->dup = orig->dup;
156 iterator->destroy = orig->destroy;
157 iterator->first = orig->first;
158 iterator->next = orig->next;
159 iterator->getitem = orig->getitem;
160 iterator->delitem = orig->delitem;
161 iterator->finished_p = orig->finished_p;
162 iterator->itrctl = orig->itrctl;
163
164 *piterator = iterator;
165 return 0;
166 }
167
168 void
mu_iterator_destroy(mu_iterator_t * piterator)169 mu_iterator_destroy (mu_iterator_t *piterator)
170 {
171 if (!piterator || !*piterator)
172 return;
173
174 if ((*piterator)->destroy)
175 (*piterator)->destroy (*piterator, (*piterator)->owner);
176
177 free (*piterator);
178 *piterator = NULL;
179 }
180
181 int
mu_iterator_first(mu_iterator_t iterator)182 mu_iterator_first (mu_iterator_t iterator)
183 {
184 iterator->is_advanced = 0;
185 return iterator->first (iterator->owner);
186 }
187
188 int
mu_iterator_next(mu_iterator_t iterator)189 mu_iterator_next (mu_iterator_t iterator)
190 {
191 int status = 0;
192 if (!iterator->is_advanced)
193 status = iterator->next (iterator->owner);
194 iterator->is_advanced = 0;
195 return status;
196 }
197
198 int
mu_iterator_skip(mu_iterator_t iterator,ssize_t count)199 mu_iterator_skip (mu_iterator_t iterator, ssize_t count)
200 {
201 int status;
202 if (count < 0)
203 return ENOSYS; /* Need prev method */
204 while (count--)
205 if ((status = mu_iterator_next (iterator)))
206 break;
207 return status;
208 }
209
210 int
mu_iterator_skip_while(mu_iterator_t iterator,int (* pred)(void *,void *),void * data)211 mu_iterator_skip_while (mu_iterator_t iterator,
212 int (*pred) (void *, void *),
213 void *data)
214 {
215 int status;
216 if (!iterator || !pred)
217 return EINVAL;
218 do
219 {
220 if ((status = mu_iterator_next (iterator)) == 0)
221 {
222 void *item;
223 if ((status = mu_iterator_current (iterator, &item)) == 0)
224 if (!pred (item, data))
225 break;
226 }
227 }
228 while (status == 0);
229
230 return status;
231 }
232
233 int
mu_iterator_skip_until(mu_iterator_t iterator,int (* pred)(void *,void *),void * data)234 mu_iterator_skip_until (mu_iterator_t iterator,
235 int (*pred) (void *, void *),
236 void *data)
237 {
238 int status;
239 if (!iterator || !pred)
240 return EINVAL;
241 do
242 {
243 if ((status = mu_iterator_next (iterator)) == 0)
244 {
245 void *item;
246 if ((status = mu_iterator_current (iterator, &item)) == 0)
247 if (pred (item, data))
248 break;
249 }
250 }
251 while (status == 0);
252
253 return status;
254 }
255
256
257 int
mu_iterator_current(mu_iterator_t iterator,void ** pitem)258 mu_iterator_current (mu_iterator_t iterator, void **pitem)
259 {
260 return mu_iterator_current_kv (iterator, NULL, pitem);
261 }
262
263 int
mu_iterator_current_kv(mu_iterator_t iterator,const void ** pkey,void ** pitem)264 mu_iterator_current_kv (mu_iterator_t iterator,
265 const void **pkey, void **pitem)
266 {
267 void *ptr;
268 int rc = iterator->getitem (iterator->owner, &ptr, pkey);
269 if (rc == 0)
270 {
271 if (iterator->dataptr)
272 *pitem = iterator->dataptr (ptr);
273 else
274 *pitem = ptr;
275 }
276 return rc;
277 }
278
279 int
mu_iterator_is_done(mu_iterator_t iterator)280 mu_iterator_is_done (mu_iterator_t iterator)
281 {
282 if (iterator == NULL)
283 return 1;
284 return iterator->finished_p (iterator->owner);
285 }
286
287 int
iterator_get_owner(mu_iterator_t iterator,void ** powner)288 iterator_get_owner (mu_iterator_t iterator, void **powner)
289 {
290 if (!iterator)
291 return EINVAL;
292 if (!powner)
293 return MU_ERR_OUT_PTR_NULL;
294 *powner = iterator->owner;
295 return 0;
296 }
297
298 void
mu_iterator_delitem(mu_iterator_t iterator,void * itm)299 mu_iterator_delitem (mu_iterator_t iterator, void *itm)
300 {
301 for (; iterator; iterator = iterator->next_itr)
302 {
303 if (iterator->delitem)
304 {
305 switch (iterator->delitem (iterator->owner, itm))
306 {
307 case MU_ITR_DELITEM_NEXT:
308 iterator->next (iterator->owner);
309 case MU_ITR_DELITEM_ADVANCE:
310 iterator->is_advanced++;
311 }
312 }
313 }
314 }
315
316 int
mu_iterator_attach(mu_iterator_t * root,mu_iterator_t iterator)317 mu_iterator_attach (mu_iterator_t *root, mu_iterator_t iterator)
318 {
319 iterator->next_itr = *root;
320 *root = iterator;
321 return 0;
322 }
323
324 int
mu_iterator_detach(mu_iterator_t * root,mu_iterator_t iterator)325 mu_iterator_detach (mu_iterator_t *root, mu_iterator_t iterator)
326 {
327 mu_iterator_t itr, prev;
328
329 for (itr = *root, prev = NULL; itr; prev = itr, itr = itr->next_itr)
330 if (iterator == itr)
331 break;
332
333 if (itr)
334 {
335 if (prev)
336 prev->next_itr = itr->next_itr;
337 else
338 *root = itr->next_itr;
339 }
340
341 return 0;
342 }
343
344 int
mu_iterator_ctl(mu_iterator_t iterator,enum mu_itrctl_req req,void * arg)345 mu_iterator_ctl (mu_iterator_t iterator, enum mu_itrctl_req req, void *arg)
346 {
347 if (!iterator)
348 return EINVAL;
349 if (!iterator->itrctl)
350 return ENOSYS;
351 return iterator->itrctl (iterator->owner, req, arg);
352 }
353