commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-449-ga736b7a


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-449-ga736b7a
Date: Fri, 18 Nov 2011 16:48:09 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=a736b7a9a775db4b82806a6214deefc3ac7a4dd4

The branch, master has been updated
       via  a736b7a9a775db4b82806a6214deefc3ac7a4dd4 (commit)
       via  e4a76054ba29cd5af1bc80a96089580d3515279a (commit)
       via  db7e58b41501fda7629080195e33946f6d26e2a3 (commit)
      from  f7942ced21d97774e678be261cc5b9094e47e8da (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a736b7a9a775db4b82806a6214deefc3ac7a4dd4
Author: Sergey Poznyakoff <address@hidden>
Date:   Fri Nov 18 18:47:50 2011 +0200

    imap client: redo capability and id support via list mappers.
    
    * libproto/imap/capability.c (mu_imap_capability): Use mu_list_map to
    create the capability list.
    * libproto/imap/id.c (_id_convert): Likewise for ID pairs.

commit e4a76054ba29cd5af1bc80a96089580d3515279a
Author: Sergey Poznyakoff <address@hidden>
Date:   Fri Nov 18 17:16:02 2011 +0200

    Implement list mapping.
    
    * include/mailutils/list.h (MU_LIST_MAP_OK)
    (MU_LIST_MAP_SKIP,MU_LIST_MAP_STOP): New constants.
    (mu_list_mapper_t): New typedef.
    (mu_list_map): New proto.
    * libmailutils/list/gmap.c: New file.
    * libmailutils/list/map.c: New file.
    * libmailutils/list/Makefile.am: Add gmap.c and map.c
    * libmailutils/tests/listop.c: New command "map".
    * libmailutils/tests/list.at: Test the list mapping.

commit db7e58b41501fda7629080195e33946f6d26e2a3
Author: Sergey Poznyakoff <address@hidden>
Date:   Fri Nov 18 13:35:30 2011 +0200

    Move list support into a separate convenience library.
    
    * configure.ac: Build libmailutils/list/Makefile
    * include/mailutils/sys/list.h (DESTROY_ITEM): New define.
    (_mu_list_insert_item): New proto.
    * libmailutils/Makefile.am (SUBDIRS): Add list.
    (libmailutils_la_LIBADD): Add list/liblist.la
    * libmailutils/base/Makefile.am (libbase_la_SOURCES): Remove list sources.
    * libmailutils/base/list.c: Split into smaller files (see below).
    * libmailutils/base/listlist.c: Move to libmailutils/list/listlist.c
    * libmailutils/list/Makefile.am: New file.
    * libmailutils/list/append.c: New file.
    * libmailutils/list/array.c: New file.
    * libmailutils/list/clear.c: New file.
    * libmailutils/list/count.c: New file.
    * libmailutils/list/create.c: New file.
    * libmailutils/list/destroy.c: New file.
    * libmailutils/list/do.c: New file.
    * libmailutils/list/empty.c: New file.
    * libmailutils/list/get.c: New file.
    * libmailutils/list/getcomp.c: New file.
    * libmailutils/list/insert.c: New file.
    * libmailutils/list/intersect.c: New file.
    * libmailutils/list/iterator.c: New file.
    * libmailutils/list/locate.c: New file.
    * libmailutils/list/prepend.c: New file.
    * libmailutils/list/remove.c: New file.
    * libmailutils/list/replace.c: New file.
    * libmailutils/list/setcomp.c: New file.
    * libmailutils/list/setdestr.c: New file.

-----------------------------------------------------------------------

Summary of changes:
 configure.ac                                       |    1 +
 include/mailutils/list.h                           |   44 ++
 include/mailutils/sys/list.h                       |   11 +
 libmailutils/Makefile.am                           |    7 +-
 libmailutils/base/Makefile.am                      |    2 -
 libmailutils/base/list.c                           |  705 --------------------
 libmailutils/{sockaddr => list}/Makefile.am        |   32 +-
 libmailutils/{property/propitr.c => list/append.c} |   33 +-
 libmailutils/{property/propitr.c => list/array.c}  |   34 +-
 libmailutils/{property/propitr.c => list/clear.c}  |   33 +-
 libmailutils/{property/propitr.c => list/count.c}  |   21 +-
 libmailutils/{property/propitr.c => list/create.c} |   33 +-
 .../{property/propitr.c => list/destroy.c}         |   26 +-
 libmailutils/{property/propitr.c => list/do.c}     |   33 +-
 libmailutils/{url/urlinv.c => list/empty.c}        |   18 +-
 libmailutils/{property/propitr.c => list/get.c}    |   36 +-
 libmailutils/{url/urlinv.c => list/getcomp.c}      |   15 +-
 libmailutils/{property/propset.c => list/gmap.c}   |   75 +--
 libmailutils/list/insert.c                         |   72 ++
 libmailutils/list/intersect.c                      |   90 +++
 libmailutils/list/iterator.c                       |  250 +++++++
 libmailutils/{base => list}/listlist.c             |    4 -
 libmailutils/{property/propitr.c => list/locate.c} |   43 +-
 libmailutils/list/map.c                            |   87 +++
 .../{property/propitr.c => list/prepend.c}         |   32 +-
 libmailutils/list/remove.c                         |   66 ++
 .../{property/propset.c => list/replace.c}         |   65 +-
 .../{property/propitr.c => list/setcomp.c}         |   25 +-
 .../{property/propitr.c => list/setdestr.c}        |   21 +-
 libmailutils/tests/list.at                         |   80 +++-
 libmailutils/tests/listop.c                        |  202 ++++++-
 libproto/imap/capability.c                         |   46 +-
 libproto/imap/id.c                                 |   41 +-
 33 files changed, 1277 insertions(+), 1006 deletions(-)
 delete mode 100644 libmailutils/base/list.c
 copy libmailutils/{sockaddr => list}/Makefile.am (75%)
 copy libmailutils/{property/propitr.c => list/append.c} (62%)
 copy libmailutils/{property/propitr.c => list/array.c} (64%)
 copy libmailutils/{property/propitr.c => list/clear.c} (63%)
 copy libmailutils/{property/propitr.c => list/count.c} (74%)
 copy libmailutils/{property/propitr.c => list/create.c} (64%)
 copy libmailutils/{property/propitr.c => list/destroy.c} (71%)
 copy libmailutils/{property/propitr.c => list/do.c} (61%)
 copy libmailutils/{url/urlinv.c => list/empty.c} (76%)
 copy libmailutils/{property/propitr.c => list/get.c} (59%)
 copy libmailutils/{url/urlinv.c => list/getcomp.c} (75%)
 copy libmailutils/{property/propset.c => list/gmap.c} (51%)
 create mode 100644 libmailutils/list/insert.c
 create mode 100644 libmailutils/list/intersect.c
 create mode 100644 libmailutils/list/iterator.c
 rename libmailutils/{base => list}/listlist.c (98%)
 copy libmailutils/{property/propitr.c => list/locate.c} (53%)
 create mode 100644 libmailutils/list/map.c
 copy libmailutils/{property/propitr.c => list/prepend.c} (61%)
 create mode 100644 libmailutils/list/remove.c
 copy libmailutils/{property/propset.c => list/replace.c} (50%)
 copy libmailutils/{property/propitr.c => list/setcomp.c} (71%)
 copy libmailutils/{property/propitr.c => list/setdestr.c} (71%)

diff --git a/configure.ac b/configure.ac
index 7251453..f28c42b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1473,6 +1473,7 @@ AC_CONFIG_FILES([
  libmailutils/diag/Makefile
  libmailutils/filter/Makefile
  libmailutils/imapio/Makefile
+ libmailutils/list/Makefile
  libmailutils/mailbox/Makefile
  libmailutils/mailer/Makefile
  libmailutils/mime/Makefile
diff --git a/include/mailutils/list.h b/include/mailutils/list.h
index d6f3f45..becf280 100644
--- a/include/mailutils/list.h
+++ b/include/mailutils/list.h
@@ -72,7 +72,51 @@ extern int mu_list_insert_list (mu_list_t list, void *item, 
mu_list_t new_list,
                                int insert_before);
 extern void mu_list_append_list (mu_list_t list, mu_list_t new_list);
 extern void mu_list_prepend_list (mu_list_t list, mu_list_t new_list);
+
+/* List mapper functions */
+typedef int (*mu_list_mapper_t) (void **itmv, size_t itmc, void *call_data);
+
+/* A generalized list mapping function.
+
+   Mu_list_gmap iterates over the LIST, gathering its elements in an
+   array of type void **.  When NELEM elements has been collected, it
+   calls the MAP function, passing it as arguments the constructed array,
+   number of elements in it (can be less than NELEM on the last call),
+   and call-specific DATA.  Iteration continues while MAP returns 0 and
+   until all elements from the array have been visited.
+
+   Mu_list_gmap returns 0 on success and a non-zero error code on failure.
+   If MAP returns !0, its return value is propagated to the caller.
+*/
+   
+int mu_list_gmap (mu_list_t list, mu_list_mapper_t map, size_t nelem,
+                 void *data);
   
+  
+#define MU_LIST_MAP_OK     0x00
+#define MU_LIST_MAP_SKIP   0x01
+#define MU_LIST_MAP_STOP   0x02
+
+/* List-to-list mapping.
+   
+   Apply the list mapping function MAP to each NELEM elements from the source
+   LIST and use its return values to form a new list, which will be returned
+   in RES.
+
+   MAP gets pointers to the collected elements in its first argument (ITMV).
+   Its second argument (ITMC) gives the number of elements filled in ARR.
+   It can be less than NELEM on the last call to MAP.  The DATA pointer is
+   passed as the 3rd argument.
+
+   Return value from MAP governs the mapping process.  Unless it has the
+   MU_LIST_MAP_SKIP bit set, the itmv[0] element is appended to the new
+   list.  If it has MU_LIST_MAP_STOP bit set, iteration is stopped
+   immediately and any remaining elements in LIST are ignored.
+*/
+
+int mu_list_map (mu_list_t list, mu_list_mapper_t map,
+                void *data, size_t nelem,
+                mu_list_t *res);
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mailutils/sys/list.h b/include/mailutils/sys/list.h
index ba00ae7..6769e78 100644
--- a/include/mailutils/sys/list.h
+++ b/include/mailutils/sys/list.h
@@ -46,6 +46,14 @@ struct _mu_list
   struct _mu_iterator *itr;
 };
 
+#define DESTROY_ITEM(list, elt)                        \
+  do                                           \
+    {                                          \
+       if ((list)->destroy_item)               \
+        (list)->destroy_item ((elt)->item);    \
+    }                                          \
+  while (0)
+
 extern void _mu_list_clear (mu_list_t list);
 extern void _mu_list_insert_sublist (mu_list_t list,
                                     struct list_data *current,
@@ -53,6 +61,9 @@ extern void _mu_list_insert_sublist (mu_list_t list,
                                     struct list_data *tail,
                                     size_t count,
                                     int insert_before);
+extern int _mu_list_insert_item (mu_list_t list, struct list_data *current,
+                                void *new_item,
+                                int insert_before);
 
 # ifdef __cplusplus
 }
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index 7c1c5c4..b321382 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -16,8 +16,10 @@
 # Public License along with this library.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-SUBDIRS = auth base address sockaddr cidr cfg diag filter mailbox mailer mime\
- server string stream stdstream property url imapio . tests 
+SUBDIRS = \
+ auth base address list sockaddr cidr cfg diag\
+ filter mailbox mailer mime server string stream stdstream\
+ property url imapio . tests 
 
 lib_LTLIBRARIES = libmailutils.la
 
@@ -34,6 +36,7 @@ libmailutils_la_LIBADD = \
  diag/libdiag.la\
  filter/libfilter.la\
  imapio/libimapio.la\
+ list/liblist.la\
  mailbox/libmailbox.la\
  mailer/libmailer.la\
  mime/libmime.la\
diff --git a/libmailutils/base/Makefile.am b/libmailutils/base/Makefile.am
index 5f41b0c..cb6c521 100644
--- a/libmailutils/base/Makefile.am
+++ b/libmailutils/base/Makefile.am
@@ -39,8 +39,6 @@ libbase_la_SOURCES = \
  iterator.c\
  kwd.c\
  lcall.c\
- list.c\
- listlist.c\
  locale.c\
  locker.c\
  mailcap.c\
diff --git a/libmailutils/base/list.c b/libmailutils/base/list.c
deleted file mode 100644
index 74ec644..0000000
--- a/libmailutils/base/list.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 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 
-   <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mailutils/sys/list.h>
-#include <mailutils/sys/iterator.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)
-{
-  mu_list_t list;
-  int status;
-
-  if (plist == NULL)
-    return MU_ERR_OUT_PTR_NULL;
-  list = calloc (sizeof (*list), 1);
-  if (list == NULL)
-    return ENOMEM;
-  status = mu_monitor_create (&list->monitor, 0,  list);
-  if (status != 0)
-    {
-      free (list);
-      return status;
-    }
-  list->head.next = &list->head;
-  list->head.prev = &list->head;
-  *plist = list;
-  return 0;
-}
-
-void
-mu_list_clear (mu_list_t list)
-{
-  struct list_data *current;
-  struct list_data *previous;
-
-  if (!list)
-    return;
-  mu_monitor_wrlock (list->monitor);
-  for (current = list->head.next; current != &list->head;)
-    {
-      previous = current;
-      current = current->next;
-      DESTROY_ITEM (list, previous);
-      free (previous);
-    }
-  list->head.next = list->head.prev = &list->head;
-  mu_monitor_unlock (list->monitor);
-}
-
-void
-mu_list_destroy (mu_list_t *plist)
-{
-  if (plist && *plist)
-    {
-      mu_list_t list = *plist;
-      mu_list_clear (list);
-      mu_monitor_destroy (&list->monitor, list);
-      free (list);
-      *plist = NULL;
-    }
-}
-
-int
-mu_list_append (mu_list_t list, void *item)
-{
-  struct list_data *ldata;
-  struct list_data *last;
-
-  if (list == NULL)
-    return EINVAL;
-  last = list->head.prev;
-  ldata = calloc (sizeof (*ldata), 1);
-  if (ldata == NULL)
-    return ENOMEM;
-  ldata->item = item;
-  mu_monitor_wrlock (list->monitor);
-  ldata->next = &list->head;
-  ldata->prev = list->head.prev;
-  last->next = ldata;
-  list->head.prev = ldata;
-  list->count++;
-  mu_monitor_unlock (list->monitor);
-  return 0;
-}
-
-int
-mu_list_prepend (mu_list_t list, void *item)
-{
-  struct list_data *ldata;
-  struct list_data *first;
-
-  if (list == NULL)
-    return EINVAL;
-  first = list->head.next;
-  ldata = calloc (sizeof (*ldata), 1);
-  if (ldata == NULL)
-    return ENOMEM;
-  ldata->item = item;
-  mu_monitor_wrlock (list->monitor);
-  ldata->prev = &list->head;
-  ldata->next = list->head.next;
-  first->prev = ldata;
-  list->head.next = ldata;
-  list->count++;
-  mu_monitor_unlock (list->monitor);
-  return 0;
-}
-
-int
-mu_list_is_empty (mu_list_t list)
-{
-  size_t n = 0;
-
-  mu_list_count (list, &n);
-  return (n == 0);
-}
-
-int
-mu_list_count (mu_list_t list, size_t *pcount)
-{
-  if (list == NULL)
-    return EINVAL;
-  if (pcount == NULL)
-    return MU_ERR_OUT_PTR_NULL;
-  *pcount = list->count;
-  return 0;
-}
-
-mu_list_comparator_t
-mu_list_set_comparator (mu_list_t list, mu_list_comparator_t comp)
-{
-  mu_list_comparator_t old_comp;
-
-  if (list == NULL)
-    return NULL;
-  old_comp = list->comp;
-  list->comp = comp;
-  return old_comp;
-}
-
-int
-mu_list_get_comparator (mu_list_t list, mu_list_comparator_t *comp)
-{
-  if (!list)
-    return EINVAL;
-  *comp = list->comp;
-  return 0;
-}
-
-int
-_mu_list_ptr_comparator (const void *item, const void *value)
-{
-  return item != value;
-}
-
-int
-mu_list_locate (mu_list_t list, void *item, void **ret_item)
-{
-  struct list_data *current, *previous;
-  mu_list_comparator_t comp;
-  int status = MU_ERR_NOENT;
-
-  if (list == NULL)
-    return EINVAL;
-  comp = list->comp ? list->comp : _mu_list_ptr_comparator;
-  mu_monitor_wrlock (list->monitor);
-  for (previous = &list->head, current = list->head.next;
-       current != &list->head; previous = current, current = current->next)
-    {
-      if (comp (current->item, item) == 0)
-       {
-         if (ret_item)
-           *ret_item = current->item;
-         status = 0;
-         break;
-       }
-    }
-  mu_monitor_unlock (list->monitor);
-  return status;
-}
-
-static int
-_insert_item (mu_list_t list, struct list_data *current, void *new_item,
-             int insert_before)
-{
-  int status;
-  struct list_data *ldata = calloc (sizeof (*ldata), 1);
-  if (ldata == NULL)
-    status = ENOMEM;
-  else
-    {
-      ldata->item = new_item;
-      _mu_list_insert_sublist (list, current,
-                              ldata, ldata,
-                              1,
-                              insert_before);
-      status = 0;
-    }
-  return status;
-}
-
-int
-mu_list_insert (mu_list_t list, void *item, void *new_item, int insert_before)
-{
-  struct list_data *current;
-  mu_list_comparator_t comp;
-  int status = MU_ERR_NOENT;
-
-  if (list == NULL)
-    return EINVAL;
-  comp = list->comp ? list->comp : _mu_list_ptr_comparator;
-
-  mu_monitor_wrlock (list->monitor);
-  for (current = list->head.next;
-       current != &list->head;
-       current = current->next)
-    {
-      if (comp (current->item, item) == 0)
-       {
-         status = _insert_item (list, current, new_item, insert_before);
-         break;
-       }
-    }
-  mu_monitor_unlock (list->monitor);
-  return status;
-}
-
-int
-mu_list_remove (mu_list_t list, void *item)
-{
-  struct list_data *current;
-  mu_list_comparator_t comp;
-  int status = MU_ERR_NOENT;
-
-  if (list == NULL)
-    return EINVAL;
-  comp = list->comp ? list->comp : _mu_list_ptr_comparator;
-  mu_monitor_wrlock (list->monitor);
-  for (current = list->head.next;
-       current != &list->head; current = current->next)
-    {
-      if (comp (current->item, item) == 0)
-       {
-         struct list_data *previous = current->prev;
-         
-         mu_iterator_advance (list->itr, current);
-         previous->next = current->next;
-         current->next->prev = previous;
-         DESTROY_ITEM (list, current);
-         free (current);
-         list->count--;
-         status = 0;
-         break;
-       }
-    }
-  mu_monitor_unlock (list->monitor);
-  return status;
-}
-
-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;
-  mu_list_comparator_t comp;
-  int status = MU_ERR_NOENT;
-
-  if (list == NULL)
-    return EINVAL;
-  comp = list->comp ? list->comp : _mu_list_ptr_comparator;
-  mu_monitor_wrlock (list->monitor);
-  for (previous = &list->head, current = list->head.next;
-       current != &list->head; previous = current, current = current->next)
-    {
-      if (comp (current->item, old_item) == 0)
-       {
-         DESTROY_ITEM (list, current);
-         current->item = new_item;
-         status = 0;
-         break;
-       }
-    }
-  mu_monitor_unlock (list->monitor);
-  return status;
-}
-
-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;
-  size_t count;
-  int status = MU_ERR_NOENT;
-
-  if (list == NULL)
-    return EINVAL;
-  if (pitem == NULL)
-    return MU_ERR_OUT_PTR_NULL;
-  mu_monitor_rdlock (list->monitor);
-  for (current = list->head.next, count = 0; current != &list->head;
-       current = current->next, count++)
-    {
-      if (count == indx)
-        {
-          *pitem = current->item;
-         status = 0;
-         break;
-        }
-    }
-  mu_monitor_unlock (list->monitor);
-  return status;
-}
-
-int
-mu_list_do (mu_list_t list, mu_list_action_t *action, void *cbdata)
-{
-  mu_iterator_t itr;
-  int status = 0;
-
-  if (list == NULL || action == NULL)
-    return EINVAL;
-  status = mu_list_get_iterator (list, &itr);
-  if (status)
-    return status;
-  for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
-       mu_iterator_next (itr))
-    {
-      void *item;
-      mu_iterator_current (itr, &item);
-      if ((status = action (item, cbdata)))
-       break;
-    }
-  mu_iterator_destroy (&itr);
-  return status;
-}
-
-mu_list_destroy_item_t
-mu_list_set_destroy_item (mu_list_t list, void (*destroy_item)(void *item))
-{
-  mu_list_destroy_item_t ret = list->destroy_item;
-  list->destroy_item = destroy_item;
-  return ret;
-}
-
-int
-mu_list_to_array (mu_list_t list, void **array, size_t count, size_t *pcount)
-{
-  size_t total = 0;
-
-  if (!list)
-    return EINVAL;
-
-  total = (count < list->count) ? count : list->count;
-
-  if (array)
-    {
-      size_t i;
-      struct list_data *current;
-
-      for (i = 0, current = list->head.next;
-          i < total && current != &list->head; current = current->next)
-       array[i++] = current->item;
-    }
-  if (pcount)
-    *pcount = total;
-  return 0;
-}
-
-/* Computes an intersection of two lists and returns it in PDEST.
-   The resulting list contains elements from A that are
-   also encountered in B (as per comparison function of
-   the latter).
-
-   If DUP_ITEM is not NULL, it is used to create copies of
-   items to be stored in PDEST.  In this case, the destroy_item
-   function of B is also attached to PDEST.  Otherwise, if
-   DUP_ITEM is NULL, pointers to elements are stored and
-   no destroy_item function is assigned. */
-int
-mu_list_intersect_dup (mu_list_t *pdest, mu_list_t a, mu_list_t b,
-                      int (*dup_item) (void **, void *, void *),
-                      void *dup_closure)
-{
-  mu_list_t dest;
-  int rc;
-  mu_iterator_t itr;
-  
-  rc = mu_list_create (&dest);
-  if (rc)
-    return rc;
-
-  mu_list_set_comparator (dest, b->comp);
-  if (dup_item)
-    mu_list_set_destroy_item (dest, b->destroy_item);
-  
-  rc = mu_list_get_iterator (a, &itr);
-  if (rc)
-    {
-      mu_list_destroy (&dest);
-      return rc;
-    }
-
-  rc = 0;
-  for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
-       mu_iterator_next (itr))
-    {
-      void *data;
-      mu_iterator_current (itr, &data);
-      if (mu_list_locate (b, data, NULL) == 0)
-       {
-         void *new_data;
-         if (dup_item && data)
-           {
-             rc = dup_item (&new_data, data, dup_closure);
-             if (rc)
-               break;
-           }
-         else
-           new_data = data;
-       
-         mu_list_append (dest, new_data); /* FIXME: Check return, and? */
-       }
-    }
-  mu_iterator_destroy (&itr);
-  *pdest = dest;
-  return rc;
-}
-
-int
-mu_list_intersect (mu_list_t *pdest, mu_list_t a, mu_list_t b)
-{
-  return mu_list_intersect_dup (pdest, a, b, NULL, NULL);
-}
-
-
-/* Iterator interface */
-
-struct list_iterator
-{
-  mu_list_t list;
-  struct list_data *cur;
-  int backwards; /* true if iterating backwards */
-};
-
-static int
-first (void *owner)
-{
-  struct list_iterator *itr = owner;
-  if (itr->backwards)
-    itr->cur = itr->list->head.prev;
-  else
-    itr->cur = itr->list->head.next;
-  return 0;
-}
-
-static int
-next (void *owner)
-{
-  struct list_iterator *itr = owner;
-  if (itr->backwards)
-    itr->cur = itr->cur->prev;
-  else
-    itr->cur = itr->cur->next;
-  return 0;
-}
-
-static int
-getitem (void *owner, void **pret, const void **pkey)
-{
-  struct list_iterator *itr = owner;
-  *pret = itr->cur->item;
-  if (pkey)
-    *pkey = NULL;
-  return 0;
-}
-
-static int
-finished_p (void *owner)
-{
-  struct list_iterator *itr = owner;
-  return itr->cur == &itr->list->head;
-}
-
-static int
-destroy (mu_iterator_t iterator, void *data)
-{
-  struct list_iterator *itr = data;
-  mu_iterator_detach (&itr->list->itr, iterator);
-  free (data);
-  return 0;
-}
-
-static int
-curitem_p (void *owner, void *item)
-{
-  struct list_iterator *itr = owner;
-  return itr->cur == item;
-}
-
-static int
-list_data_dup (void **ptr, void *owner)
-{
-  *ptr = malloc (sizeof (struct list_iterator));
-  if (*ptr == NULL)
-    return ENOMEM;
-  memcpy (*ptr, owner, sizeof (struct list_iterator));
-  return 0;
-}
-
-static int
-list_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
-{
-  struct list_iterator *itr = owner;
-  mu_list_t list = itr->list;
-  struct list_data *ptr;
-  
-  switch (req)
-    {
-    case mu_itrctl_tell:
-      /* Return current position in the object */
-      if (itr->cur == NULL)
-       return MU_ERR_NOENT;
-      else
-       {
-         size_t count;
-
-         for (count = 0, ptr = list->head.next; ptr != &list->head;
-              ptr = ptr->next, count++)
-           {
-             if (ptr == itr->cur)
-               {
-                 *(size_t*)arg = count;
-                 return 0;
-               }
-           }
-         return MU_ERR_NOENT;
-       }
-      break;
-      
-    case mu_itrctl_delete:
-    case mu_itrctl_delete_nd:
-      /* Delete current element */
-      if (itr->cur == NULL)
-       return MU_ERR_NOENT;
-      else
-       {
-         struct list_data *prev;
-       
-         ptr = itr->cur;
-         prev = ptr->prev;
-       
-         mu_iterator_advance (list->itr, ptr);
-         prev->next = ptr->next;
-         ptr->next->prev = prev;
-         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 (itr->cur == NULL)
-       return MU_ERR_NOENT;
-      if (!arg)
-       return EINVAL;
-      ptr = itr->cur;
-      if (req == mu_itrctl_replace)
-         DESTROY_ITEM (list, ptr);
-      ptr = itr->cur;
-      ptr->item = arg;
-      break;
-      
-    case mu_itrctl_insert:
-      /* Insert new element in the current position */
-      if (itr->cur == NULL)
-       return MU_ERR_NOENT;
-      if (!arg)
-       return EINVAL;
-      return _insert_item (list, itr->cur, arg, 0);
-
-    case mu_itrctl_insert_list:
-      /* Insert a list of elements */
-      if (itr->cur == NULL)
-       return MU_ERR_NOENT;
-      if (!arg)
-       return EINVAL;
-      else
-       {
-         mu_list_t new_list = arg;
-         _mu_list_insert_sublist (list, itr->cur,
-                                  new_list->head.next, new_list->head.prev,
-                                  new_list->count,
-                                  0);
-         _mu_list_clear (new_list);
-       }
-      break;
-
-    case mu_itrctl_qry_direction:
-      if (!arg)
-       return EINVAL;
-      else
-       *(int*)arg = itr->backwards;
-      break;
-
-    case mu_itrctl_set_direction:
-      if (!arg)
-       return EINVAL;
-      else
-       itr->backwards = !!*(int*)arg;
-      break;
-      
-    default:
-      return ENOSYS;
-    }
-  return 0;
-}
-
-int
-mu_list_get_iterator (mu_list_t list, mu_iterator_t *piterator)
-{
-  mu_iterator_t iterator;
-  int status;
-  struct list_iterator *itr;
-
-  if (!list)
-    return EINVAL;
-
-  itr = calloc (1, sizeof *itr);
-  if (!itr)
-    return ENOMEM;
-  itr->list = list;
-  itr->cur = NULL;
-
-  status = mu_iterator_create (&iterator, itr);
-  if (status)
-    {
-      free (itr);
-      return status;
-    }
-
-  mu_iterator_set_first (iterator, first);
-  mu_iterator_set_next (iterator, next);
-  mu_iterator_set_getitem (iterator, getitem);
-  mu_iterator_set_finished_p (iterator, finished_p);
-  mu_iterator_set_curitem_p (iterator, curitem_p);
-  mu_iterator_set_destroy (iterator, destroy);
-  mu_iterator_set_dup (iterator, list_data_dup);
-  mu_iterator_set_itrctl (iterator, list_itrctl);
-  
-  mu_iterator_attach (&list->itr, iterator);
-
-  *piterator = iterator;
-  return 0;
-}
diff --git a/libmailutils/sockaddr/Makefile.am b/libmailutils/list/Makefile.am
similarity index 75%
copy from libmailutils/sockaddr/Makefile.am
copy to libmailutils/list/Makefile.am
index dcfb184..3b959fc 100644
--- a/libmailutils/sockaddr/Makefile.am
+++ b/libmailutils/list/Makefile.am
@@ -15,17 +15,31 @@
 # Public License along with this library.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-noinst_LTLIBRARIES = libsockaddr.la
+noinst_LTLIBRARIES = liblist.la
 
-libsockaddr_la_SOURCES = \
- copy.c\
+liblist_la_SOURCES = \
+ append.c\
+ array.c\
+ clear.c\
+ count.c\
  create.c\
- free.c\
- fromnode.c\
+ destroy.c\
+ do.c\
+ empty.c\
+ get.c\
+ getcomp.c\
+ gmap.c\
  insert.c\
- ipaddr.c\
- str.c\
- unlink.c\
- url.c
+ intersect.c\
+ iterator.c\
+ listlist.c\
+ locate.c\
+ map.c\
+ prepend.c\
+ remove.c\
+ replace.c\
+ setcomp.c\
+ setdestr.c
 
 INCLUDES = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
+
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/append.c
similarity index 62%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/append.c
index 0c3fd86..f514b3f 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/append.c
@@ -17,20 +17,31 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
-
-#include <mailutils/types.h>
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
 
 int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+mu_list_append (mu_list_t list, void *item)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  struct list_data *ldata;
+  struct list_data *last;
+
+  if (list == NULL)
+    return EINVAL;
+  last = list->head.prev;
+  ldata = calloc (sizeof (*ldata), 1);
+  if (ldata == NULL)
+    return ENOMEM;
+  ldata->item = item;
+  mu_monitor_wrlock (list->monitor);
+  ldata->next = &list->head;
+  ldata->prev = list->head.prev;
+  last->next = ldata;
+  list->head.prev = ldata;
+  list->count++;
+  mu_monitor_unlock (list->monitor);
+  return 0;
 }
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/array.c
similarity index 64%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/array.c
index 0c3fd86..65433af 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/array.c
@@ -17,20 +17,32 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
-
-#include <mailutils/types.h>
+#include <mailutils/sys/list.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
 
 int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+mu_list_to_array (mu_list_t list, void **array, size_t count, size_t *pcount)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  size_t total = 0;
+
+  if (!list)
+    return EINVAL;
+
+  total = (count < list->count) ? count : list->count;
+
+  if (array)
+    {
+      size_t i;
+      struct list_data *current;
+
+      for (i = 0, current = list->head.next;
+          i < total && current != &list->head; current = current->next)
+       array[i++] = current->item;
+    }
+  if (pcount)
+    *pcount = total;
+  return 0;
 }
+
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/clear.c
similarity index 63%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/clear.c
index 0c3fd86..e39b389 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/clear.c
@@ -17,20 +17,27 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 
-#include <mailutils/types.h>
-#include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
-
-int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+void
+mu_list_clear (mu_list_t list)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  struct list_data *current;
+  struct list_data *previous;
+
+  if (!list)
+    return;
+  mu_monitor_wrlock (list->monitor);
+  for (current = list->head.next; current != &list->head;)
+    {
+      previous = current;
+      current = current->next;
+      DESTROY_ITEM (list, previous);
+      free (previous);
+    }
+  list->head.next = list->head.prev = &list->head;
+  mu_monitor_unlock (list->monitor);
 }
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/count.c
similarity index 74%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/count.c
index 0c3fd86..981dbcc 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/count.c
@@ -17,20 +17,19 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
-
-#include <mailutils/types.h>
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
 
 int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+mu_list_count (mu_list_t list, size_t *pcount)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  if (list == NULL)
+    return EINVAL;
+  if (pcount == NULL)
+    return MU_ERR_OUT_PTR_NULL;
+  *pcount = list->count;
+  return 0;
 }
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/create.c
similarity index 64%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/create.c
index 0c3fd86..c5d59e1 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/create.c
@@ -17,20 +17,33 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
 
-#include <mailutils/types.h>
+#include <stdlib.h>
+
+#include <mailutils/sys/list.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
 
 int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+mu_list_create (mu_list_t *plist)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  mu_list_t list;
+  int status;
+
+  if (plist == NULL)
+    return MU_ERR_OUT_PTR_NULL;
+  list = calloc (sizeof (*list), 1);
+  if (list == NULL)
+    return ENOMEM;
+  status = mu_monitor_create (&list->monitor, 0,  list);
+  if (status != 0)
+    {
+      free (list);
+      return status;
+    }
+  list->head.next = &list->head;
+  list->head.prev = &list->head;
+  *plist = list;
+  return 0;
 }
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/destroy.c
similarity index 71%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/destroy.c
index 0c3fd86..ebfd813 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/destroy.c
@@ -17,20 +17,20 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 
-#include <mailutils/types.h>
-#include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
-
-int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+void
+mu_list_destroy (mu_list_t *plist)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  if (plist && *plist)
+    {
+      mu_list_t list = *plist;
+      mu_list_clear (list);
+      mu_monitor_destroy (&list->monitor, list);
+      free (list);
+      *plist = NULL;
+    }
 }
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/do.c
similarity index 61%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/do.c
index 0c3fd86..ef9ef17 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/do.c
@@ -17,20 +17,31 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
-
-#include <mailutils/types.h>
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
 
 int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+mu_list_do (mu_list_t list, mu_list_action_t *action, void *cbdata)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  mu_iterator_t itr;
+  int status = 0;
+
+  if (list == NULL || action == NULL)
+    return EINVAL;
+  status = mu_list_get_iterator (list, &itr);
+  if (status)
+    return status;
+  for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+       mu_iterator_next (itr))
+    {
+      void *item;
+      mu_iterator_current (itr, &item);
+      if ((status = action (item, cbdata)))
+       break;
+    }
+  mu_iterator_destroy (&itr);
+  return status;
 }
diff --git a/libmailutils/url/urlinv.c b/libmailutils/list/empty.c
similarity index 76%
copy from libmailutils/url/urlinv.c
copy to libmailutils/list/empty.c
index c4f8113..4498414 100644
--- a/libmailutils/url/urlinv.c
+++ b/libmailutils/list/empty.c
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2011 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 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
@@ -18,16 +19,13 @@
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
-#include <stdlib.h>
-#include <errno.h>
-#include <mailutils/sys/url.h>
+#include <mailutils/sys/list.h>
 
 int
-mu_url_invalidate (mu_url_t url)
+mu_list_is_empty (mu_list_t list)
 {
-  if (!url)
-    return EINVAL;
-  free (url->name);
-  url->name = NULL;
-  return 0;
+  size_t n = 0;
+
+  mu_list_count (list, &n);
+  return (n == 0);
 }
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/get.c
similarity index 59%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/get.c
index 0c3fd86..03ed739 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/get.c
@@ -17,20 +17,34 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
-
-#include <mailutils/types.h>
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
 
 int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+mu_list_get (mu_list_t list, size_t indx, void **pitem)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  struct list_data *current;
+  size_t count;
+  int status = MU_ERR_NOENT;
+
+  if (list == NULL)
+    return EINVAL;
+  if (pitem == NULL)
+    return MU_ERR_OUT_PTR_NULL;
+  mu_monitor_rdlock (list->monitor);
+  for (current = list->head.next, count = 0; current != &list->head;
+       current = current->next, count++)
+    {
+      if (count == indx)
+        {
+          *pitem = current->item;
+         status = 0;
+         break;
+        }
+    }
+  mu_monitor_unlock (list->monitor);
+  return status;
 }
diff --git a/libmailutils/url/urlinv.c b/libmailutils/list/getcomp.c
similarity index 75%
copy from libmailutils/url/urlinv.c
copy to libmailutils/list/getcomp.c
index c4f8113..520ca6f 100644
--- a/libmailutils/url/urlinv.c
+++ b/libmailutils/list/getcomp.c
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2011 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 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
@@ -18,16 +19,14 @@
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
-#include <stdlib.h>
-#include <errno.h>
-#include <mailutils/sys/url.h>
+#include <mailutils/sys/list.h>
+#include <mailutils/errno.h>
 
 int
-mu_url_invalidate (mu_url_t url)
+mu_list_get_comparator (mu_list_t list, mu_list_comparator_t *comp)
 {
-  if (!url)
+  if (!list)
     return EINVAL;
-  free (url->name);
-  url->name = NULL;
+  *comp = list->comp;
   return 0;
 }
diff --git a/libmailutils/property/propset.c b/libmailutils/list/gmap.c
similarity index 51%
copy from libmailutils/property/propset.c
copy to libmailutils/list/gmap.c
index 147471d..4a20a44 100644
--- a/libmailutils/property/propset.c
+++ b/libmailutils/list/gmap.c
@@ -17,54 +17,49 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
-
-#include <mailutils/types.h>
+#include <stdlib.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
+#include <mailutils/sys/list.h>
 
 int
-mu_property_set_value (mu_property_t prop, const char *key,
-                      const char *value, int overwrite)
+mu_list_gmap (mu_list_t list, mu_list_mapper_t map, size_t nelem, void *data)
 {
   int rc;
+  int status;
+  mu_iterator_t itr;
+  void **buf;
+  size_t i;
   
-  if (!value)
-    rc = mu_property_unset (prop, key);
-  else
+  if (!list || !map || nelem == 0)
+    return EINVAL;
+  rc = mu_list_get_iterator (list, &itr);
+  if (rc)
+    return status;
+  buf = calloc (nelem, sizeof (buf[0]));
+  if (!buf)
     {
-      rc = _mu_property_check (prop);
-      if (rc)
-       return rc;
-      if (!prop->_prop_setval)
-       return MU_ERR_EMPTY_VFN;
-      rc = prop->_prop_setval (prop, key, value, overwrite);
-      if (rc == 0)
-       prop->_prop_flags |= MU_PROP_MODIFIED;
+      mu_iterator_destroy (&itr);
+      return ENOMEM;
     }
+  for (i = 0, mu_iterator_first (itr); !mu_iterator_is_done (itr);
+       mu_iterator_next (itr))
+    {
+      void *item;
+      mu_iterator_current (itr, &item);
+      buf[i++] = item;
+      if (i == nelem)
+       {
+         i = 0;
+         rc = map (buf, nelem, data);
+         if (rc)
+           break;
+       }
+    }
+  if (rc == 0 && i > 0 && i < nelem)
+    rc = map (buf, i, data);
+  mu_iterator_destroy (&itr);
+  free (buf);
   return rc;
 }
-
-int
-mu_property_unset (mu_property_t prop, const char *key)
-{
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_unset)
-    return MU_ERR_EMPTY_VFN;
-  rc = prop->_prop_unset (prop, key);
-  if (rc == 0)
-    prop->_prop_flags |= MU_PROP_MODIFIED;
-  return rc;
-}
-
-int
-mu_property_set (mu_property_t prop, const char *key)
-{
-  return mu_property_set_value (prop, key, "", 1);
-}
-
-  
-
diff --git a/libmailutils/list/insert.c b/libmailutils/list/insert.c
new file mode 100644
index 0000000..3e7846c
--- /dev/null
+++ b/libmailutils/list/insert.c
@@ -0,0 +1,72 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 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 
+   <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
+#include <mailutils/errno.h>
+
+int
+_mu_list_insert_item (mu_list_t list, struct list_data *current,
+                     void *new_item,
+                     int insert_before)
+{
+  int status;
+  struct list_data *ldata = calloc (sizeof (*ldata), 1);
+  if (ldata == NULL)
+    status = ENOMEM;
+  else
+    {
+      ldata->item = new_item;
+      _mu_list_insert_sublist (list, current,
+                              ldata, ldata,
+                              1,
+                              insert_before);
+      status = 0;
+    }
+  return status;
+}
+
+int
+mu_list_insert (mu_list_t list, void *item, void *new_item, int insert_before)
+{
+  struct list_data *current;
+  mu_list_comparator_t comp;
+  int status = MU_ERR_NOENT;
+
+  if (list == NULL)
+    return EINVAL;
+  comp = list->comp ? list->comp : _mu_list_ptr_comparator;
+
+  mu_monitor_wrlock (list->monitor);
+  for (current = list->head.next;
+       current != &list->head;
+       current = current->next)
+    {
+      if (comp (current->item, item) == 0)
+       {
+         status = _mu_list_insert_item (list, current, new_item,
+                                        insert_before);
+         break;
+       }
+    }
+  mu_monitor_unlock (list->monitor);
+  return status;
+}
diff --git a/libmailutils/list/intersect.c b/libmailutils/list/intersect.c
new file mode 100644
index 0000000..d191c8f
--- /dev/null
+++ b/libmailutils/list/intersect.c
@@ -0,0 +1,90 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 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 
+   <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
+#include <mailutils/errno.h>
+
+/* Computes an intersection of two lists and returns it in PDEST.
+   The resulting list contains elements from A that are
+   also encountered in B (as per comparison function of
+   the latter).
+
+   If DUP_ITEM is not NULL, it is used to create copies of
+   items to be stored in PDEST.  In this case, the destroy_item
+   function of B is also attached to PDEST.  Otherwise, if
+   DUP_ITEM is NULL, pointers to elements are stored and
+   no destroy_item function is assigned. */
+int
+mu_list_intersect_dup (mu_list_t *pdest, mu_list_t a, mu_list_t b,
+                      int (*dup_item) (void **, void *, void *),
+                      void *dup_closure)
+{
+  mu_list_t dest;
+  int rc;
+  mu_iterator_t itr;
+  
+  rc = mu_list_create (&dest);
+  if (rc)
+    return rc;
+
+  mu_list_set_comparator (dest, b->comp);
+  if (dup_item)
+    mu_list_set_destroy_item (dest, b->destroy_item);
+  
+  rc = mu_list_get_iterator (a, &itr);
+  if (rc)
+    {
+      mu_list_destroy (&dest);
+      return rc;
+    }
+
+  rc = 0;
+  for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+       mu_iterator_next (itr))
+    {
+      void *data;
+      mu_iterator_current (itr, &data);
+      if (mu_list_locate (b, data, NULL) == 0)
+       {
+         void *new_data;
+         if (dup_item && data)
+           {
+             rc = dup_item (&new_data, data, dup_closure);
+             if (rc)
+               break;
+           }
+         else
+           new_data = data;
+       
+         mu_list_append (dest, new_data); /* FIXME: Check return, and? */
+       }
+    }
+  mu_iterator_destroy (&itr);
+  *pdest = dest;
+  return rc;
+}
+
+int
+mu_list_intersect (mu_list_t *pdest, mu_list_t a, mu_list_t b)
+{
+  return mu_list_intersect_dup (pdest, a, b, NULL, NULL);
+}
diff --git a/libmailutils/list/iterator.c b/libmailutils/list/iterator.c
new file mode 100644
index 0000000..8287ea3
--- /dev/null
+++ b/libmailutils/list/iterator.c
@@ -0,0 +1,250 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 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 
+   <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/sys/list.h>
+#include <mailutils/sys/iterator.h>
+#include <mailutils/errno.h>
+
+/* Iterator interface */
+
+struct list_iterator
+{
+  mu_list_t list;
+  struct list_data *cur;
+  int backwards; /* true if iterating backwards */
+};
+
+static int
+first (void *owner)
+{
+  struct list_iterator *itr = owner;
+  if (itr->backwards)
+    itr->cur = itr->list->head.prev;
+  else
+    itr->cur = itr->list->head.next;
+  return 0;
+}
+
+static int
+next (void *owner)
+{
+  struct list_iterator *itr = owner;
+  if (itr->backwards)
+    itr->cur = itr->cur->prev;
+  else
+    itr->cur = itr->cur->next;
+  return 0;
+}
+
+static int
+getitem (void *owner, void **pret, const void **pkey)
+{
+  struct list_iterator *itr = owner;
+  *pret = itr->cur->item;
+  if (pkey)
+    *pkey = NULL;
+  return 0;
+}
+
+static int
+finished_p (void *owner)
+{
+  struct list_iterator *itr = owner;
+  return itr->cur == &itr->list->head;
+}
+
+static int
+destroy (mu_iterator_t iterator, void *data)
+{
+  struct list_iterator *itr = data;
+  mu_iterator_detach (&itr->list->itr, iterator);
+  free (data);
+  return 0;
+}
+
+static int
+curitem_p (void *owner, void *item)
+{
+  struct list_iterator *itr = owner;
+  return itr->cur == item;
+}
+
+static int
+list_data_dup (void **ptr, void *owner)
+{
+  *ptr = malloc (sizeof (struct list_iterator));
+  if (*ptr == NULL)
+    return ENOMEM;
+  memcpy (*ptr, owner, sizeof (struct list_iterator));
+  return 0;
+}
+
+static int
+list_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
+{
+  struct list_iterator *itr = owner;
+  mu_list_t list = itr->list;
+  struct list_data *ptr;
+  
+  switch (req)
+    {
+    case mu_itrctl_tell:
+      /* Return current position in the object */
+      if (itr->cur == NULL)
+       return MU_ERR_NOENT;
+      else
+       {
+         size_t count;
+
+         for (count = 0, ptr = list->head.next; ptr != &list->head;
+              ptr = ptr->next, count++)
+           {
+             if (ptr == itr->cur)
+               {
+                 *(size_t*)arg = count;
+                 return 0;
+               }
+           }
+         return MU_ERR_NOENT;
+       }
+      break;
+      
+    case mu_itrctl_delete:
+    case mu_itrctl_delete_nd:
+      /* Delete current element */
+      if (itr->cur == NULL)
+       return MU_ERR_NOENT;
+      else
+       {
+         struct list_data *prev;
+       
+         ptr = itr->cur;
+         prev = ptr->prev;
+       
+         mu_iterator_advance (list->itr, ptr);
+         prev->next = ptr->next;
+         ptr->next->prev = prev;
+         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 (itr->cur == NULL)
+       return MU_ERR_NOENT;
+      if (!arg)
+       return EINVAL;
+      ptr = itr->cur;
+      if (req == mu_itrctl_replace)
+         DESTROY_ITEM (list, ptr);
+      ptr = itr->cur;
+      ptr->item = arg;
+      break;
+      
+    case mu_itrctl_insert:
+      /* Insert new element in the current position */
+      if (itr->cur == NULL)
+       return MU_ERR_NOENT;
+      if (!arg)
+       return EINVAL;
+      return _mu_list_insert_item (list, itr->cur, arg, 0);
+
+    case mu_itrctl_insert_list:
+      /* Insert a list of elements */
+      if (itr->cur == NULL)
+       return MU_ERR_NOENT;
+      if (!arg)
+       return EINVAL;
+      else
+       {
+         mu_list_t new_list = arg;
+         _mu_list_insert_sublist (list, itr->cur,
+                                  new_list->head.next, new_list->head.prev,
+                                  new_list->count,
+                                  0);
+         _mu_list_clear (new_list);
+       }
+      break;
+
+    case mu_itrctl_qry_direction:
+      if (!arg)
+       return EINVAL;
+      else
+       *(int*)arg = itr->backwards;
+      break;
+
+    case mu_itrctl_set_direction:
+      if (!arg)
+       return EINVAL;
+      else
+       itr->backwards = !!*(int*)arg;
+      break;
+      
+    default:
+      return ENOSYS;
+    }
+  return 0;
+}
+
+int
+mu_list_get_iterator (mu_list_t list, mu_iterator_t *piterator)
+{
+  mu_iterator_t iterator;
+  int status;
+  struct list_iterator *itr;
+
+  if (!list)
+    return EINVAL;
+
+  itr = calloc (1, sizeof *itr);
+  if (!itr)
+    return ENOMEM;
+  itr->list = list;
+  itr->cur = NULL;
+
+  status = mu_iterator_create (&iterator, itr);
+  if (status)
+    {
+      free (itr);
+      return status;
+    }
+
+  mu_iterator_set_first (iterator, first);
+  mu_iterator_set_next (iterator, next);
+  mu_iterator_set_getitem (iterator, getitem);
+  mu_iterator_set_finished_p (iterator, finished_p);
+  mu_iterator_set_curitem_p (iterator, curitem_p);
+  mu_iterator_set_destroy (iterator, destroy);
+  mu_iterator_set_dup (iterator, list_data_dup);
+  mu_iterator_set_itrctl (iterator, list_itrctl);
+  
+  mu_iterator_attach (&list->itr, iterator);
+
+  *piterator = iterator;
+  return 0;
+}
diff --git a/libmailutils/base/listlist.c b/libmailutils/list/listlist.c
similarity index 98%
rename from libmailutils/base/listlist.c
rename to libmailutils/list/listlist.c
index 1032f7a..38bd588 100644
--- a/libmailutils/base/listlist.c
+++ b/libmailutils/list/listlist.c
@@ -19,11 +19,7 @@
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
-
-#include <errno.h>
 #include <stdlib.h>
-#include <string.h>
-
 #include <mailutils/sys/list.h>
 #include <mailutils/sys/iterator.h>
 #include <mailutils/errno.h>
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/locate.c
similarity index 53%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/locate.c
index 0c3fd86..10170c4 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/locate.c
@@ -17,20 +17,41 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
-
-#include <mailutils/types.h>
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
 
 int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+_mu_list_ptr_comparator (const void *item, const void *value)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  return item != value;
 }
+
+int
+mu_list_locate (mu_list_t list, void *item, void **ret_item)
+{
+  struct list_data *current, *previous;
+  mu_list_comparator_t comp;
+  int status = MU_ERR_NOENT;
+
+  if (list == NULL)
+    return EINVAL;
+  comp = list->comp ? list->comp : _mu_list_ptr_comparator;
+  mu_monitor_wrlock (list->monitor);
+  for (previous = &list->head, current = list->head.next;
+       current != &list->head; previous = current, current = current->next)
+    {
+      if (comp (current->item, item) == 0)
+       {
+         if (ret_item)
+           *ret_item = current->item;
+         status = 0;
+         break;
+       }
+    }
+  mu_monitor_unlock (list->monitor);
+  return status;
+}
+
diff --git a/libmailutils/list/map.c b/libmailutils/list/map.c
new file mode 100644
index 0000000..e16f129
--- /dev/null
+++ b/libmailutils/list/map.c
@@ -0,0 +1,87 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 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 
+   <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <mailutils/errno.h>
+#include <mailutils/sys/list.h>
+
+struct map_closure
+{
+  mu_list_mapper_t map;
+  void *data;
+  mu_list_t list;
+  int status;
+};
+
+static int
+_list_mapper (void **itmv, size_t itmc, void *data)
+{
+  struct map_closure *clos = data;
+  int rc, status;
+      
+  if (!clos->list)
+    {
+      status = mu_list_create (&clos->list);
+      if (status)
+       {
+         clos->status = status;
+         return MU_ERR_FAILURE;
+       }
+    }
+  
+  rc = clos->map (itmv, itmc, clos->data);
+  if (!(rc & MU_LIST_MAP_SKIP))
+    {
+      status = mu_list_append (clos->list, itmv[0]);
+      if (status)
+       {
+         clos->status = status;
+         return MU_ERR_FAILURE;
+       }
+    }
+  if (rc & MU_LIST_MAP_STOP)
+    return MU_ERR_CANCELED;
+  return 0;
+}
+               
+int
+mu_list_map (mu_list_t list, mu_list_mapper_t map, void *data, size_t nelem,
+            mu_list_t *res)
+{
+  int rc;
+  struct map_closure cl;
+
+  if (!res)
+    return MU_ERR_OUT_PTR_NULL;
+
+  cl.map = map;
+  cl.data = data;
+  cl.list = NULL;
+  cl.status = 0;
+
+  rc = mu_list_gmap (list, _list_mapper, nelem, &cl);
+
+  if (cl.list)
+    *res = cl.list;
+  if (rc == MU_ERR_FAILURE)
+    return cl.status;
+  return 0;
+}
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/prepend.c
similarity index 61%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/prepend.c
index 0c3fd86..35b7623 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/prepend.c
@@ -17,20 +17,32 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
 
-#include <mailutils/types.h>
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
 
 int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+mu_list_prepend (mu_list_t list, void *item)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  struct list_data *ldata;
+  struct list_data *first;
+
+  if (list == NULL)
+    return EINVAL;
+  first = list->head.next;
+  ldata = calloc (sizeof (*ldata), 1);
+  if (ldata == NULL)
+    return ENOMEM;
+  ldata->item = item;
+  mu_monitor_wrlock (list->monitor);
+  ldata->prev = &list->head;
+  ldata->next = list->head.next;
+  first->prev = ldata;
+  list->head.next = ldata;
+  list->count++;
+  mu_monitor_unlock (list->monitor);
+  return 0;
 }
diff --git a/libmailutils/list/remove.c b/libmailutils/list/remove.c
new file mode 100644
index 0000000..ab5951d
--- /dev/null
+++ b/libmailutils/list/remove.c
@@ -0,0 +1,66 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 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 
+   <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
+#include <mailutils/errno.h>
+
+int
+mu_list_remove (mu_list_t list, void *item)
+{
+  struct list_data *current;
+  mu_list_comparator_t comp;
+  int status = MU_ERR_NOENT;
+
+  if (list == NULL)
+    return EINVAL;
+  comp = list->comp ? list->comp : _mu_list_ptr_comparator;
+  mu_monitor_wrlock (list->monitor);
+  for (current = list->head.next;
+       current != &list->head; current = current->next)
+    {
+      if (comp (current->item, item) == 0)
+       {
+         struct list_data *previous = current->prev;
+         
+         mu_iterator_advance (list->itr, current);
+         previous->next = current->next;
+         current->next->prev = previous;
+         DESTROY_ITEM (list, current);
+         free (current);
+         list->count--;
+         status = 0;
+         break;
+       }
+    }
+  mu_monitor_unlock (list->monitor);
+  return status;
+}
+
+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;
+}
+
diff --git a/libmailutils/property/propset.c b/libmailutils/list/replace.c
similarity index 50%
copy from libmailutils/property/propset.c
copy to libmailutils/list/replace.c
index 147471d..bebdd9a 100644
--- a/libmailutils/property/propset.c
+++ b/libmailutils/list/replace.c
@@ -17,54 +17,43 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
-
-#include <mailutils/types.h>
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 #include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
 
 int
-mu_property_set_value (mu_property_t prop, const char *key,
-                      const char *value, int overwrite)
+mu_list_replace (mu_list_t list, void *old_item, void *new_item)
 {
-  int rc;
-  
-  if (!value)
-    rc = mu_property_unset (prop, key);
-  else
+  struct list_data *current, *previous;
+  mu_list_comparator_t comp;
+  int status = MU_ERR_NOENT;
+
+  if (list == NULL)
+    return EINVAL;
+  comp = list->comp ? list->comp : _mu_list_ptr_comparator;
+  mu_monitor_wrlock (list->monitor);
+  for (previous = &list->head, current = list->head.next;
+       current != &list->head; previous = current, current = current->next)
     {
-      rc = _mu_property_check (prop);
-      if (rc)
-       return rc;
-      if (!prop->_prop_setval)
-       return MU_ERR_EMPTY_VFN;
-      rc = prop->_prop_setval (prop, key, value, overwrite);
-      if (rc == 0)
-       prop->_prop_flags |= MU_PROP_MODIFIED;
+      if (comp (current->item, old_item) == 0)
+       {
+         DESTROY_ITEM (list, current);
+         current->item = new_item;
+         status = 0;
+         break;
+       }
     }
-  return rc;
+  mu_monitor_unlock (list->monitor);
+  return status;
 }
 
 int
-mu_property_unset (mu_property_t prop, const char *key)
+mu_list_replace_nd (mu_list_t list, void *item, void *new_item)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_unset)
-    return MU_ERR_EMPTY_VFN;
-  rc = prop->_prop_unset (prop, key);
-  if (rc == 0)
-    prop->_prop_flags |= MU_PROP_MODIFIED;
+  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_property_set (mu_property_t prop, const char *key)
-{
-  return mu_property_set_value (prop, key, "", 1);
-}
-
-  
-
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/setcomp.c
similarity index 71%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/setcomp.c
index 0c3fd86..2eafc6b 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/setcomp.c
@@ -17,20 +17,19 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 
-#include <mailutils/types.h>
-#include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
-
-int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+mu_list_comparator_t
+mu_list_set_comparator (mu_list_t list, mu_list_comparator_t comp)
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  mu_list_comparator_t old_comp;
+
+  if (list == NULL)
+    return NULL;
+  old_comp = list->comp;
+  list->comp = comp;
+  return old_comp;
 }
diff --git a/libmailutils/property/propitr.c b/libmailutils/list/setdestr.c
similarity index 71%
copy from libmailutils/property/propitr.c
copy to libmailutils/list/setdestr.c
index 0c3fd86..9edd7d0 100644
--- a/libmailutils/property/propitr.c
+++ b/libmailutils/list/setdestr.c
@@ -17,20 +17,15 @@
    <http://www.gnu.org/licenses/>. */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
+#include <stdlib.h>
+#include <mailutils/sys/list.h>
 
-#include <mailutils/types.h>
-#include <mailutils/errno.h>
-#include <mailutils/sys/property.h>
-
-int
-mu_property_get_iterator (mu_property_t prop, mu_iterator_t *pitr)
+mu_list_destroy_item_t
+mu_list_set_destroy_item (mu_list_t list, void (*destroy_item)(void *item))
 {
-  int rc = _mu_property_check (prop);
-  if (rc)
-    return rc;
-  if (!prop->_prop_getitr)
-    return MU_ERR_EMPTY_VFN;
-  return prop->_prop_getitr (prop, pitr);
+  mu_list_destroy_item_t ret = list->destroy_item;
+  list->destroy_item = destroy_item;
+  return ret;
 }
diff --git a/libmailutils/tests/list.at b/libmailutils/tests/list.at
index eab485b..f32249f 100644
--- a/libmailutils/tests/list.at
+++ b/libmailutils/tests/list.at
@@ -109,7 +109,7 @@ TESTLIST([get],[],
 # ------------------------------------------------------------
 
 m4_define([MU_TEST_GROUP],[Iterator])
-m4_define([MU_TEST_KEYWORDS],MU_TEST_KEYWORDS[ iterator itr])
+m4_pushdef([MU_TEST_KEYWORDS],MU_TEST_KEYWORDS[ iterator itr])
 
 TESTLIST([forward],[],
 [add en to tre fire fem
@@ -246,6 +246,84 @@ cur
 0:2:fire
 ])
 
+m4_popdef([MU_TEST_KEYWORDS])
+
+
+# ------------------------------------------------------------
+# Maps
+# ------------------------------------------------------------
+
+m4_define([MU_TEST_GROUP],[Map])
+m4_pushdef([MU_TEST_KEYWORDS],MU_TEST_KEYWORDS[ map])
+
+TESTLIST([even],[],
+[add null en to tre fire fem
+map even
+],
+[# items: 3
+null
+to
+fire
+])
+
+TESTLIST([odd],[],
+[add null en to tre fire fem
+map odd
+],
+[# items: 3
+en
+tre
+fem
+])
+
+TESTLIST([odd0],[],
+[add null
+map odd
+],
+[# items: 0
+])
+
+TESTLIST([concat],[],
+[add en to tre fire fem
+map concat 2 -
+],
+[# items: 3
+en-to
+tre-fire
+fem
+])
+
+TESTLIST([concat3],[],
+[add en to tre fire fem
+map concat 3 -
+],
+[# items: 2
+en-to-tre
+fire-fem
+])
+
+TESTLIST([skip],[],
+[add null en to tre fire fem
+map skip 3
+],
+[# items: 3
+tre
+fire
+fem
+])
+
+TESTLIST([trim],[],
+[add null en to tre fire fem
+map trim 3
+],
+[# items: 3
+null
+en
+to
+])
+
+m4_popdef([MU_TEST_KEYWORDS])
+
 dnl ------------------------------------------------------------
 dnl Cleanup
 m4_popdef([TESTLIST])
diff --git a/libmailutils/tests/listop.c b/libmailutils/tests/listop.c
index 0672b7d..fceec54 100644
--- a/libmailutils/tests/listop.c
+++ b/libmailutils/tests/listop.c
@@ -428,6 +428,197 @@ cur (int num, mu_iterator_t itr)
   printf ("%s\n", text);
 }
 
+static int
+map_even (void **itmv, size_t itmc, void *call_data)
+{
+  int *num = call_data, n = *num;
+  *num = !*num;
+  if ((n % 2) == 0)
+    {
+      itmv[0] = strdup (itmv[0]);
+      return MU_LIST_MAP_OK;
+    }
+  return MU_LIST_MAP_SKIP;
+}
+
+static int
+map_odd (void **itmv, size_t itmc, void *call_data)
+{
+  int *num = call_data, n = *num;
+  *num = !*num;
+  if (n % 2)
+    {
+      itmv[0] = strdup (itmv[0]);
+      return MU_LIST_MAP_OK;
+    }
+  return MU_LIST_MAP_SKIP;
+}
+
+static int
+map_concat (void **itmv, size_t itmc, void *call_data)
+{
+  char *delim = call_data;
+  size_t dlen = strlen (delim);
+  size_t i;
+  size_t len = 0;
+  char *res, *p;
+  
+  for (i = 0; i < itmc; i++)
+    len += strlen (itmv[i]);
+  len += (itmc - 1) * dlen + 1;
+
+  res = malloc (len);
+  if (!res)
+    abort ();
+  p = res;
+  for (i = 0; ; )
+    {
+      p = mu_stpcpy (p, itmv[i++]);
+      if (i == itmc)
+       break;
+      p = mu_stpcpy (p, delim);
+    }
+  itmv[0] = res;
+  return MU_LIST_MAP_OK;
+}
+
+struct trim_data
+{
+  size_t n;
+  size_t lim;
+};
+
+static int
+map_skip (void **itmv, size_t itmc, void *call_data)
+{
+  struct trim_data *td = call_data;
+
+  if (td->n++ < td->lim)
+    return MU_LIST_MAP_SKIP;
+  itmv[0] = strdup (itmv[0]);
+  return MU_LIST_MAP_OK;
+}
+
+static int
+map_trim (void **itmv, size_t itmc, void *call_data)
+{
+  struct trim_data *td = call_data;
+
+  if (td->n++ < td->lim)
+    {
+      itmv[0] = strdup (itmv[0]);
+      return MU_LIST_MAP_OK;
+    }
+  return MU_LIST_MAP_STOP|MU_LIST_MAP_SKIP;
+}
+
+int
+map (mu_list_t *plist, int argc, char **argv)
+{
+  mu_list_t list = *plist;
+  mu_list_t result;
+  int rc;
+  int replace = 0;
+
+  if (argc > 1 && strcmp (argv[1], "-replace") == 0)
+    {
+      replace = 1;
+      argc--;
+      argv++;
+    }
+  
+  if (argc < 2)
+    {
+      fprintf (stderr, "map [-replace] even|odd|concat|keep|trim\n");
+      return 0;
+    }
+
+  if (strcmp (argv[1], "even") == 0)
+    {
+      int n = 0;
+      rc = mu_list_map (list, map_even, &n, 1, &result);
+    }
+  else if (strcmp (argv[1], "odd") == 0)
+    {
+      int n = 0;
+      rc = mu_list_map (list, map_odd, &n, 1, &result);
+    }
+  else if (strcmp (argv[1], "concat") == 0)
+    {
+      size_t num;
+      char *delim = "";
+      
+      if (argc < 3 || argc > 4)
+       {
+         fprintf (stderr, "map concat NUM [DELIM]?\n");
+         return 0;
+       }
+      num = atoi (argv[2]);
+      if (argc == 4)
+       delim = argv[3];
+      
+      rc = mu_list_map (list, map_concat, delim, num, &result);
+    }
+  else if (strcmp (argv[1], "skip") == 0)
+    {
+      struct trim_data td;
+
+      if (argc < 3 || argc > 4)
+       {
+         fprintf (stderr, "map skip NUM?\n");
+         return 0;
+       }
+      td.n = 0;
+      td.lim = atoi (argv[2]);
+      rc = mu_list_map (list, map_skip, &td, 1, &result);
+    }
+  else if (strcmp (argv[1], "trim") == 0)
+    {
+      struct trim_data td;
+
+      if (argc < 3 || argc > 4)
+       {
+         fprintf (stderr, "map trim NUM?\n");
+         return 0;
+       }
+      td.n = 0;
+      td.lim = atoi (argv[2]);
+      rc = mu_list_map (list, map_trim, &td, 1, &result);
+    }
+  else
+    {
+      mu_error ("unknown map name\n");
+      return 0;
+    }
+  
+  if (rc)
+    {
+      mu_error ("map failed: %s", mu_strerror (rc));
+      return 0;
+    }
+
+  mu_list_set_destroy_item (result, mu_list_free_item);
+
+  if (replace)
+    {
+      size_t count[2];
+      mu_list_count (list, &count[0]);
+      mu_list_count (result, &count[1]);
+      
+      printf ("%lu in, %lu out\n", (unsigned long) count[0],
+             (unsigned long) count[1]);
+      mu_list_destroy (&list);
+      *plist = result;
+      return 1;
+    }
+  else
+    {
+      print (result);
+      mu_list_destroy (&result);
+    }
+  return 0;
+}
+
 void
 help ()
 {
@@ -446,6 +637,7 @@ help ()
   printf ("ictl repl item\n");
   printf ("ictl ins item [item*]\n");
   printf ("ictl dir [backwards|forwards]\n");
+  printf ("map NAME [ARGS]\n");
   printf ("print\n");
   printf ("quit\n");
   printf ("iter num\n");
@@ -517,6 +709,14 @@ shell (mu_list_t list)
            print (list);
          else if (strcmp (ws.ws_wordv[0], "cur") == 0)
            cur (num, itr[num]);
+         else if (strcmp (ws.ws_wordv[0], "map") == 0)
+           {
+             int i;
+             
+             if (map (&list, ws.ws_wordc, ws.ws_wordv))
+               for (i = 0; i < NITR; i++)
+                 mu_iterator_destroy (&itr[i]);
+           }
          else if (strcmp (ws.ws_wordv[0], "quit") == 0)
            return;
          else if (strcmp (ws.ws_wordv[0], "iter") == 0)
@@ -591,7 +791,7 @@ main (int argc, char **argv)
   
   while (argc--)
     {
-      rc = mu_list_append (list, *argv++);
+      rc = mu_list_append (list, strdup (*argv++));
       if (rc)
        lperror ("mu_list_append", rc);
     }
diff --git a/libproto/imap/capability.c b/libproto/imap/capability.c
index ab69ad2..feaed0d 100644
--- a/libproto/imap/capability.c
+++ b/libproto/imap/capability.c
@@ -44,6 +44,27 @@ capa_comp (const void *item, const void *value)
   return !(*capa == 0 || *capa == '=');
 }
 
+static int
+_map_capa (void **itmv, size_t itmc, void *call_data)
+{
+  int *n = call_data;
+  struct imap_list_element *elt = itmv[0];
+
+  if (elt->type != imap_eltype_string)
+    return MU_LIST_MAP_STOP;
+  if (*n == 0)
+    {
+      ++*n;
+      if (strcmp (elt->v.string, "CAPABILITY") == 0)
+       return MU_LIST_MAP_SKIP;
+      else
+       return MU_LIST_MAP_STOP;
+    }
+  itmv[0] = elt->v.string;
+  elt->v.string = NULL;
+  return MU_LIST_MAP_OK;
+}
+
 int
 mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
 {
@@ -100,28 +121,9 @@ mu_imap_capability (mu_imap_t imap, int reread, 
mu_iterator_t *piter)
          if (mu_list_get (imap->untagged_resp, 0, (void*)&elt) == 0)
            {
              /* Top-level elements are always of imap_eltype_list type. */
-             mu_iterator_t itr;
-             
-             mu_list_get_iterator (elt->v.list, &itr);
-             mu_iterator_first (itr);
-             if (mu_iterator_is_done (itr))
-               return MU_ERR_PARSE;
-             mu_iterator_current (itr, (void **) &elt);
-             if (elt->type == imap_eltype_string &&
-                 strcmp (elt->v.string, "CAPABILITY") == 0)
-               {
-                 for (mu_iterator_next (itr); !mu_iterator_is_done (itr);
-                      mu_iterator_next (itr))
-                   {
-                     mu_iterator_current (itr, (void **) &elt);
-                     if (elt->type == imap_eltype_string)
-                       {
-                         mu_list_append (imap->capa, elt->v.string);
-                         elt->v.string = NULL;
-                       }
-                   }
-               }
-             mu_iterator_destroy (&itr);
+             int n = 0;
+             status = mu_list_map (elt->v.list, _map_capa, &n, 1,
+                                   &imap->capa);
            }
          if (piter)
            status = mu_list_get_iterator (imap->capa, piter);
diff --git a/libproto/imap/id.c b/libproto/imap/id.c
index ef0974d..a6e6254 100644
--- a/libproto/imap/id.c
+++ b/libproto/imap/id.c
@@ -34,6 +34,20 @@ _id_free (void *data)
   free (s);
 }
 
+static int
+_id_mapper (void **itmv, size_t itmc, void *call_data)
+{
+  int rc;
+  mu_assoc_t assoc = call_data;
+  struct imap_list_element *key = itmv[0], *val = itmv[1];
+  if (key->type != imap_eltype_string || val->type != imap_eltype_string)
+    return MU_ERR_FAILURE;
+  rc = mu_assoc_install (assoc, key->v.string, &val->v.string);
+  if (rc == 0)
+    val->v.string = NULL;
+  return rc;
+}
+
 struct id_convert_state
 {
   int item;
@@ -61,32 +75,7 @@ _id_convert (void *item, void *data)
 
     case 1:
       if (elt->type == imap_eltype_list)
-       {
-         mu_iterator_t itr;
-
-         mu_list_get_iterator (elt->v.list, &itr);
-         for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
-              mu_iterator_next (itr))
-           {
-             char *key, *val;
-             mu_iterator_current (itr, (void **) &elt);
-
-             if (elt->type != imap_eltype_string)
-               break;
-             key = elt->v.string;
-             elt->v.string = NULL;
-
-             mu_iterator_next (itr);
-             if (mu_iterator_is_done (itr))
-               break;
-             mu_iterator_current (itr, (void **) &elt);
-             if (elt->type != imap_eltype_string)
-               break;
-             val = elt->v.string;
-             elt->v.string = NULL;
-             mu_assoc_install (stp->assoc, key, &val);
-           }
-       }
+       mu_list_gmap (elt->v.list, _id_mapper, 2, stp->assoc);
     }
   return 1;
 }      


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]