/* GNU mailutils - a suite of utilities for electronic mail Copyright (C) 1999, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Library Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include int observer_create (observer_t *pobserver, void *owner) { observer_t observer; observer = calloc (sizeof (*observer), 1); if (observer == NULL) return ENOMEM; observer->owner = owner; *pobserver = observer; return 0; } void observer_destroy (observer_t *pobserver, void *owner) { if (pobserver && *pobserver) { observer_t observer = *pobserver; if (observer->owner == owner || observer->flags & MU_OBSERVER_NO_CHECK) { if (observer->_destroy) observer->_destroy (observer); free (observer); } *pobserver = NULL; } } void * observer_get_owner (observer_t observer) { return (observer) ? observer->owner : NULL; } int observer_action (observer_t observer, size_t type) { if (observer == NULL) return EINVAL; if (observer->_action) return observer->_action (observer, type); return 0; } int observer_set_action (observer_t observer, int (*_action) __P ((observer_t, size_t)), void *owner) { if (observer == NULL) return EINVAL; if (observer->owner != owner) return EACCES; observer->_action = _action; return 0; } int observer_set_destroy (observer_t observer, int (*_destroy) __P((observer_t)), void *owner) { if (observer == NULL) return EINVAL; if (observer->owner != owner) return EACCES; observer->_destroy = _destroy; return 0; } int observer_set_flags (observer_t observer, int flags) { if (observer == NULL) return EINVAL; observer->flags |= flags; return 0; } int observable_create (observable_t *pobservable, void *owner) { observable_t observable; int status; if (pobservable == NULL) return EINVAL; observable = calloc (sizeof (*observable), 1); if (observable == NULL) return ENOMEM; status = list_create (&(observable->list)); if (status != 0 ) { free (observable); return status; } observable->owner = owner; *pobservable = observable; return 0; } void observable_destroy (observable_t *pobservable, void *owner) { iterator_t iterator; if (pobservable && *pobservable) { observable_t observable = *pobservable; if (observable->owner == owner) { int status = iterator_create (&iterator, observable->list); if (status == 0) { event_t event = NULL; for (iterator_first (iterator); !iterator_is_done (iterator); iterator_next (iterator)) { event = NULL; iterator_current (iterator, (void **)&event); if (event != NULL) { observer_destroy (&(event->observer), NULL); free (event); } } iterator_destroy (&iterator); } list_destroy (&((*pobservable)->list)); free (*pobservable); } *pobservable = NULL; } } void * observable_get_owner (observable_t observable) { return (observable) ? observable->owner : NULL; } int observable_attach (observable_t observable, size_t type, observer_t observer) { event_t event; if (observable == NULL || observer == NULL) return EINVAL; event = calloc (1, sizeof (*event)); if (event == NULL) return ENOMEM; event->type = type; event->observer = observer; return list_append (observable->list, event); } int observable_detach (observable_t observable, observer_t observer) { iterator_t iterator; int status; int found = 0; event_t event = NULL; if (observable == NULL ||observer == NULL) return EINVAL; status = iterator_create (&iterator, observable->list); if (status != 0) return status; for (iterator_first (iterator); !iterator_is_done (iterator); iterator_next (iterator)) { event = NULL; iterator_current (iterator, (void **)&event); if (event && (int)(event->observer) == (int)observer) { found = 1; break; } } iterator_destroy (&iterator); if (found) { status = list_remove (observable->list, event); free (event); } else status = ENOENT; return status; } int observable_notify (observable_t observable, int type) { iterator_t iterator; event_t event = NULL; int status = 0; if (observable == NULL) return EINVAL; status = iterator_create (&iterator, observable->list); if (status != 0) return status; for (iterator_first (iterator); !iterator_is_done (iterator); iterator_next (iterator)) { event = NULL; iterator_current (iterator, (void **)&event); if (event && event->type & type) { status |= observer_action (event->observer, type); } } iterator_destroy (&iterator); return status; }