Blame view

mailbox/observer.c 5.53 KB
1
/* GNU Mailutils -- a suite of utilities for electronic mail
2
   Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc.
3

4 5 6 7
   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 2 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 12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
13

14 15 16
   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA  */
17 18 19 20 21 22 23

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <errno.h>
#include <stdlib.h>
24 25

#include <mailutils/list.h>
26
#include <mailutils/iterator.h>
27
#include <mailutils/errno.h>
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
#include <observer0.h>

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)
113
    return MU_ERR_OUT_PTR_NULL;
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
  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)
	{
137
	  int status = list_get_iterator (observable->list, &iterator);
138 139
	  if (status == 0)
	    {
140
	      event_t event = NULL;
141 142 143
	      for (iterator_first (iterator); !iterator_is_done (iterator);
		   iterator_next (iterator))
		{
144 145 146 147 148 149 150
		  event = NULL;
		  iterator_current (iterator, (void **)&event);
		  if (event != NULL)
		    {
		      observer_destroy (&(event->observer), NULL);
		      free (event);
		    }
151
		}
152
	      iterator_destroy (&iterator);
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
	    }
	  list_destroy (&((*pobservable)->list));
	  free (*pobservable);
	}
      *pobservable = NULL;
    }
}

void *
observable_get_owner (observable_t observable)
{
  return (observable) ? observable->owner : NULL;
}

int
168
observable_attach (observable_t observable, size_t type,  observer_t observer)
169
{
170
  event_t event;
171 172
  if (observable == NULL || observer == NULL)
    return EINVAL;
173 174 175 176 177 178
  event = calloc (1, sizeof (*event));
  if (event == NULL)
    return ENOMEM;
  event->type = type;
  event->observer = observer;
  return list_append (observable->list, event);
179 180 181 182 183 184 185 186
}

int
observable_detach (observable_t observable, observer_t observer)
{
  iterator_t iterator;
  int status;
  int found = 0;
187
  event_t event = NULL;
188
  if (observable == NULL || observer == NULL)
189
    return EINVAL;
190
  status = list_get_iterator (observable->list, &iterator);
191 192 193 194 195
  if (status != 0)
    return status;
  for (iterator_first (iterator); !iterator_is_done (iterator);
       iterator_next (iterator))
    {
196 197
      event = NULL;
      iterator_current (iterator, (void **)&event);
198
      if (event && event->observer == observer)
199 200 201 202 203 204
        {
          found = 1;
          break;
        }
    }
  iterator_destroy (&iterator);
205 206 207 208 209 210
  if (found)
    {
      status = list_remove (observable->list, event);
      free (event);
    }
  else
211
    status = MU_ERR_NOENT;
212
  return status;
213 214 215 216 217 218
}

int
observable_notify (observable_t observable, int type)
{
  iterator_t iterator;
219
  event_t event = NULL;
220 221 222
  int status = 0;
  if (observable == NULL)
    return EINVAL;
223
  status = list_get_iterator (observable->list, &iterator);
224 225 226 227 228
  if (status != 0)
    return status;
  for (iterator_first (iterator); !iterator_is_done (iterator);
       iterator_next (iterator))
    {
229 230 231
      event = NULL;
      iterator_current (iterator, (void **)&event);
      if (event && event->type & type)
232
        {
233
	  status |= observer_action (event->observer, type);
234 235 236 237 238
        }
    }
  iterator_destroy (&iterator);
  return status;
}