/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 1999, 2000, 2004, 2005, 2007, 2010, 2011 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include int mu_iterator_create (mu_iterator_t *piterator, void *owner) { mu_iterator_t iterator; if (piterator == NULL) return MU_ERR_OUT_PTR_NULL; if (owner == NULL) return EINVAL; iterator = calloc (1, sizeof (*iterator)); if (iterator == NULL) return ENOMEM; iterator->owner = owner; *piterator = iterator; return 0; } int mu_iterator_set_first (mu_iterator_t itr, int (*first) (void *)) { if (!itr) return EINVAL; itr->first = first; return 0; } int mu_iterator_set_next (mu_iterator_t itr, int (*next) (void *)) { if (!itr) return EINVAL; itr->next = next; return 0; } int mu_iterator_set_getitem (mu_iterator_t itr, int (*getitem) (void *, void **, const void **)) { if (!itr) return EINVAL; itr->getitem = getitem; return 0; } int mu_iterator_set_finished_p (mu_iterator_t itr, int (*finished_p) (void *)) { if (!itr) return EINVAL; itr->finished_p = finished_p; return 0; } int mu_iterator_set_curitem_p (mu_iterator_t itr, int (*curitem_p) (void *, void *)) { if (!itr) return EINVAL; itr->curitem_p = curitem_p; return 0; } int mu_iterator_set_itrctl (mu_iterator_t itr, int (*itrctl) (void *, enum mu_itrctl_req, void *)) { if (!itr) return EINVAL; itr->itrctl = itrctl; return 0; } int mu_iterator_set_dataptr (mu_iterator_t itr, void *(*dataptr) (void *)) { if (!itr) return EINVAL; itr->dataptr = dataptr; return 0; } int mu_iterator_set_destroy (mu_iterator_t itr, int (*destroy) (mu_iterator_t, void *)) { if (!itr) return EINVAL; itr->destroy = destroy; return 0; } int mu_iterator_set_dup (mu_iterator_t itr, int (*dup) (void **ptr, void *data)) { if (!itr) return EINVAL; itr->dup = dup; return 0; } int mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig) { mu_iterator_t iterator; int status; if (piterator == NULL) return MU_ERR_OUT_PTR_NULL; if (orig == NULL) return EINVAL; status = mu_iterator_create (&iterator, orig->owner); if (status) return status; status = orig->dup (&iterator->owner, orig->owner); if (status) { free (iterator); return status; } iterator->is_advanced = orig->is_advanced; iterator->dup = orig->dup; iterator->destroy = orig->destroy; iterator->first = orig->first; iterator->next = orig->next; iterator->getitem = orig->getitem; iterator->curitem_p = orig->curitem_p; iterator->finished_p = orig->finished_p; iterator->itrctl = orig->itrctl; *piterator = iterator; return 0; } void mu_iterator_destroy (mu_iterator_t *piterator) { if (!piterator || !*piterator) return; if ((*piterator)->destroy) (*piterator)->destroy (*piterator, (*piterator)->owner); free (*piterator); *piterator = NULL; } int mu_iterator_first (mu_iterator_t iterator) { iterator->is_advanced = 0; return iterator->first (iterator->owner); } int mu_iterator_next (mu_iterator_t iterator) { int status = 0; if (!iterator->is_advanced) status = iterator->next (iterator->owner); iterator->is_advanced = 0; return status; } int mu_iterator_skip (mu_iterator_t iterator, ssize_t count) { int status; if (count < 0) return ENOSYS; /* Need prev method */ while (count--) if ((status = mu_iterator_next (iterator))) break; return status; } int mu_iterator_current (mu_iterator_t iterator, void **pitem) { return mu_iterator_current_kv (iterator, NULL, pitem); } int mu_iterator_current_kv (mu_iterator_t iterator, const void **pkey, void **pitem) { void *ptr; int rc = iterator->getitem (iterator->owner, &ptr, pkey); if (rc == 0) { if (iterator->dataptr) *pitem = iterator->dataptr (ptr); else *pitem = ptr; } return rc; } int mu_iterator_is_done (mu_iterator_t iterator) { if (iterator == NULL) return 1; return iterator->finished_p (iterator->owner); } int iterator_get_owner (mu_iterator_t iterator, void **powner) { if (!iterator) return EINVAL; if (!powner) return MU_ERR_OUT_PTR_NULL; *powner = iterator->owner; return 0; } void mu_iterator_advance (mu_iterator_t iterator, void *e) { for (; iterator; iterator = iterator->next_itr) { if (iterator->curitem_p (iterator->owner, e)) { iterator->next (iterator->owner); iterator->is_advanced++; } } } int mu_iterator_attach (mu_iterator_t *root, mu_iterator_t iterator) { iterator->next_itr = *root; *root = iterator; return 0; } int mu_iterator_detach (mu_iterator_t *root, mu_iterator_t iterator) { mu_iterator_t itr, prev; for (itr = *root, prev = NULL; itr; prev = itr, itr = itr->next_itr) if (iterator == itr) break; if (itr) { if (prev) prev->next_itr = itr->next_itr; else *root = itr->next_itr; } return 0; } int mu_iterator_ctl (mu_iterator_t iterator, enum mu_itrctl_req req, void *arg) { if (!iterator) return EINVAL; if (!iterator->itrctl) return ENOSYS; return iterator->itrctl (iterator->owner, req, arg); }