diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-06-20 00:39:18 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-06-20 00:39:18 +0300 |
commit | 455554b8b04054e1db41b72426f7ee9d8579acf5 (patch) | |
tree | 8b6ff512af954dcf4c6cc1525b58b11e35788d1d | |
parent | 1ddc81a18a3f1491494ff7ec3a21e1bbcabf265a (diff) | |
download | mailutils-455554b8b04054e1db41b72426f7ee9d8579acf5.tar.gz mailutils-455554b8b04054e1db41b72426f7ee9d8579acf5.tar.bz2 |
API for formatting message sets on output
* libmailutils/msgset/print.c (mu_msgset_formats): New global.
(mu_stream_msgset_format): New function.
* include/mailutils/msgset.h (mu_msgset_format): New struct.
(mu_msgset_fmt_imap, mu_msgset_fmt_mh): New defines.
(MU_MSGSET_IGNORE_TRANSERR): New flag
(mu_msgset_copy, mu_msgset_translate): New protos.
(mu_stream_msgset_format, mu_msgset_imap_print): New protos.
(mu_msgset_print): Deprecate.
* libmailutils/imapio/sendmsgset.c: Use mu_msgset_imap_print
instead of mu_msgset_print.
* mu/libexec/imap.c: Likewise.
* libmailutils/msgset/Makefile.am: Add copy.c
* libmailutils/msgset/add.c (mu_msgset_add_range): Translate if
message set mode doesn't match the requested one.
* libmailutils/msgset/sub.c (mu_msgset_sub_range): Likewise.
* libmailutils/msgset/trans.c (_mu_msgset_translate_pair): Act
according to the mode argument.
(mu_msgset_translate): New function.
* libmailutils/tests/msgset.c: New option -mh
* mh/mh_sequence.c (write_sequence): Rewrite.
* testsuite/msgset.c: Optionally translate uids to msgnums and
vice-versa.
-rw-r--r-- | include/mailutils/msgset.h | 41 | ||||
-rw-r--r-- | include/mailutils/sys/msgset.h | 1 | ||||
-rw-r--r-- | libmailutils/imapio/sendmsgset.c | 2 | ||||
-rw-r--r-- | libmailutils/msgset/Makefile.am | 1 | ||||
-rw-r--r-- | libmailutils/msgset/add.c | 6 | ||||
-rw-r--r-- | libmailutils/msgset/print.c | 55 | ||||
-rw-r--r-- | libmailutils/msgset/sub.c | 6 | ||||
-rw-r--r-- | libmailutils/msgset/trans.c | 75 | ||||
-rw-r--r-- | libmailutils/tests/msgset.c | 8 | ||||
-rw-r--r-- | mh/inc.c | 4 | ||||
-rw-r--r-- | mh/mh_msgset.c | 1 | ||||
-rw-r--r-- | mh/mh_sequence.c | 87 | ||||
-rw-r--r-- | mu/libexec/imap.c | 2 | ||||
-rw-r--r-- | testsuite/msgset.c | 20 |
14 files changed, 212 insertions, 97 deletions
diff --git a/include/mailutils/msgset.h b/include/mailutils/msgset.h index 8f3b6e1bf..cad1532ae 100644 --- a/include/mailutils/msgset.h +++ b/include/mailutils/msgset.h @@ -30,6 +30,25 @@ struct mu_msgrange size_t msg_end; }; +struct mu_msgset_format +{ + char *range; /* range separator (e.g., ":" for IMAP, "-" for MH) */ + char *delim; /* delimiter (e.g., "," for IMAP, " " for MH) */ + char *last; /* last message marker (e.g., "*" for IMAP, "last" for MH) */ + char *empty; /* empty list representation ( "NIL", for IMAP, NULL for MH */ +}; + +enum + { + MU_MSGSET_FMT_IMAP, + MU_MSGSET_FMT_MH + }; + +extern struct mu_msgset_format const mu_msgset_formats[]; +typedef struct mu_msgset_format const *mu_msgset_format_t; +#define mu_msgset_fmt_imap (&mu_msgset_formats[MU_MSGSET_FMT_IMAP]) +#define mu_msgset_fmt_mh (&mu_msgset_formats[MU_MSGSET_FMT_MH]) + /* Message numbers start with 1. MU_MSGNO_LAST denotes the last message. */ #define MU_MSGNO_LAST 0 @@ -37,9 +56,15 @@ struct mu_msgrange #define MU_MSGSET_NUM 0 /* Message set operates on sequence numbers */ #define MU_MSGSET_UID 1 /* Message set operates on UIDs */ +#define MU_MSGSET_IGNORE_TRANSERR 0x10 + #define MU_MSGSET_MODE_MASK 0x0f int mu_msgset_create (mu_msgset_t *pmsgset, mu_mailbox_t mbox, int mode); + +int mu_msgset_copy (mu_msgset_t src, mu_msgset_t dst); +int mu_msgset_translate (mu_msgset_t *dst, mu_msgset_t src, int flags); + int mu_msgset_get_list (mu_msgset_t msgset, mu_list_t *plist); int mu_msgset_get_iterator (mu_msgset_t msgset, mu_iterator_t *pitr); @@ -54,9 +79,21 @@ int mu_msgset_clear (mu_msgset_t set); void mu_msgset_free (mu_msgset_t set); void mu_msgset_destroy (mu_msgset_t *set); -int mu_msgset_parse_imap (mu_msgset_t set, int mode, const char *s, char **end); +int mu_msgset_parse_imap (mu_msgset_t set, int mode, const char *s, + char **end); + +int mu_stream_msgset_format (mu_stream_t str, + struct mu_msgset_format const *fmt, + mu_msgset_t mset); +int mu_msgset_print (mu_stream_t str, mu_msgset_t msgset) + MU_DEPRECATED; + +static inline int +mu_msgset_imap_print (mu_stream_t str, mu_msgset_t mset) +{ + return mu_stream_msgset_format (str, mu_msgset_fmt_imap, mset); +} -int mu_msgset_print (mu_stream_t str, mu_msgset_t msgset); int mu_msgset_locate (mu_msgset_t msgset, size_t n, struct mu_msgrange const **prange); diff --git a/include/mailutils/sys/msgset.h b/include/mailutils/sys/msgset.h index 8bb12091e..2392ff1e9 100644 --- a/include/mailutils/sys/msgset.h +++ b/include/mailutils/sys/msgset.h @@ -27,6 +27,7 @@ struct _mu_msgset mu_list_t list; /* List of mu_msgrange structures */ mu_mailbox_t mbox; /* Associated mailbox */ int flags; /* Message set flags */ + size_t format; /* Format index */ }; int _mu_msgset_translate_pair (mu_msgset_t mset, int mode, diff --git a/libmailutils/imapio/sendmsgset.c b/libmailutils/imapio/sendmsgset.c index 7310c956a..9ed85ce65 100644 --- a/libmailutils/imapio/sendmsgset.c +++ b/libmailutils/imapio/sendmsgset.c @@ -25,5 +25,5 @@ int mu_imapio_send_msgset (mu_imapio_t io, mu_msgset_t msgset) { - return mu_msgset_print (io->_imap_stream, msgset); + return mu_msgset_imap_print (io->_imap_stream, msgset); } diff --git a/libmailutils/msgset/Makefile.am b/libmailutils/msgset/Makefile.am index 1dd608ad5..806d5d38b 100644 --- a/libmailutils/msgset/Makefile.am +++ b/libmailutils/msgset/Makefile.am @@ -22,6 +22,7 @@ libmsgset_la_SOURCES = \ addset.c\ aggr.c\ clear.c\ + copy.c\ create.c\ count.c\ getitr.c\ diff --git a/libmailutils/msgset/add.c b/libmailutils/msgset/add.c index 3e11f5ab4..f16f73450 100644 --- a/libmailutils/msgset/add.c +++ b/libmailutils/msgset/add.c @@ -41,12 +41,16 @@ mu_msgset_add_range (mu_msgset_t mset, size_t beg, size_t end, int mode) return ENOMEM; range->msg_beg = beg; range->msg_end = end; - rc = _mu_msgset_translate_range (mset, mode, range); + if (mode != _MU_MSGSET_MODE (mset->flags)) + { + rc = _mu_msgset_translate_range (mset, _MU_MSGSET_MODE (mset->flags), + range); if (rc) { free (range); return rc; } + } rc = mu_list_append (mset->list, range); if (rc) free (range); diff --git a/libmailutils/msgset/print.c b/libmailutils/msgset/print.c index 108c70099..7c3816b6a 100644 --- a/libmailutils/msgset/print.c +++ b/libmailutils/msgset/print.c @@ -24,10 +24,26 @@ #include <mailutils/msgset.h> #include <mailutils/sys/msgset.h> +struct mu_msgset_format const mu_msgset_formats[] = { + [MU_MSGSET_FMT_IMAP] = { + .delim = ",", + .range = ":", + .last = "*", + .empty = "NIL" + }, + [MU_MSGSET_FMT_MH] = { + .delim = " ", + .range = "-", + .last = "last" + } +}; + + struct print_env { mu_stream_t stream; int cont; + struct mu_msgset_format const *fmt; }; static int @@ -39,36 +55,59 @@ _msgrange_printer (void *item, void *data) if (env->cont) { - rc = mu_stream_write (env->stream, ",", 1, NULL); + rc = mu_stream_printf (env->stream, "%s", env->fmt->delim); if (rc) return rc; } else env->cont = 1; + if (range->msg_beg == range->msg_end) rc = mu_stream_printf (env->stream, "%lu", (unsigned long) range->msg_beg); else if (range->msg_end == 0) - rc = mu_stream_printf (env->stream, "%lu:*", - (unsigned long) range->msg_beg); + rc = mu_stream_printf (env->stream, "%lu%s%s", + (unsigned long) range->msg_beg, + env->fmt->range, + env->fmt->last); + else if (range->msg_end == range->msg_beg + 1) + rc = mu_stream_printf (env->stream, "%lu%s%lu", + (unsigned long) range->msg_beg, + env->fmt->delim, + (unsigned long) range->msg_end); else - rc = mu_stream_printf (env->stream, "%lu:%lu", + rc = mu_stream_printf (env->stream, "%lu%s%lu", (unsigned long) range->msg_beg, + env->fmt->range, (unsigned long) range->msg_end); return rc; } int -mu_msgset_print (mu_stream_t str, mu_msgset_t mset) +mu_stream_msgset_format (mu_stream_t str, struct mu_msgset_format const *fmt, + mu_msgset_t mset) { struct print_env env; int rc; + env.stream = str; + env.cont = 0; + env.fmt = fmt; + if (mu_list_is_empty (mset->list)) - return mu_stream_printf (str, "%s", "nil"); + { + if (env.fmt->empty) + return mu_stream_printf (str, "%s", env.fmt->empty); + return 0; + } rc = mu_msgset_aggregate (mset); if (rc) return rc; - env.stream = str; - env.cont = 0; return mu_list_foreach (mset->list, _msgrange_printer, &env); } + +int +mu_msgset_print (mu_stream_t str, mu_msgset_t mset) +{ + return mu_stream_msgset_format (str, mu_msgset_fmt_imap, mset); +} + diff --git a/libmailutils/msgset/sub.c b/libmailutils/msgset/sub.c index efd578eed..af2bc60e6 100644 --- a/libmailutils/msgset/sub.c +++ b/libmailutils/msgset/sub.c @@ -129,11 +129,15 @@ mu_msgset_sub_range (mu_msgset_t mset, size_t beg, size_t end, int mode) beg = t; } - rc = _mu_msgset_translate_pair (mset, mode, &beg, &end); + if (mode != _MU_MSGSET_MODE (mset->flags)) + { + rc = _mu_msgset_translate_pair (mset, _MU_MSGSET_MODE (mset->flags), + &beg, &end); if (rc == MU_ERR_NOENT) return 0; else if (rc) return rc; + } rc = mu_msgset_aggregate (mset); if (rc) diff --git a/libmailutils/msgset/trans.c b/libmailutils/msgset/trans.c index 66cf8f651..b4e44fa7e 100644 --- a/libmailutils/msgset/trans.c +++ b/libmailutils/msgset/trans.c @@ -27,14 +27,14 @@ int _mu_msgset_translate_pair (mu_msgset_t mset, int mode, size_t *pbeg, size_t *pend) { - if (mode != _MU_MSGSET_MODE (mset->flags) && mset->mbox) + if (mset->mbox) { int cmd, rc; size_t n = 1; size_t beg = *pbeg; size_t end = *pend; - switch (_MU_MSGSET_MODE (mset->flags)) + switch (mode) { case MU_MSGSET_NUM: cmd = MU_MAILBOX_UID_TO_MSGNO; @@ -97,3 +97,74 @@ _mu_msgset_translate_range (mu_msgset_t mset, int mode, struct mu_msgrange *r) return _mu_msgset_translate_pair (mset, mode, &r->msg_beg, &r->msg_end); } +struct trans_closure +{ + mu_msgset_t mset; + int flags; +}; + +static int +trans_range (void *item, void *data) +{ + struct mu_msgrange const *range = item; + struct trans_closure *clos = data; + struct mu_msgrange *copy; + int rc; + + copy = malloc (sizeof *copy); + if (!copy) + return errno; + *copy = *range; + rc = _mu_msgset_translate_range (clos->mset, _MU_MSGSET_MODE (clos->flags), + copy); + switch (rc) + { + case 0: + rc = mu_list_append (clos->mset->list, copy); + break; + + case MU_ERR_NOENT: + if (clos->flags & MU_MSGSET_IGNORE_TRANSERR) + rc = 0; + /* fallthrough */ + + default: + free (copy); + } + + return rc; +} + +int +mu_msgset_translate (mu_msgset_t *dst, mu_msgset_t src, int flags) +{ + int rc; + mu_msgset_t tmp; + + rc = mu_msgset_create (&tmp, src->mbox, src->flags); + if (rc) + return rc; + + tmp->format = src->format; + + if (_MU_MSGSET_MODE (flags) == src->flags) + { + rc = mu_msgset_copy (src, tmp); + } + else + { + struct trans_closure tc; + tc.mset = tmp; + tc.flags = flags; + rc = mu_list_foreach (src->list, trans_range, &tc); + } + + if (rc) + mu_msgset_destroy (&tmp); + else + *dst = tmp; + + return rc; +} + + diff --git a/libmailutils/tests/msgset.c b/libmailutils/tests/msgset.c index 6d6a06dc9..c9aa53182 100644 --- a/libmailutils/tests/msgset.c +++ b/libmailutils/tests/msgset.c @@ -18,6 +18,8 @@ #include <stdlib.h> #include <mailutils/mailutils.h> +mu_msgset_format_t format = mu_msgset_fmt_imap; + static void parse_msgrange (char *arg, struct mu_msgrange *range) { @@ -76,7 +78,7 @@ parse_msgset (const char *arg) static void print_all (mu_msgset_t msgset) { - MU_ASSERT (mu_msgset_print (mu_strout, msgset)); + MU_ASSERT (mu_stream_msgset_format (mu_strout, format, msgset)); mu_printf ("\n"); } @@ -111,13 +113,15 @@ main (int argc, char **argv) if (strcmp (arg, "-h") == 0 || strcmp (arg, "-help") == 0) { - mu_printf ("usage: %s [-msgset=SET] [-add=X[:Y]] [-del=X[:Y]] " + mu_printf ("usage: %s [-mh] [-msgset=SET] [-add=X[:Y]] [-del=X[:Y]] " "[-addset=SET] [-delset=SET] [-first] [-last] ...\n", mu_program_name); return 0; } else if (strncmp (arg, "-msgset=", 8) == 0) msgset_string = arg + 8; + else if (strcmp (arg, "-mh") == 0) + format = mu_msgset_fmt_mh; else break; } @@ -440,9 +440,7 @@ main (int argc, char **argv) mu_msgset_create (&unseen, NULL, MU_MSGSET_NUM); mu_msgset_add_range (unseen, lastseen, incdat.lastmsg, MU_MSGSET_NUM); - mh_seq_add (incdat.output, - unseen_seq, - unseen, 0); + mh_seq_add (incdat.output, unseen_seq, unseen, 0); mu_msgset_free (unseen); } diff --git a/mh/mh_msgset.c b/mh/mh_msgset.c index 3b961d5c7..5b372cc63 100644 --- a/mh/mh_msgset.c +++ b/mh/mh_msgset.c @@ -119,6 +119,7 @@ msgset_parser_init (struct msgset_parser *parser, mu_mailbox_t mbox, mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_create", NULL, rc); exit (1); } + parser->argc = argc; parser->argv = argv; parser->curp = ""; diff --git a/mh/mh_sequence.c b/mh/mh_sequence.c index 5ae37c621..50c6ca248 100644 --- a/mh/mh_sequence.c +++ b/mh/mh_sequence.c @@ -47,6 +47,8 @@ mh_seq_read (mu_mailbox_t mbox, const char *name, int flags) static void write_sequence (mu_mailbox_t mbox, const char *name, char *value, int private) { + if (value && value[0] == 0) + value = NULL; if (private) { char *p = private_sequence_name (name); @@ -63,96 +65,35 @@ delete_sequence (mu_mailbox_t mbox, const char *name, int private) write_sequence (mbox, name, NULL, private); } -struct format_closure -{ - mu_stream_t stream; - mu_mailbox_t mailbox; - int delim; -}; - -static int -format_sequence (void *item, void *data) -{ - struct mu_msgrange *r = item; - struct format_closure *clos = data; - int rc; - size_t beg, end; - - if (clos->mailbox) - { - rc = mu_mailbox_translate (clos->mailbox, - MU_MAILBOX_MSGNO_TO_UID, - r->msg_beg, &beg); - if (rc) - return rc; - } - else - beg = r->msg_beg; - if (clos->delim) - mu_stream_write (clos->stream, " ", 1, NULL); - if (r->msg_beg == r->msg_end) - rc = mu_stream_printf (clos->stream, "%lu", (unsigned long) beg); - else - { - if (clos->mailbox) - { - rc = mu_mailbox_translate (clos->mailbox, - MU_MAILBOX_MSGNO_TO_UID, - r->msg_end, &end); - if (rc) - return rc; - } - else - end = r->msg_end; - if (beg + 1 == end) - rc = mu_stream_printf (clos->stream, "%lu %lu", - (unsigned long) beg, - (unsigned long) end); - else - rc = mu_stream_printf (clos->stream, "%lu-%lu", - (unsigned long) beg, - (unsigned long) end); - } - clos->delim = 1; - return rc; -} - static void save_sequence (mu_mailbox_t mbox, const char *name, mu_msgset_t mset, int flags) { - mu_list_t list; - - mu_msgset_get_list (mset, &list); - if (mu_list_is_empty (list)) - write_sequence (mset->mbox, name, NULL, flags & SEQ_PRIVATE); - else - { - struct format_closure clos; int rc; + mu_stream_t mstr; + mu_msgset_t outset; mu_transport_t trans[2]; - rc = mu_memory_stream_create (&clos.stream, MU_STREAM_RDWR); + rc = mu_msgset_translate (&outset, mset, + MU_MSGSET_UID|MU_MSGSET_IGNORE_TRANSERR); if (rc) { - mu_diag_funcall (MU_DIAG_ERROR, "mu_memory_stream_create", NULL, rc); + mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_translate", NULL, rc); exit (1); } - clos.mailbox = mset->mbox; - clos.delim = 0; - rc = mu_list_foreach (list, format_sequence, &clos); + rc = mu_memory_stream_create (&mstr, MU_STREAM_RDWR); if (rc) { - mu_diag_funcall (MU_DIAG_ERROR, "mu_list_foreach", NULL, rc); + mu_diag_funcall (MU_DIAG_ERROR, "mu_memory_stream_create", NULL, rc); exit (1); } - mu_stream_write (clos.stream, "", 1, NULL); - mu_stream_ioctl (clos.stream, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, - trans); + mu_stream_msgset_format (mstr, mu_msgset_fmt_mh, outset); + mu_stream_write (mstr, "", 1, NULL); + mu_stream_ioctl (mstr, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans); write_sequence (mbox, name, (char*)trans[0], flags & SEQ_PRIVATE); - mu_stream_unref (clos.stream); - } + mu_stream_unref (mstr); + mu_msgset_free (outset); } void diff --git a/mu/libexec/imap.c b/mu/libexec/imap.c index a56af8c77..37d494a7a 100644 --- a/mu/libexec/imap.c +++ b/mu/libexec/imap.c @@ -1100,7 +1100,7 @@ com_search (int argc, char **argv) return 0; } mu_printf ("%lu matches:", (unsigned long) count); - mu_msgset_print (mu_strout, mset); + mu_msgset_imap_print (mu_strout, mset); mu_printf ("\n"); mu_msgset_free (mset); diff --git a/testsuite/msgset.c b/testsuite/msgset.c index 18a62a244..215c3d585 100644 --- a/testsuite/msgset.c +++ b/testsuite/msgset.c @@ -79,13 +79,16 @@ main (int argc, char **argv) { int i; char *msgset_string = NULL; - mu_msgset_t msgset; + mu_msgset_t msgset, outset; int create_mode = MU_MSGSET_NUM; int parse_mode = MU_MSGSET_NUM; + int output_mode = MU_MSGSET_NUM; + int output_flags = 0; + mu_msgset_format_t format = mu_msgset_fmt_imap; mu_mailbox_t mbox = NULL; mu_set_program_name (argv[0]); - mu_registrar_record (mu_mbox_record); + mu_register_local_mbox_formats (); for (i = 1; i < argc; i++) { char *arg = argv[i]; @@ -114,6 +117,14 @@ main (int argc, char **argv) MU_ASSERT (mu_mailbox_create (&mbox, arg + 9)); MU_ASSERT (mu_mailbox_open (mbox, MU_STREAM_READ)); } + else if (strcmp (arg, "-mh") == 0) + format = mu_msgset_fmt_mh; + else if (strcmp (arg, "-printuid") == 0) + output_mode = MU_MSGSET_UID; + else if (strcmp (arg, "-printnum") == 0) + output_mode = MU_MSGSET_NUM; + else if (strcmp (arg, "-ignore-error") == 0) + output_flags = MU_MSGSET_IGNORE_TRANSERR; else break; } @@ -230,8 +241,11 @@ main (int argc, char **argv) return 1; } } - MU_ASSERT (mu_msgset_print (mu_strout, msgset)); + + MU_ASSERT (mu_msgset_translate (&outset, msgset, output_mode|output_flags)); + MU_ASSERT (mu_stream_msgset_format (mu_strout, format, outset)); mu_printf ("\n"); + mu_msgset_free (outset); mu_msgset_free (msgset); return 0; |