Commit 26cfa219 26cfa2197d5a2866f1a08c48f94d65504fdef7b1 by Sergey Poznyakoff

msgset: implement "foreach" calls.

* imap4d/copy.c (copy_env) <src>: Remove. Not needed now.
(size_sum,do_copy): Change to a mu_msgset_message_action_t.
(try_copy,safe_copy): Change signature; use mu_msgset_foreach_message.
* imap4d/fetch.c (_fetch_from_message): Change to a
mu_msgset_message_action_t.
(imap4d_fetch0): Use mu_msgset_foreach_message.
* imap4d/imap4d.h (imap4d_message_action_t): Remove typedef.
(util_foreach_message): Remove. Use mu_msgset_foreach_message.
* imap4d/store.c (_do_store): Change to a mu_msgset_message_action_t.
(imap4d_store0): Use mu_msgset_foreach_message.
* imap4d/util.c (util_foreach_message): Remove.
* include/mailutils/list.h (mu_list_foreach_dir): New proto.
* include/mailutils/msgset.h (mu_msgset_msgno_action_t)
(mu_msgset_message_action_t): New typedefs.
(mu_msgset_negate,mu_msgset_foreach_dir_msgno)
(mu_msgset_foreach_msgno,mu_msgset_foreach_dir_message)
(mu_msgset_foreach_message): New protos.
* libmailutils/list/foreachdir.c: New file.
* libmailutils/list/Makefile.am (liblist_la_SOURCES): Add foreachdir.c.
* libmailutils/list/head.c (mu_list_head): Fix conditional.
* libmailutils/list/tail.c (mu_list_tail): Likewise.
* libmailutils/msgset/foreachmsg.c: New file.
* libmailutils/msgset/foreachnum.c: New file.
* libmailutils/msgset/negate.c: New file.
* libmailutils/msgset/Makefile.am (libmsgset_la_SOURCES): Add
new files.
* libmailutils/msgset/getitr.c (mu_msgset_get_iterator): Call
mu_msgset_aggregate before doing anything.
* libmailutils/msgset/getlist.c (mu_msgset_get_list): Likewise.
* libmailutils/msgset/locate.c (mu_msgset_locate): Likewise.
* libmailutils/msgset/parse.c (parse_msgrange): Remove duplicated
code.
* testsuite/msgset.c: Implement -neg option.
1 parent e7ab6892
...@@ -58,57 +58,35 @@ imap4d_copy (struct imap4d_command *command, imap4d_tokbuf_t tok) ...@@ -58,57 +58,35 @@ imap4d_copy (struct imap4d_command *command, imap4d_tokbuf_t tok)
58 struct copy_env 58 struct copy_env
59 { 59 {
60 mu_mailbox_t dst; 60 mu_mailbox_t dst;
61 mu_mailbox_t src;
62 mu_off_t total; 61 mu_off_t total;
63 int ret; 62 int ret;
64 char **err_text; 63 char **err_text;
65 }; 64 };
66 65
67 static int 66 static int
68 size_sum (size_t msgno, void *data) 67 size_sum (size_t msgno, mu_message_t msg, void *data)
69 { 68 {
70 struct copy_env *env = data; 69 struct copy_env *env = data;
71 mu_message_t msg = NULL;
72 int rc; 70 int rc;
73 71
74 rc = mu_mailbox_get_message (env->src, msgno, &msg); 72 size_t size;
73 rc = mu_message_size (msg, &size);
75 if (rc) 74 if (rc)
76 { 75 {
77 mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL, rc); 76 mu_diag_funcall (MU_DIAG_ERROR, "mu_message_size", NULL, rc);
78 env->ret = RESP_NO; 77 env->ret = RESP_BAD;
79 return MU_ERR_FAILURE; 78 return MU_ERR_FAILURE;
80 } 79 }
81 else 80 env->total += size;
82 {
83 size_t size;
84 rc = mu_message_size (msg, &size);
85 if (rc)
86 {
87 mu_diag_funcall (MU_DIAG_ERROR, "mu_message_size", NULL, rc);
88 env->ret = RESP_BAD;
89 return MU_ERR_FAILURE;
90 }
91 env->total += size;
92 }
93 return 0; 81 return 0;
94 } 82 }
95 83
96 static int 84 static int
97 do_copy (size_t msgno, void *data) 85 do_copy (size_t msgno, mu_message_t msg, void *data)
98 { 86 {
99 struct copy_env *env = data; 87 struct copy_env *env = data;
100 mu_message_t msg = NULL;
101 int status; 88 int status;
102 89
103 status = mu_mailbox_get_message (env->src, msgno, &msg);
104 if (status)
105 {
106 mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL,
107 status);
108 env->ret = RESP_BAD;
109 return MU_ERR_FAILURE;
110 }
111
112 imap4d_enter_critical (); 90 imap4d_enter_critical ();
113 status = mu_mailbox_append_message (env->dst, msg); 91 status = mu_mailbox_append_message (env->dst, msg);
114 imap4d_leave_critical (); 92 imap4d_leave_critical ();
...@@ -124,14 +102,12 @@ do_copy (size_t msgno, void *data) ...@@ -124,14 +102,12 @@ do_copy (size_t msgno, void *data)
124 } 102 }
125 103
126 static int 104 static int
127 try_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset, 105 try_copy (mu_mailbox_t dst, mu_msgset_t msgset, char **err_text)
128 char **err_text)
129 { 106 {
130 int rc; 107 int rc;
131 struct copy_env env; 108 struct copy_env env;
132 109
133 env.dst = dst; 110 env.dst = dst;
134 env.src = src;
135 env.total = 0; 111 env.total = 0;
136 env.ret = RESP_OK; 112 env.ret = RESP_OK;
137 env.err_text = err_text; 113 env.err_text = err_text;
...@@ -139,7 +115,7 @@ try_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset, ...@@ -139,7 +115,7 @@ try_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset,
139 *env.err_text = "Operation failed"; 115 *env.err_text = "Operation failed";
140 116
141 /* Check size */ 117 /* Check size */
142 rc = util_foreach_message (msgset, size_sum, &env); 118 rc = mu_msgset_foreach_message (msgset, size_sum, &env);
143 if (rc) 119 if (rc)
144 return RESP_NO; 120 return RESP_NO;
145 if (env.ret != RESP_OK) 121 if (env.ret != RESP_OK)
...@@ -151,7 +127,7 @@ try_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset, ...@@ -151,7 +127,7 @@ try_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset,
151 return RESP_NO; 127 return RESP_NO;
152 } 128 }
153 env.total = 0; 129 env.total = 0;
154 rc = util_foreach_message (msgset, do_copy, &env); 130 rc = mu_msgset_foreach_message (msgset, do_copy, &env);
155 quota_update (env.total); 131 quota_update (env.total);
156 if (rc) 132 if (rc)
157 return RESP_NO; 133 return RESP_NO;
...@@ -159,8 +135,7 @@ try_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset, ...@@ -159,8 +135,7 @@ try_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset,
159 } 135 }
160 136
161 static int 137 static int
162 safe_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset, 138 safe_copy (mu_mailbox_t dst, mu_msgset_t msgset, char **err_text)
163 char **err_text)
164 { 139 {
165 size_t nmesg; 140 size_t nmesg;
166 int status; 141 int status;
...@@ -174,7 +149,7 @@ safe_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset, ...@@ -174,7 +149,7 @@ safe_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_msgset_t msgset,
174 return RESP_NO; 149 return RESP_NO;
175 } 150 }
176 151
177 status = try_copy (dst, src, msgset, err_text); 152 status = try_copy (dst, msgset, err_text);
178 if (status != RESP_OK) 153 if (status != RESP_OK)
179 { 154 {
180 size_t maxmesg; 155 size_t maxmesg;
...@@ -283,7 +258,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -283,7 +258,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
283 mu_list_t msglist; 258 mu_list_t msglist;
284 mu_msgset_get_list (msgset, &msglist); 259 mu_msgset_get_list (msgset, &msglist);
285 if (!mu_list_is_empty (msglist)) 260 if (!mu_list_is_empty (msglist))
286 status = safe_copy (cmbox, mbox, msgset, err_text); 261 status = safe_copy (cmbox, msgset, err_text);
287 mu_mailbox_close (cmbox); 262 mu_mailbox_close (cmbox);
288 } 263 }
289 mu_mailbox_destroy (&cmbox); 264 mu_mailbox_destroy (&cmbox);
......
...@@ -1783,19 +1783,19 @@ fetch_thunk (imap4d_parsebuf_t pb) ...@@ -1783,19 +1783,19 @@ fetch_thunk (imap4d_parsebuf_t pb)
1783 } 1783 }
1784 1784
1785 int 1785 int
1786 _fetch_from_message (size_t msgno, void *data) 1786 _fetch_from_message (size_t msgno, mu_message_t msg, void *data)
1787 { 1787 {
1788 int rc = 0; 1788 int rc = 0;
1789 struct fetch_runtime_closure *frc = data; 1789 struct fetch_runtime_closure *frc = data;
1790 1790
1791 frc->msgno = msgno; 1791 frc->msgno = msgno;
1792 if (mu_mailbox_get_message (mbox, msgno, &frc->msg) == 0) 1792 frc->msg = msg;
1793 { 1793
1794 io_sendf ("* %lu FETCH (", (unsigned long) msgno); 1794 io_sendf ("* %lu FETCH (", (unsigned long) msgno);
1795 frc->eltno = 0; 1795 frc->eltno = 0;
1796 rc = mu_list_foreach (frc->fnlist, _do_fetch, frc); 1796 rc = mu_list_foreach (frc->fnlist, _do_fetch, frc);
1797 io_sendf (")\n"); 1797 io_sendf (")\n");
1798 } 1798
1799 return rc; 1799 return rc;
1800 } 1800 }
1801 1801
...@@ -1833,7 +1833,7 @@ imap4d_fetch0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -1833,7 +1833,7 @@ imap4d_fetch0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
1833 loop below */ 1833 loop below */
1834 frc.err_text = "Completed"; 1834 frc.err_text = "Completed";
1835 1835
1836 util_foreach_message (pclos.msgset, _fetch_from_message, &frc); 1836 mu_msgset_foreach_message (pclos.msgset, _fetch_from_message, &frc);
1837 mu_list_destroy (&frc.msglist); 1837 mu_list_destroy (&frc.msglist);
1838 } 1838 }
1839 1839
......
...@@ -372,11 +372,6 @@ extern char *util_getfullpath (const char *); ...@@ -372,11 +372,6 @@ extern char *util_getfullpath (const char *);
372 extern struct imap4d_command *util_getcommand (char *, 372 extern struct imap4d_command *util_getcommand (char *,
373 struct imap4d_command []); 373 struct imap4d_command []);
374 374
375 typedef int (*imap4d_message_action_t) (size_t, void *);
376
377 int util_foreach_message (mu_msgset_t list, imap4d_message_action_t action,
378 void *data);
379
380 enum datetime_parse_mode /* how to parse date/time strings */ 375 enum datetime_parse_mode /* how to parse date/time strings */
381 { 376 {
382 datetime_default, /* default mode */ 377 datetime_default, /* default mode */
......
...@@ -91,13 +91,11 @@ store_thunk (imap4d_parsebuf_t p) ...@@ -91,13 +91,11 @@ store_thunk (imap4d_parsebuf_t p)
91 } 91 }
92 92
93 static int 93 static int
94 _do_store (size_t msgno, void *data) 94 _do_store (size_t msgno, mu_message_t msg, void *data)
95 { 95 {
96 struct store_parse_closure *pclos = data; 96 struct store_parse_closure *pclos = data;
97 mu_message_t msg = NULL;
98 mu_attribute_t attr = NULL; 97 mu_attribute_t attr = NULL;
99 98
100 mu_mailbox_get_message (mbox, msgno, &msg);
101 mu_message_get_attribute (msg, &attr); 99 mu_message_get_attribute (msg, &attr);
102 100
103 switch (pclos->how) 101 switch (pclos->how)
...@@ -154,7 +152,7 @@ imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char **ptext) ...@@ -154,7 +152,7 @@ imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char **ptext)
154 ptext); 152 ptext);
155 if (rc == RESP_OK) 153 if (rc == RESP_OK)
156 { 154 {
157 util_foreach_message (pclos.msgset, _do_store, &pclos); 155 mu_msgset_foreach_message (pclos.msgset, _do_store, &pclos);
158 156
159 *ptext = "Completed"; 157 *ptext = "Completed";
160 } 158 }
......
...@@ -39,42 +39,6 @@ util_getfullpath (const char *name) ...@@ -39,42 +39,6 @@ util_getfullpath (const char *name)
39 return mu_normalize_path (exp); 39 return mu_normalize_path (exp);
40 } 40 }
41 41
42 struct action_closure
43 {
44 imap4d_message_action_t action;
45 void *data;
46 };
47
48 static int
49 procrange (void *item, void *data)
50 {
51 struct mu_msgrange *mp = item;
52 struct action_closure *clos = data;
53 size_t i;
54
55 for (i = mp->msg_beg; i <= mp->msg_end; i++)
56 {
57 int rc = clos->action (i, clos->data);
58 if (rc)
59 return rc;
60 }
61 return 0;
62 }
63
64 /* Apply ACTION to each message number from LIST. */
65 int
66 util_foreach_message (mu_msgset_t msgset, imap4d_message_action_t action,
67 void *data)
68 {
69 mu_list_t list;
70 struct action_closure clos;
71
72 clos.action = action;
73 clos.data = data;
74 mu_msgset_get_list (msgset, &list);
75 return mu_list_foreach (list, procrange, &clos);
76 }
77
78 int 42 int
79 util_do_command (imap4d_tokbuf_t tok) 43 util_do_command (imap4d_tokbuf_t tok)
80 { 44 {
......
...@@ -144,10 +144,15 @@ int mu_list_get_iterator (mu_list_t _list, mu_iterator_t *_pitr); ...@@ -144,10 +144,15 @@ int mu_list_get_iterator (mu_list_t _list, mu_iterator_t *_pitr);
144 typedef int (*mu_list_action_t) (void *_item, void *_data); 144 typedef int (*mu_list_action_t) (void *_item, void *_data);
145 145
146 /* Execute _action for each element in _list. Use _data as the call-specific 146 /* Execute _action for each element in _list. Use _data as the call-specific
147 data. */ 147 data. If _dir is 0, traverse the list from head to tail. If it is 1,
148 traverse it in the reverse direction */
149 int mu_list_foreach_dir (mu_list_t _list, int _dir, mu_list_action_t _action,
150 void *_cbdata);
151 /* Same as mu_list_foreach_dir with _dir==0. */
148 int mu_list_foreach (mu_list_t _list, mu_list_action_t _action, void *_data); 152 int mu_list_foreach (mu_list_t _list, mu_list_action_t _action, void *_data);
149 /* A historical alias to the above. */ 153 /* A historical alias to the above. */
150 int mu_list_do (mu_list_t, mu_list_action_t, void *) MU_DEPRECATED; 154 int mu_list_do (mu_list_t, mu_list_action_t, void *) MU_DEPRECATED;
155
151 156
152 /* ************************************************* */ 157 /* ************************************************* */
153 /* Functions for combining two lists. */ 158 /* Functions for combining two lists. */
......
...@@ -33,7 +33,7 @@ struct mu_msgrange ...@@ -33,7 +33,7 @@ struct mu_msgrange
33 #define MU_MSGNO_LAST 0 33 #define MU_MSGNO_LAST 0
34 34
35 #define MU_MSGSET_UID 0x01 /* Message set operates on UIDs */ 35 #define MU_MSGSET_UID 0x01 /* Message set operates on UIDs */
36 36
37 int mu_msgset_create (mu_msgset_t *pmsgset, mu_mailbox_t mbox, int flags); 37 int mu_msgset_create (mu_msgset_t *pmsgset, mu_mailbox_t mbox, int flags);
38 int mu_msgset_get_list (mu_msgset_t msgset, mu_list_t *plist); 38 int mu_msgset_get_list (mu_msgset_t msgset, mu_list_t *plist);
39 int mu_msgset_get_iterator (mu_msgset_t msgset, mu_iterator_t *pitr); 39 int mu_msgset_get_iterator (mu_msgset_t msgset, mu_iterator_t *pitr);
...@@ -53,6 +53,26 @@ int mu_msgset_print (mu_stream_t str, mu_msgset_t msgset); ...@@ -53,6 +53,26 @@ int mu_msgset_print (mu_stream_t str, mu_msgset_t msgset);
53 53
54 int mu_msgset_locate (mu_msgset_t msgset, size_t n, 54 int mu_msgset_locate (mu_msgset_t msgset, size_t n,
55 struct mu_msgrange const **prange); 55 struct mu_msgrange const **prange);
56
57 int mu_msgset_negate (mu_msgset_t msgset, mu_msgset_t *pnset);
58
59 typedef int (*mu_msgset_msgno_action_t) (size_t _n, void *_call_data);
60 typedef int (*mu_msgset_message_action_t) (size_t _n, mu_message_t _msg,
61 void *_call_data);
62
63 int mu_msgset_foreach_dir_msgno (mu_msgset_t _msgset, int _dir,
64 mu_msgset_msgno_action_t _action,
65 void *_data);
66 int mu_msgset_foreach_msgno (mu_msgset_t _msgset,
67 mu_msgset_msgno_action_t _action,
68 void *_call_data);
69 int mu_msgset_foreach_dir_message (mu_msgset_t _msgset, int _dir,
70 mu_msgset_message_action_t _action,
71 void *_call_data);
72 int mu_msgset_foreach_message (mu_msgset_t _msgset,
73 mu_msgset_message_action_t _action,
74 void *_call_data);
75
56 76
57 #ifdef __cplusplus 77 #ifdef __cplusplus
58 } 78 }
......
...@@ -29,6 +29,7 @@ liblist_la_SOURCES = \ ...@@ -29,6 +29,7 @@ liblist_la_SOURCES = \
29 foreach.c\ 29 foreach.c\
30 get.c\ 30 get.c\
31 getcomp.c\ 31 getcomp.c\
32 foreachdir.c\
32 gmap.c\ 33 gmap.c\
33 head.c\ 34 head.c\
34 insert.c\ 35 insert.c\
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2010, 2011
3 Free Software Foundation, Inc.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 3 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General
16 Public License along with this library. If not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 #include <stdlib.h>
23 #include <mailutils/sys/list.h>
24 #include <mailutils/errno.h>
25
26 int
27 mu_list_foreach_dir (mu_list_t list, int dir,
28 mu_list_action_t action, void *cbdata)
29 {
30 mu_iterator_t itr;
31 int status = 0;
32
33 if (list == NULL || action == NULL)
34 return EINVAL;
35 status = mu_list_get_iterator (list, &itr);
36 if (status)
37 return status;
38
39 status = mu_iterator_ctl (itr, mu_itrctl_set_direction, &dir);
40 if (status == 0)
41 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
42 mu_iterator_next (itr))
43 {
44 void *item;
45 mu_iterator_current (itr, &item);
46 if ((status = action (item, cbdata)))
47 break;
48 }
49 mu_iterator_destroy (&itr);
50 return status;
51 }
52
...@@ -29,7 +29,7 @@ mu_list_head (mu_list_t list, void **pitem) ...@@ -29,7 +29,7 @@ mu_list_head (mu_list_t list, void **pitem)
29 return EINVAL; 29 return EINVAL;
30 if (pitem == NULL) 30 if (pitem == NULL)
31 return MU_ERR_OUT_PTR_NULL; 31 return MU_ERR_OUT_PTR_NULL;
32 if (!list->head.next) 32 if (list->head.next == &list->head)
33 return MU_ERR_NOENT; 33 return MU_ERR_NOENT;
34 *pitem = list->head.next->item; 34 *pitem = list->head.next->item;
35 return 0; 35 return 0;
......
...@@ -29,7 +29,7 @@ mu_list_tail (mu_list_t list, void **pitem) ...@@ -29,7 +29,7 @@ mu_list_tail (mu_list_t list, void **pitem)
29 return EINVAL; 29 return EINVAL;
30 if (pitem == NULL) 30 if (pitem == NULL)
31 return MU_ERR_OUT_PTR_NULL; 31 return MU_ERR_OUT_PTR_NULL;
32 if (!list->head.prev) 32 if (list->head.prev == &list->head)
33 return MU_ERR_NOENT; 33 return MU_ERR_NOENT;
34 *pitem = list->head.prev->item; 34 *pitem = list->head.prev->item;
35 return 0; 35 return 0;
......
...@@ -24,8 +24,11 @@ libmsgset_la_SOURCES = \ ...@@ -24,8 +24,11 @@ libmsgset_la_SOURCES = \
24 create.c\ 24 create.c\
25 getitr.c\ 25 getitr.c\
26 getlist.c\ 26 getlist.c\
27 foreachnum.c\
28 foreachmsg.c\
27 free.c\ 29 free.c\
28 locate.c\ 30 locate.c\
31 negate.c\
29 parse.c\ 32 parse.c\
30 print.c\ 33 print.c\
31 sub.c 34 sub.c
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <stdlib.h>
19 #include <mailutils/types.h>
20 #include <mailutils/errno.h>
21 #include <mailutils/list.h>
22 #include <mailutils/msgset.h>
23 #include <mailutils/mailbox.h>
24 #include <mailutils/sys/msgset.h>
25
26 struct action_closure
27 {
28 mu_msgset_message_action_t action;
29 void *data;
30 mu_msgset_t msgset;
31 int dir;
32 };
33
34 static int
35 procrange (void *item, void *data)
36 {
37 struct mu_msgrange *mp = item;
38 struct action_closure *clos = data;
39 size_t i;
40
41 if (clos->dir)
42 for (i = mp->msg_end; i >= mp->msg_beg; i--)
43 {
44 int rc;
45 mu_message_t msg = NULL;
46
47 if (clos->msgset->mbox)
48 {
49 rc = mu_mailbox_get_message (clos->msgset->mbox, i, &msg);
50 if (rc == MU_ERR_NOENT)
51 continue;
52 else if (rc)
53 return rc;
54 }
55 rc = clos->action (i, msg, clos->data);
56 if (rc)
57 return rc;
58 }
59 else
60 for (i = mp->msg_beg; i <= mp->msg_end; i++)
61 {
62 int rc;
63 mu_message_t msg = NULL;
64
65 if (clos->msgset->mbox)
66 {
67 rc = mu_mailbox_get_message (clos->msgset->mbox, i, &msg);
68 if (rc == MU_ERR_NOENT)
69 continue;
70 else if (rc)
71 return rc;
72 }
73 rc = clos->action (i, msg, clos->data);
74 if (rc)
75 return rc;
76 }
77 return 0;
78 }
79
80 /* Apply ACTION to each message number from MSGSET. */
81 int
82 mu_msgset_foreach_dir_message (mu_msgset_t msgset, int dir,
83 mu_msgset_message_action_t action,
84 void *data)
85 {
86 int rc;
87 struct action_closure clos;
88
89 rc = mu_msgset_aggregate (msgset);
90 if (rc)
91 return rc;
92 clos.action = action;
93 clos.data = data;
94 clos.msgset = msgset;
95 clos.dir = dir;
96 return mu_list_foreach_dir (msgset->list, dir, procrange, &clos);
97 }
98
99 int
100 mu_msgset_foreach_message (mu_msgset_t msgset,
101 mu_msgset_message_action_t action,
102 void *data)
103 {
104 return mu_msgset_foreach_dir_message (msgset, 0, action, data);
105 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <stdlib.h>
19 #include <mailutils/types.h>
20 #include <mailutils/errno.h>
21 #include <mailutils/list.h>
22 #include <mailutils/msgset.h>
23 #include <mailutils/sys/msgset.h>
24
25 struct action_closure
26 {
27 mu_msgset_msgno_action_t action;
28 void *data;
29 mu_msgset_t msgset;
30 int dir;
31 };
32
33 static int
34 procrange (void *item, void *data)
35 {
36 struct mu_msgrange *mp = item;
37 struct action_closure *clos = data;
38 size_t i;
39
40 if (clos->dir)
41 for (i = mp->msg_end; i >= mp->msg_beg; i--)
42 {
43 int rc = clos->action (i, clos->data);
44 if (rc)
45 return rc;
46 }
47 else
48 for (i = mp->msg_beg; i <= mp->msg_end; i++)
49 {
50 int rc = clos->action (i, clos->data);
51 if (rc)
52 return rc;
53 }
54 return 0;
55 }
56
57 /* Apply ACTION to each message number from MSGSET. */
58 int
59 mu_msgset_foreach_dir_msgno (mu_msgset_t msgset, int dir,
60 mu_msgset_msgno_action_t action,
61 void *data)
62 {
63 int rc;
64 struct action_closure clos;
65
66 rc = mu_msgset_aggregate (msgset);
67 if (rc)
68 return rc;
69 clos.action = action;
70 clos.data = data;
71 clos.dir = dir;
72 return mu_list_foreach_dir (msgset->list, dir, procrange, &clos);
73 }
74
75 int
76 mu_msgset_foreach_msgno (mu_msgset_t msgset,
77 mu_msgset_msgno_action_t action,
78 void *data)
79 {
80 return mu_msgset_foreach_dir_msgno (msgset, 0, action, data);
81 }
...@@ -24,7 +24,11 @@ ...@@ -24,7 +24,11 @@
24 int 24 int
25 mu_msgset_get_iterator (mu_msgset_t msgset, mu_iterator_t *pitr) 25 mu_msgset_get_iterator (mu_msgset_t msgset, mu_iterator_t *pitr)
26 { 26 {
27 int rc;
27 if (!msgset) 28 if (!msgset)
28 return EINVAL; 29 return EINVAL;
30 rc = mu_msgset_aggregate (msgset);
31 if (rc)
32 return rc;
29 return mu_list_get_iterator (msgset->list, pitr); 33 return mu_list_get_iterator (msgset->list, pitr);
30 } 34 }
......
...@@ -24,10 +24,14 @@ ...@@ -24,10 +24,14 @@
24 int 24 int
25 mu_msgset_get_list (mu_msgset_t msgset, mu_list_t *plist) 25 mu_msgset_get_list (mu_msgset_t msgset, mu_list_t *plist)
26 { 26 {
27 int rc;
27 if (!msgset) 28 if (!msgset)
28 return EINVAL; 29 return EINVAL;
29 if (!plist) 30 if (!plist)
30 return MU_ERR_OUT_PTR_NULL; 31 return MU_ERR_OUT_PTR_NULL;
32 rc = mu_msgset_aggregate (msgset);
33 if (rc)
34 return rc;
31 *plist = msgset->list; 35 *plist = msgset->list;
32 return 0; 36 return 0;
33 } 37 }
......
...@@ -26,7 +26,11 @@ int ...@@ -26,7 +26,11 @@ int
26 mu_msgset_locate (mu_msgset_t msgset, size_t n, 26 mu_msgset_locate (mu_msgset_t msgset, size_t n,
27 struct mu_msgrange const **prange) 27 struct mu_msgrange const **prange)
28 { 28 {
29 int rc;
29 if (!msgset || n == 0) 30 if (!msgset || n == 0)
30 return EINVAL; 31 return EINVAL;
32 rc = mu_msgset_aggregate (msgset);
33 if (rc)
34 return rc;
31 return mu_list_locate (msgset->list, &n, (void**)prange); 35 return mu_list_locate (msgset->list, &n, (void**)prange);
32 } 36 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <stdlib.h>
19 #include <mailutils/types.h>
20 #include <mailutils/errno.h>
21 #include <mailutils/list.h>
22 #include <mailutils/mailbox.h>
23 #include <mailutils/msgset.h>
24 #include <mailutils/sys/msgset.h>
25
26 struct invert_closure
27 {
28 mu_msgset_t nset;
29 size_t next_num;
30 };
31
32 static int
33 _invert_range (void *item, void *data)
34 {
35 struct mu_msgrange *range = item;
36 struct invert_closure *clos = data;
37 int rc;
38
39 if (clos->next_num < range->msg_beg - 1)
40 {
41 rc = mu_msgset_add_range (clos->nset, clos->next_num, range->msg_beg - 1);
42 if (rc)
43 return rc;
44 }
45 clos->next_num = range->msg_end + 1;
46 return 0;
47 }
48
49 /* Negate the message set: on return PNSET consists of the messages
50 _not contained_ in the input message set. */
51 int
52 mu_msgset_negate (mu_msgset_t msgset, mu_msgset_t *pnset)
53 {
54 int rc;
55 struct invert_closure clos;
56 size_t total;
57
58 if (!msgset)
59 return EINVAL;
60 if (!msgset->mbox)
61 return MU_ERR_NOT_OPEN;
62
63 rc = mu_msgset_aggregate (msgset);
64 if (rc)
65 return rc;
66 rc = mu_mailbox_messages_count (msgset->mbox, &total);
67 if (rc)
68 return rc;
69 rc = mu_msgset_create (&clos.nset, NULL, 0);
70 if (rc)
71 return rc;
72 clos.next_num = 1;
73 rc = mu_list_foreach (msgset->list, _invert_range, &clos);
74 if (rc == 0)
75 {
76 if (clos.next_num < total)
77 rc = mu_msgset_add_range (clos.nset, clos.next_num, total);
78 }
79
80 if (rc)
81 mu_msgset_free (clos.nset);
82 else
83 {
84 clos.nset->mbox = msgset->mbox;
85 *pnset = clos.nset;
86 }
87 return 0;
88 }
...@@ -101,14 +101,6 @@ parse_msgrange (struct parse_msgnum_env *env) ...@@ -101,14 +101,6 @@ parse_msgrange (struct parse_msgnum_env *env)
101 101
102 rc = mu_mailbox_translate (env->msgset->mbox, 102 rc = mu_mailbox_translate (env->msgset->mbox,
103 MU_MAILBOX_UID_TO_MSGNO, 103 MU_MAILBOX_UID_TO_MSGNO,
104 msgrange.msg_beg, &msgrange.msg_beg);
105 if (rc == MU_ERR_NOENT)
106 msgrange.msg_beg = env->minval;
107 else if (rc)
108 return rc;
109
110 rc = mu_mailbox_translate (env->msgset->mbox,
111 MU_MAILBOX_UID_TO_MSGNO,
112 msgrange.msg_end, &msgrange.msg_end); 104 msgrange.msg_end, &msgrange.msg_end);
113 if (rc == MU_ERR_NOENT) 105 if (rc == MU_ERR_NOENT)
114 msgrange.msg_end = env->maxval; 106 msgrange.msg_end = env->maxval;
......
...@@ -117,6 +117,13 @@ main (int argc, char **argv) ...@@ -117,6 +117,13 @@ main (int argc, char **argv)
117 MU_ASSERT (mu_msgset_sub_range (msgset, range.msg_beg, 117 MU_ASSERT (mu_msgset_sub_range (msgset, range.msg_beg,
118 range.msg_end)); 118 range.msg_end));
119 } 119 }
120 else if (strcmp (arg, "-neg") == 0)
121 {
122 mu_msgset_t negated_set;
123 MU_ASSERT (mu_msgset_negate (msgset, &negated_set));
124 mu_msgset_free (msgset);
125 msgset = negated_set;
126 }
120 else 127 else
121 { 128 {
122 mu_error ("unknown option %s", arg); 129 mu_error ("unknown option %s", arg);
......