diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | NEWS | 20 | ||||
-rw-r--r-- | examples/header.c | 91 | ||||
-rw-r--r-- | include/mailutils/header.h | 2 | ||||
-rw-r--r-- | libproto/include/header0.h | 6 | ||||
-rw-r--r-- | mailbox/Makefile.am | 1 | ||||
-rw-r--r-- | mailbox/hdritr.c | 159 | ||||
-rw-r--r-- | mailbox/header.c | 1 |
8 files changed, 280 insertions, 13 deletions
@@ -1,3 +1,16 @@ +2008-02-04 Sergey Poznyakoff <gray@gnu.org.ua> + + * NEWS: Update. + * examples/header.c: New command `itr'. + (main): Empty input repeats the recent command. + * include/mailutils/header.h (mu_header_get_iterator): New + function. + * libproto/include/header0.h (struct _mu_header): New member itr. + * mailbox/Makefile.am (libmailutils_la_SOURCES): Add hdritr.c + * mailbox/hdritr.c: New file. + * mailbox/header.c (mu_header_remove): Bugfix. Invalidate the + header after removal. + 2008-01-31 Sergey Poznyakoff <gray@gnu.org.ua> * auth/radius.c (_expand_query): Fix typo. @@ -1,4 +1,4 @@ -GNU mailutils NEWS -- history of user-visible changes. 2008-01-12 +GNU mailutils NEWS -- history of user-visible changes. 2008-02-04 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. See the end of file for copying conditions. @@ -143,6 +143,24 @@ approach is recommended to use instead of mu_error_set_print: mu_diag_get_debug (&debug); mu_debug_set_print (debug, new_printer, NULL); +** Header iteration + +New function `mu_header_get_iterator' returns an iterator for this +header object. Thus, the following code loops over all headers: + + mu_iterator_t itr; + mu_header_get_iterator (header, &itr); + for (mu_iterator_first (itr); !mu_iterator_is_done (itr); + mu_iterator_next (itr)) + { + const char *hdr, *val; + mu_iterator_current_kv (itr, + (const void**)&hdr, + (void**)&val)); + /* Do something with hdr and val */ + } + mu_iterator_destroy (&itr); + ** Global debugging and verbosity settings. These settings provide default values for mu_debug_t objects created diff --git a/examples/header.c b/examples/header.c index 76d6b7fe1..bd2939181 100644 --- a/examples/header.c +++ b/examples/header.c @@ -27,6 +27,7 @@ char *file; mu_header_t header; +mu_iterator_t iterator; char *ps[] = { "> ", ". " }; int interactive; @@ -132,6 +133,7 @@ cmd_free (int argc, char **argv) { if (check_args (argv[0], argc, 1, 1)) return; + mu_iterator_destroy (&iterator); mu_header_destroy (&header, NULL); } @@ -285,7 +287,55 @@ cmd_write (int argc, char **argv) break; } } - + +void +cmd_iterate (int argc, char **argv) +{ + if (check_args (argv[0], argc, 1, 2)) + return; + if (argc == 1) + { + mu_iterator_t itr; + MU_ASSERT (mu_header_get_iterator (header, &itr)); + for (mu_iterator_first (itr); !mu_iterator_is_done (itr); + mu_iterator_next (itr)) + { + const char *hdr, *val; + MU_ASSERT (mu_iterator_current_kv (itr, + (const void**)&hdr, + (void**)&val)); + printf ("%s: %s\n", hdr, val); + } + mu_iterator_destroy (&itr); + } + else + { + const char *hdr, *val; + + if (!iterator) + MU_ASSERT (mu_header_get_iterator (header, &iterator)); + + if (strcmp (argv[1], "first") == 0 || strcmp (argv[1], "1") == 0) + mu_iterator_first (iterator); + else if (strcmp (argv[1], "next") == 0 || strcmp (argv[1], "n") == 0) + { + mu_iterator_next (iterator); + if (mu_iterator_is_done (iterator)) + { + printf ("Past end of headers. Use `itr first'.\n"); + return; + } + } + + MU_ASSERT (mu_iterator_current_kv (iterator, + (const void **)&hdr, + (void**)&val)); + printf ("%s: %s\n", hdr, val); + } +} + + + struct cmdtab { char *name; @@ -303,6 +353,7 @@ static struct cmdtab cmdtab[] = { { "print", cmd_print, "NAME [N]", "find and print the Nth (by default, 1st) instance of header named NAME" }, { "dump", cmd_dump, NULL, "dump all headers on screen" }, + { "itr", cmd_iterate, "[first|1|next|n]", "iterate over headers" }, { "remove", cmd_remove, "NAME [N]", "remove the Nth (by default, 1st) instance of header named NAME" }, { "insert", cmd_insert, "NAME VALUE [REF [NUM] [before|after] [replace]]", @@ -392,11 +443,27 @@ cmd_help (int argc, char **argv) } int +docmd (int argc, char **argv) +{ + struct cmdtab *cmd = find_cmd (argv[0]); + if (!cmd) + { + mu_error ("%u: unknown command %s", line_num, argv[0]); + return 1; + } + else + cmd->fun (argc, argv); + return 0; +} + +int main (int argc, char **argv) { int c; char buf[512]; - + char **prevv; + int prevc = 0; + interactive = isatty (0); while ((c = getopt (argc, argv, "f:h")) != EOF) { @@ -434,7 +501,6 @@ main (int argc, char **argv) { int c; char **v; - struct cmdtab *cmd; int status; line_num++; @@ -446,17 +512,20 @@ main (int argc, char **argv) continue; } - cmd = find_cmd (v[0]); - if (!cmd) + if (c == 0) { - mu_error ("%u: unknown command %s", - line_num, v[0]); + if (prevc) + docmd (prevc, prevv); + else + mu_argcv_free (c, v); } else - cmd->fun (c, v); - - mu_argcv_free (c, v); - + { + docmd (c, v); + mu_argcv_free (prevc, prevv); + prevc = c; + prevv = v; + } } exit (0); } diff --git a/include/mailutils/header.h b/include/mailutils/header.h index 58bf8f261..29e004a19 100644 --- a/include/mailutils/header.h +++ b/include/mailutils/header.h @@ -154,6 +154,8 @@ extern int mu_header_set_stream (mu_header_t, mu_stream_t, void *); extern int mu_header_size (mu_header_t, size_t *); extern int mu_header_lines (mu_header_t, size_t *); +extern int mu_header_get_iterator (mu_header_t, mu_iterator_t *); + extern int mu_header_set_fill (mu_header_t, int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *), void *owner); diff --git a/libproto/include/header0.h b/libproto/include/header0.h index 76b8bcf34..31e1b1e48 100644 --- a/libproto/include/header0.h +++ b/libproto/include/header0.h @@ -25,6 +25,7 @@ #include <mailutils/header.h> #include <mailutils/assoc.h> +#include <mailutils/iterator.h> #include <sys/types.h> #ifdef __cplusplus @@ -67,7 +68,10 @@ struct _mu_header /* Stream. */ mu_stream_t stream; size_t strpos; - + + /* Iterators */ + mu_iterator_t itr; + /* Methods */ int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *); }; diff --git a/mailbox/Makefile.am b/mailbox/Makefile.am index 9fdf7b57c..c309bb238 100644 --- a/mailbox/Makefile.am +++ b/mailbox/Makefile.am @@ -65,6 +65,7 @@ libmailutils_la_SOURCES = \ folder.c\ gdebug.c\ gocs.c\ + hdritr.c\ header.c\ iterator.c\ ipsrv.c\ diff --git a/mailbox/hdritr.c b/mailbox/hdritr.c new file mode 100644 index 000000000..7bd6780a3 --- /dev/null +++ b/mailbox/hdritr.c @@ -0,0 +1,159 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2008 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, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA */ + +/* Mail header iterators. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include <header0.h> +#include <mailutils/errno.h> + +struct header_iterator +{ + mu_header_t header; + size_t index; +}; + +static int +hdr_first (void *owner) +{ + struct header_iterator *itr = owner; + itr->index = 1; + return 0; +} + +static int +hdr_next (void *owner) +{ + struct header_iterator *itr = owner; + itr->index++; + return 0; +} + +static int +hdr_getitem (void *owner, void **pret, const void **pkey) +{ + struct header_iterator *itr = owner; + int rc; + size_t count; + + rc = mu_header_get_field_count (itr->header, &count); + if (rc) + return rc; + if (itr->index > count) + return MU_ERR_NOENT; + + rc = mu_header_sget_field_name (itr->header, itr->index, + (const char**) pkey); + if (rc == 0) + { + if (pkey) + rc = mu_header_sget_field_value (itr->header, itr->index, + (const char**) pret); + } + return rc; +} + +static int +hdr_finished_p (void *owner) +{ + struct header_iterator *itr = owner; + size_t count; + + if (mu_header_get_field_count (itr->header, &count)) + return 1; + return itr->index > count; +} + +static int +hdr_destroy (mu_iterator_t iterator, void *data) +{ + struct header_iterator *itr = data; + mu_iterator_detach (&itr->header->itr, iterator); + free (data); + return 0; +} + +static int +hdr_curitem_p (void *owner, void *item) +{ + void *ptr; + + if (hdr_getitem (owner, &ptr, NULL)) + return 0; + return ptr == item; +} + +static int +hdr_data_dup (void **ptr, void *owner) +{ + *ptr = malloc (sizeof (struct header_iterator)); + if (*ptr == NULL) + return ENOMEM; + memcpy (*ptr, owner, sizeof (struct header_iterator)); + return 0; +} + +int +mu_header_get_iterator (mu_header_t hdr, mu_iterator_t *piterator) +{ + mu_iterator_t iterator; + int status; + struct header_iterator *itr; + + if (!hdr) + return EINVAL; + + itr = calloc (1, sizeof *itr); + if (!itr) + return ENOMEM; + itr->header = hdr; + itr->index = 1; + + status = mu_iterator_create (&iterator, itr); + if (status) + { + free (itr); + return status; + } + + mu_iterator_set_first (iterator, hdr_first); + mu_iterator_set_next (iterator, hdr_next); + mu_iterator_set_getitem (iterator, hdr_getitem); + mu_iterator_set_finished_p (iterator, hdr_finished_p); + mu_iterator_set_curitem_p (iterator, hdr_curitem_p); + mu_iterator_set_destroy (iterator, hdr_destroy); + mu_iterator_set_dup (iterator, hdr_data_dup); + + mu_iterator_attach (&hdr->itr, iterator); + + *piterator = iterator; + return 0; +} + + + + + + + + diff --git a/mailbox/header.c b/mailbox/header.c index a5c1083ac..f423d1317 100644 --- a/mailbox/header.c +++ b/mailbox/header.c @@ -579,6 +579,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n) return MU_ERR_NOENT; mu_hdrent_remove (header, ent); + HEADER_SET_MODIFIED (header); free (ent); return 0; } |