Commit 1413567b 1413567bfd73bfb39404201a4fc19a4d23dae3ec by Sergey Poznyakoff

Mu_list_replace and mu_list_remove actually reclaim the memory associated with the item.

* include/mailutils/iterator.h (mu_itrctl_delete_nd)
(mu_itrctl_replace_nd): New mu_itrctl_req constants.
* include/mailutils/list.h (mu_list_remove_nd)
(mu_list_replace_nd): New prototypes.
(mu_list_destroy_item_t): New typedef.
(mu_list_set_destroy_item): Return mu_list_destroy_item_t.
* mailbox/list.c (DESTROY_ITEM): New macro.
(mu_list_destroy): Use DESTROY_ITEM.
(mu_list_remove, mu_list_replace): Actually destroy the
item being removed.
(mu_list_remove_nd, mu_list_replace_nd): New functions.
(mu_list_set_destroy_item): Return previous value of
destroy_item.
(list_itrctl): Handle mu_itrctl_delete_nd and mu_itrctl_replace_nd.

* mailbox/observer.c (mu_observable_create): Register destroy_item
function.
(mu_observable_destroy): Remove explicit loop. Rely on destroy_item
instead.
(mu_observable_detach): Use mu_iterator_ctl to actually
remove the event.
* mh/mh_alias.y (_insert_list): Remove.
(alias_expand_list): Use mu_iterator_ctl to insert
replacement list and remove the current item.
* mh/sortm.c (addop): Register destroy_item function.
(remop): Remove call to free.
* movemail/movemail.c (main): <uidl loop>: Use mu_itrctl_delete
to remove items.

* libmu_sieve/util.c: Minor change.

* mail/util.c (util_slist_compare): New static function.
(util_slist_add): Register destroy_item and comparison
functions for the new list.
(util_slist_remove,util_slist_destroy): Rewrite.

* imap4d/authenticate.c (auth_add): Use mu_list_free_item as
destroy_item function.
* imap4d/util.c (util_register_event): Likewise.

* include/mailutils/cpp/list.h (List)<set_destroy_item>: Change
return value.
* libmu_cpp/list.cc (List::set_destroy_item): Reflect changes to
mu_list_set_destroy_item.
* libmu_argp/common.c: Include stdlib.h
1 parent a192c111
......@@ -47,6 +47,7 @@ auth_add (char *name, imap4d_auth_handler_fp handler)
{
mu_list_create (&imap_auth_list);
mu_list_set_comparator (imap_auth_list, comp);
mu_list_set_destroy_item (imap_auth_list, mu_list_free_item);
}
mu_list_append (imap_auth_list, (void*)p);
}
......
......@@ -951,7 +951,10 @@ util_register_event (int old_state, int new_state,
evp->action = action;
evp->data = data;
if (!event_list)
{
mu_list_create (&event_list);
mu_list_set_destroy_item (event_list, mu_list_free_item);
}
mu_list_append (event_list, (void*)evp);
}
......
......@@ -69,7 +69,7 @@ class List
void apply (mu_list_action_t* action, void* cbdata);
mu_list_comparator_t set_comparator (mu_list_comparator_t comp);
void set_destroy_item (void (*mu_destoy_item) (void *item));
mu_list_destroy_item_t set_destroy_item (mu_list_destroy_item_t mu_destroy_item);
bool is_empty ();
size_t count ();
......
......@@ -30,7 +30,9 @@ enum mu_itrctl_req
{
mu_itrctl_tell, /* Return current position in the object */
mu_itrctl_delete, /* Delete current element */
mu_itrctl_replace,/* Replace current element */
mu_itrctl_delete_nd, /* Delete current element, non-destructive */
mu_itrctl_replace, /* Replace current element */
mu_itrctl_replace_nd, /* Replace current element, non-destructive */
mu_itrctl_insert, /* Insert new element in the current position */
mu_itrctl_insert_list, /* Insert a list of elements */
};
......
......@@ -35,7 +35,9 @@ extern int mu_list_insert (mu_list_t list, void *item, void *new_item,
extern int mu_list_is_empty (mu_list_t);
extern int mu_list_count (mu_list_t, size_t *pcount);
extern int mu_list_remove (mu_list_t, void *item);
extern int mu_list_remove_nd (mu_list_t, void *item);
extern int mu_list_replace (mu_list_t list, void *old_item, void *new_item);
extern int mu_list_replace_nd (mu_list_t list, void *old_item, void *new_item);
extern int mu_list_get (mu_list_t, size_t _index, void **pitem);
extern int mu_list_to_array (mu_list_t list, void **array, size_t count, size_t *pcount);
extern int mu_list_locate (mu_list_t list, void *item, void **ret_item);
......@@ -55,8 +57,10 @@ extern int mu_list_get_comparator (mu_list_t, mu_list_comparator_t *);
extern void mu_list_free_item (void *item);
extern int mu_list_set_destroy_item (mu_list_t list,
void (*destroy_item) (void *));
typedef void (*mu_list_destroy_item_t) (void *);
extern mu_list_destroy_item_t mu_list_set_destroy_item
(mu_list_t list, mu_list_destroy_item_t destroy_item);
extern int mu_list_intersect_dup (mu_list_t *, mu_list_t, mu_list_t,
......
......@@ -21,6 +21,7 @@
#endif
#include "cmdline.h"
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <mailutils/syslog.h>
#include <mailutils/mailbox.h>
......
......@@ -215,12 +215,10 @@ List :: set_comparator (mu_list_comparator_t comp)
return mu_list_set_comparator (mu_list, comp);
}
void
List :: set_destroy_item (void (*mu_destroy_item) (void *item))
mu_list_destroy_item_t
List :: set_destroy_item (mu_list_destroy_item_t mu_destroy_item)
{
int status = mu_list_set_destroy_item (mu_list, mu_destroy_item);
if (status)
throw Exception ("List::set_destroy_item", status);
return mu_list_set_destroy_item (mu_list, mu_destroy_item);
}
std::list<void*>
......
......@@ -96,7 +96,6 @@ mu_sieve_prealloc (mu_list_t *pool, void *ptr, size_t size)
void
mu_sieve_pfree (mu_list_t *pool, void *ptr)
{
if (*pool)
mu_list_remove (*pool, ptr);
free (ptr);
......
......@@ -587,55 +587,39 @@ util_slist_lookup (mu_list_t list, const char *str)
return rc;
}
void
util_slist_add (mu_list_t *list, char *value)
static int
util_slist_compare (const void *a, const void *b)
{
char *p;
return mu_c_strcasecmp (a, b);
}
if (!*list && mu_list_create (list))
return;
void
util_slist_add (mu_list_t *plist, char *value)
{
mu_list_t list;
if ((p = strdup(value)) == NULL)
if (!*plist)
{
util_error(_("Not enough memory"));
if (mu_list_create (&list))
return;
mu_list_set_destroy_item (list, mu_list_free_item);
mu_list_set_comparator (list, util_slist_compare);
*plist = list;
}
mu_list_append (*list, p);
}
static int
comp (const void *item, const void *data)
{
return strcmp ((char*)item, (char*)data);
else
list = *plist;
mu_list_append (list, xstrdup (value));
}
void
util_slist_remove (mu_list_t *list, char *value)
{
mu_list_comparator_t cp;
if (!*list)
return;
cp = mu_list_set_comparator (*list, comp);
mu_list_remove (*list, value);
mu_list_set_comparator (*list, cp);
}
void
util_slist_destroy (mu_list_t *list)
{
mu_iterator_t itr;
char *name;
if (!*list || mu_list_get_iterator (*list, &itr))
return;
for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
{
mu_iterator_current (itr, (void **)&name);
free (name);
}
mu_iterator_destroy (&itr);
mu_list_destroy (list);
}
......@@ -649,12 +633,13 @@ util_slist_to_string (mu_list_t list, const char *delim)
if (!list || mu_list_get_iterator (list, &itr))
return NULL;
for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
{
mu_iterator_current (itr, (void **)&name);
if (str && delim)
util_strcat(&str, delim);
util_strcat(&str, name);
util_strcat (&str, delim);
util_strcat (&str, name);
}
mu_iterator_destroy (&itr);
return str;
......
......@@ -29,6 +29,14 @@
#include <iterator0.h>
#include <mailutils/errno.h>
#define DESTROY_ITEM(list, elt) \
do \
{ \
if ((list)->destroy_item) \
(list)->destroy_item ((elt)->item); \
} \
while (0)
int
mu_list_create (mu_list_t *plist)
{
......@@ -66,8 +74,7 @@ mu_list_destroy (mu_list_t *plist)
{
previous = current;
current = current->next;
if (list->destroy_item)
list->destroy_item (previous->item);
DESTROY_ITEM (list, previous);
free (previous);
}
mu_monitor_unlock (list->monitor);
......@@ -263,7 +270,7 @@ mu_list_remove (mu_list_t list, void *item)
mu_iterator_advance (list->itr, current);
previous->next = current->next;
current->next->prev = previous;
/* FIXME: Call destroy_item */
DESTROY_ITEM (list, current);
free (current);
list->count--;
status = 0;
......@@ -275,6 +282,15 @@ mu_list_remove (mu_list_t list, void *item)
}
int
mu_list_remove_nd (mu_list_t list, void *item)
{
mu_list_destroy_item_t dptr = mu_list_set_destroy_item (list, NULL);
int rc = mu_list_remove (list, item);
mu_list_set_destroy_item (list, dptr);
return rc;
}
int
mu_list_replace (mu_list_t list, void *old_item, void *new_item)
{
struct list_data *current, *previous;
......@@ -290,7 +306,7 @@ mu_list_replace (mu_list_t list, void *old_item, void *new_item)
{
if (comp (current->item, old_item) == 0)
{
/* FIXME: Call destroy_item. Perhaps optionally? */
DESTROY_ITEM (list, current);
current->item = new_item;
status = 0;
break;
......@@ -301,6 +317,15 @@ mu_list_replace (mu_list_t list, void *old_item, void *new_item)
}
int
mu_list_replace_nd (mu_list_t list, void *item, void *new_item)
{
mu_list_destroy_item_t dptr = mu_list_set_destroy_item (list, NULL);
int rc = mu_list_replace (list, item, new_item);
mu_list_set_destroy_item (list, dptr);
return rc;
}
int
mu_list_get (mu_list_t list, size_t indx, void **pitem)
{
struct list_data *current;
......@@ -349,13 +374,12 @@ mu_list_do (mu_list_t list, mu_list_action_t *action, void *cbdata)
return status;
}
int
mu_list_destroy_item_t
mu_list_set_destroy_item (mu_list_t list, void (*destroy_item)(void *item))
{
if (list == NULL)
return EINVAL;
mu_list_destroy_item_t ret = list->destroy_item;
list->destroy_item = destroy_item;
return 0;
return ret;
}
int
......@@ -545,6 +569,7 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
}
case mu_itrctl_delete:
case mu_itrctl_delete_nd:
/* Delete current element */
{
struct list_data *prev;
......@@ -555,17 +580,20 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
mu_iterator_advance (list->itr, ptr);
prev->next = ptr->next;
ptr->next->prev = prev;
/* FIXME: Call destroy_item */
if (req == mu_itrctl_delete)
DESTROY_ITEM (list, ptr);
free (ptr);
list->count--;
}
break;
case mu_itrctl_replace:
case mu_itrctl_replace_nd:
/* Replace current element */
if (!arg)
return EINVAL;
/* FIXME: Call destroy_item. Perhaps optionally? */
if (req == mu_itrctl_replace)
DESTROY_ITEM (list, ptr);
ptr = itr->cur;
ptr->item = arg;
break;
......
......@@ -119,6 +119,14 @@ mu_observer_set_flags (mu_observer_t observer, int flags)
return 0;
}
static void
_free_event (void *ptr)
{
event_t event = ptr;
mu_observer_destroy (&event->observer, NULL);
free (event);
}
int
mu_observable_create (mu_observable_t *pobservable, void *owner)
{
......@@ -129,12 +137,13 @@ mu_observable_create (mu_observable_t *pobservable, void *owner)
observable = calloc (sizeof (*observable), 1);
if (observable == NULL)
return ENOMEM;
status = mu_list_create (&(observable->list));
status = mu_list_create (&observable->list);
if (status != 0 )
{
free (observable);
return status;
}
mu_list_set_destroy_item (observable->list, _free_event);
observable->owner = owner;
*pobservable = observable;
return 0;
......@@ -143,31 +152,13 @@ mu_observable_create (mu_observable_t *pobservable, void *owner)
void
mu_observable_destroy (mu_observable_t *pobservable, void *owner)
{
mu_iterator_t iterator;
if (pobservable && *pobservable)
{
mu_observable_t observable = *pobservable;
if (observable->owner == owner)
{
int status = mu_list_get_iterator (observable->list, &iterator);
if (status == 0)
{
event_t event = NULL;
for (mu_iterator_first (iterator); !mu_iterator_is_done (iterator);
mu_iterator_next (iterator))
{
event = NULL;
mu_iterator_current (iterator, (void **)&event);
if (event != NULL)
{
mu_observer_destroy (&(event->observer), NULL);
free (event);
}
}
mu_iterator_destroy (&iterator);
}
mu_list_destroy (&((*pobservable)->list));
free (*pobservable);
mu_list_destroy (&observable->list);
free (observable);
}
*pobservable = NULL;
}
......@@ -198,13 +189,14 @@ mu_observable_detach (mu_observable_t observable, mu_observer_t observer)
{
mu_iterator_t iterator;
int status;
int found = 0;
event_t event = NULL;
if (observable == NULL || observer == NULL)
return EINVAL;
status = mu_list_get_iterator (observable->list, &iterator);
if (status != 0)
return status;
status = MU_ERR_NOENT;
for (mu_iterator_first (iterator); !mu_iterator_is_done (iterator);
mu_iterator_next (iterator))
{
......@@ -212,18 +204,12 @@ mu_observable_detach (mu_observable_t observable, mu_observer_t observer)
mu_iterator_current (iterator, (void **)&event);
if (event && event->observer == observer)
{
found = 1;
mu_iterator_ctl (iterator, mu_itrctl_delete, NULL);
status = 0;
break;
}
}
mu_iterator_destroy (&iterator);
if (found)
{
status = mu_list_remove (observable->list, event);
free (event);
}
else
status = MU_ERR_NOENT;
return status;
}
......
......@@ -262,26 +262,6 @@ aliascmp (const char *pattern, const char *name)
return strcmp (pattern, name);
}
int
_insert_list (mu_list_t list, void *prev, mu_list_t new_list)
{
mu_iterator_t itr;
if (mu_list_get_iterator (new_list, &itr))
return 1;
for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
{
void *item;
mu_iterator_current (itr, &item);
mu_list_insert (list, prev, item, 0);
prev = item;
}
mu_iterator_destroy (&itr);
return 0;
}
static int mh_alias_get_internal (const char *name, mu_iterator_t start,
mu_list_t *return_list, int *inclusive);
......@@ -300,9 +280,11 @@ alias_expand_list (mu_list_t name_list, mu_iterator_t orig_itr, int *inclusive)
mu_iterator_current (itr, (void **)&name);
if (mh_alias_get_internal (name, orig_itr, &exlist, inclusive) == 0)
{
_insert_list (name_list, name, exlist);
mu_list_remove (name_list, name);
/* Insert exlist after name */
mu_iterator_ctl (itr, mu_itrctl_insert_list, exlist);
mu_list_destroy (&exlist);
/* Remove name */
mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
}
}
mu_iterator_destroy (&itr);
......
......@@ -215,11 +215,15 @@ addop (char *field, compfun comp)
{
struct comp_op *op = xmalloc (sizeof (*op));
if (!oplist && mu_list_create (&oplist))
if (!oplist)
{
if (mu_list_create (&oplist))
{
mu_error (_("can't create operation list"));
exit (1);
}
mu_list_set_destroy_item (oplist, mu_list_free_item);
}
op->field = field;
op->comp = comp;
mu_list_append (oplist, op);
......@@ -248,7 +252,6 @@ remop (compfun comp)
d.op = NULL;
mu_list_do (oplist, rem_action, &d);
mu_list_remove (oplist, d.op);
free (d.op);
}
struct comp_data {
......
......@@ -731,7 +731,6 @@ main (int argc, char **argv)
if (rc)
die (dest, _("cannot get UIDLs"), rc);
mu_list_set_comparator (src_uidl_list, NULL);
mu_list_set_comparator (dst_uidl_list, _compare_uidls);
mu_list_get_iterator (src_uidl_list, &itr);
......@@ -742,7 +741,7 @@ main (int argc, char **argv)
mu_iterator_current (itr, (void **)&uidl);
if (mu_list_locate (dst_uidl_list, uidl, NULL) == 0)
mu_list_remove (src_uidl_list, uidl);
mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
}
mu_iterator_destroy (&itr);
mu_list_destroy (&dst_uidl_list);
......