* 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.
Showing
8 changed files
with
280 additions
and
13 deletions
1 | 2008-02-04 Sergey Poznyakoff <gray@gnu.org.ua> | ||
2 | |||
3 | * NEWS: Update. | ||
4 | * examples/header.c: New command `itr'. | ||
5 | (main): Empty input repeats the recent command. | ||
6 | * include/mailutils/header.h (mu_header_get_iterator): New | ||
7 | function. | ||
8 | * libproto/include/header0.h (struct _mu_header): New member itr. | ||
9 | * mailbox/Makefile.am (libmailutils_la_SOURCES): Add hdritr.c | ||
10 | * mailbox/hdritr.c: New file. | ||
11 | * mailbox/header.c (mu_header_remove): Bugfix. Invalidate the | ||
12 | header after removal. | ||
13 | |||
1 | 2008-01-31 Sergey Poznyakoff <gray@gnu.org.ua> | 14 | 2008-01-31 Sergey Poznyakoff <gray@gnu.org.ua> |
2 | 15 | ||
3 | * auth/radius.c (_expand_query): Fix typo. | 16 | * auth/radius.c (_expand_query): Fix typo. | ... | ... |
1 | GNU mailutils NEWS -- history of user-visible changes. 2008-01-12 | 1 | GNU mailutils NEWS -- history of user-visible changes. 2008-02-04 |
2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. | 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. |
3 | See the end of file for copying conditions. | 3 | See the end of file for copying conditions. |
4 | 4 | ||
... | @@ -143,6 +143,24 @@ approach is recommended to use instead of mu_error_set_print: | ... | @@ -143,6 +143,24 @@ approach is recommended to use instead of mu_error_set_print: |
143 | mu_diag_get_debug (&debug); | 143 | mu_diag_get_debug (&debug); |
144 | mu_debug_set_print (debug, new_printer, NULL); | 144 | mu_debug_set_print (debug, new_printer, NULL); |
145 | 145 | ||
146 | ** Header iteration | ||
147 | |||
148 | New function `mu_header_get_iterator' returns an iterator for this | ||
149 | header object. Thus, the following code loops over all headers: | ||
150 | |||
151 | mu_iterator_t itr; | ||
152 | mu_header_get_iterator (header, &itr); | ||
153 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); | ||
154 | mu_iterator_next (itr)) | ||
155 | { | ||
156 | const char *hdr, *val; | ||
157 | mu_iterator_current_kv (itr, | ||
158 | (const void**)&hdr, | ||
159 | (void**)&val)); | ||
160 | /* Do something with hdr and val */ | ||
161 | } | ||
162 | mu_iterator_destroy (&itr); | ||
163 | |||
146 | ** Global debugging and verbosity settings. | 164 | ** Global debugging and verbosity settings. |
147 | 165 | ||
148 | These settings provide default values for mu_debug_t objects created | 166 | These settings provide default values for mu_debug_t objects created | ... | ... |
... | @@ -27,6 +27,7 @@ | ... | @@ -27,6 +27,7 @@ |
27 | 27 | ||
28 | char *file; | 28 | char *file; |
29 | mu_header_t header; | 29 | mu_header_t header; |
30 | mu_iterator_t iterator; | ||
30 | 31 | ||
31 | char *ps[] = { "> ", ". " }; | 32 | char *ps[] = { "> ", ". " }; |
32 | int interactive; | 33 | int interactive; |
... | @@ -132,6 +133,7 @@ cmd_free (int argc, char **argv) | ... | @@ -132,6 +133,7 @@ cmd_free (int argc, char **argv) |
132 | { | 133 | { |
133 | if (check_args (argv[0], argc, 1, 1)) | 134 | if (check_args (argv[0], argc, 1, 1)) |
134 | return; | 135 | return; |
136 | mu_iterator_destroy (&iterator); | ||
135 | mu_header_destroy (&header, NULL); | 137 | mu_header_destroy (&header, NULL); |
136 | } | 138 | } |
137 | 139 | ||
... | @@ -285,7 +287,55 @@ cmd_write (int argc, char **argv) | ... | @@ -285,7 +287,55 @@ cmd_write (int argc, char **argv) |
285 | break; | 287 | break; |
286 | } | 288 | } |
287 | } | 289 | } |
288 | 290 | ||
291 | void | ||
292 | cmd_iterate (int argc, char **argv) | ||
293 | { | ||
294 | if (check_args (argv[0], argc, 1, 2)) | ||
295 | return; | ||
296 | if (argc == 1) | ||
297 | { | ||
298 | mu_iterator_t itr; | ||
299 | MU_ASSERT (mu_header_get_iterator (header, &itr)); | ||
300 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); | ||
301 | mu_iterator_next (itr)) | ||
302 | { | ||
303 | const char *hdr, *val; | ||
304 | MU_ASSERT (mu_iterator_current_kv (itr, | ||
305 | (const void**)&hdr, | ||
306 | (void**)&val)); | ||
307 | printf ("%s: %s\n", hdr, val); | ||
308 | } | ||
309 | mu_iterator_destroy (&itr); | ||
310 | } | ||
311 | else | ||
312 | { | ||
313 | const char *hdr, *val; | ||
314 | |||
315 | if (!iterator) | ||
316 | MU_ASSERT (mu_header_get_iterator (header, &iterator)); | ||
317 | |||
318 | if (strcmp (argv[1], "first") == 0 || strcmp (argv[1], "1") == 0) | ||
319 | mu_iterator_first (iterator); | ||
320 | else if (strcmp (argv[1], "next") == 0 || strcmp (argv[1], "n") == 0) | ||
321 | { | ||
322 | mu_iterator_next (iterator); | ||
323 | if (mu_iterator_is_done (iterator)) | ||
324 | { | ||
325 | printf ("Past end of headers. Use `itr first'.\n"); | ||
326 | return; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | MU_ASSERT (mu_iterator_current_kv (iterator, | ||
331 | (const void **)&hdr, | ||
332 | (void**)&val)); | ||
333 | printf ("%s: %s\n", hdr, val); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | |||
338 | |||
289 | struct cmdtab | 339 | struct cmdtab |
290 | { | 340 | { |
291 | char *name; | 341 | char *name; |
... | @@ -303,6 +353,7 @@ static struct cmdtab cmdtab[] = { | ... | @@ -303,6 +353,7 @@ static struct cmdtab cmdtab[] = { |
303 | { "print", cmd_print, "NAME [N]", | 353 | { "print", cmd_print, "NAME [N]", |
304 | "find and print the Nth (by default, 1st) instance of header named NAME" }, | 354 | "find and print the Nth (by default, 1st) instance of header named NAME" }, |
305 | { "dump", cmd_dump, NULL, "dump all headers on screen" }, | 355 | { "dump", cmd_dump, NULL, "dump all headers on screen" }, |
356 | { "itr", cmd_iterate, "[first|1|next|n]", "iterate over headers" }, | ||
306 | { "remove", cmd_remove, "NAME [N]", | 357 | { "remove", cmd_remove, "NAME [N]", |
307 | "remove the Nth (by default, 1st) instance of header named NAME" }, | 358 | "remove the Nth (by default, 1st) instance of header named NAME" }, |
308 | { "insert", cmd_insert, "NAME VALUE [REF [NUM] [before|after] [replace]]", | 359 | { "insert", cmd_insert, "NAME VALUE [REF [NUM] [before|after] [replace]]", |
... | @@ -392,11 +443,27 @@ cmd_help (int argc, char **argv) | ... | @@ -392,11 +443,27 @@ cmd_help (int argc, char **argv) |
392 | } | 443 | } |
393 | 444 | ||
394 | int | 445 | int |
446 | docmd (int argc, char **argv) | ||
447 | { | ||
448 | struct cmdtab *cmd = find_cmd (argv[0]); | ||
449 | if (!cmd) | ||
450 | { | ||
451 | mu_error ("%u: unknown command %s", line_num, argv[0]); | ||
452 | return 1; | ||
453 | } | ||
454 | else | ||
455 | cmd->fun (argc, argv); | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | int | ||
395 | main (int argc, char **argv) | 460 | main (int argc, char **argv) |
396 | { | 461 | { |
397 | int c; | 462 | int c; |
398 | char buf[512]; | 463 | char buf[512]; |
399 | 464 | char **prevv; | |
465 | int prevc = 0; | ||
466 | |||
400 | interactive = isatty (0); | 467 | interactive = isatty (0); |
401 | while ((c = getopt (argc, argv, "f:h")) != EOF) | 468 | while ((c = getopt (argc, argv, "f:h")) != EOF) |
402 | { | 469 | { |
... | @@ -434,7 +501,6 @@ main (int argc, char **argv) | ... | @@ -434,7 +501,6 @@ main (int argc, char **argv) |
434 | { | 501 | { |
435 | int c; | 502 | int c; |
436 | char **v; | 503 | char **v; |
437 | struct cmdtab *cmd; | ||
438 | int status; | 504 | int status; |
439 | 505 | ||
440 | line_num++; | 506 | line_num++; |
... | @@ -446,17 +512,20 @@ main (int argc, char **argv) | ... | @@ -446,17 +512,20 @@ main (int argc, char **argv) |
446 | continue; | 512 | continue; |
447 | } | 513 | } |
448 | 514 | ||
449 | cmd = find_cmd (v[0]); | 515 | if (c == 0) |
450 | if (!cmd) | ||
451 | { | 516 | { |
452 | mu_error ("%u: unknown command %s", | 517 | if (prevc) |
453 | line_num, v[0]); | 518 | docmd (prevc, prevv); |
519 | else | ||
520 | mu_argcv_free (c, v); | ||
454 | } | 521 | } |
455 | else | 522 | else |
456 | cmd->fun (c, v); | 523 | { |
457 | 524 | docmd (c, v); | |
458 | mu_argcv_free (c, v); | 525 | mu_argcv_free (prevc, prevv); |
459 | 526 | prevc = c; | |
527 | prevv = v; | ||
528 | } | ||
460 | } | 529 | } |
461 | exit (0); | 530 | exit (0); |
462 | } | 531 | } | ... | ... |
... | @@ -154,6 +154,8 @@ extern int mu_header_set_stream (mu_header_t, mu_stream_t, void *); | ... | @@ -154,6 +154,8 @@ extern int mu_header_set_stream (mu_header_t, mu_stream_t, void *); |
154 | extern int mu_header_size (mu_header_t, size_t *); | 154 | extern int mu_header_size (mu_header_t, size_t *); |
155 | extern int mu_header_lines (mu_header_t, size_t *); | 155 | extern int mu_header_lines (mu_header_t, size_t *); |
156 | 156 | ||
157 | extern int mu_header_get_iterator (mu_header_t, mu_iterator_t *); | ||
158 | |||
157 | 159 | ||
158 | extern int mu_header_set_fill (mu_header_t, | 160 | extern int mu_header_set_fill (mu_header_t, |
159 | int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *), void *owner); | 161 | int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *), void *owner); | ... | ... |
... | @@ -25,6 +25,7 @@ | ... | @@ -25,6 +25,7 @@ |
25 | 25 | ||
26 | #include <mailutils/header.h> | 26 | #include <mailutils/header.h> |
27 | #include <mailutils/assoc.h> | 27 | #include <mailutils/assoc.h> |
28 | #include <mailutils/iterator.h> | ||
28 | #include <sys/types.h> | 29 | #include <sys/types.h> |
29 | 30 | ||
30 | #ifdef __cplusplus | 31 | #ifdef __cplusplus |
... | @@ -67,7 +68,10 @@ struct _mu_header | ... | @@ -67,7 +68,10 @@ struct _mu_header |
67 | /* Stream. */ | 68 | /* Stream. */ |
68 | mu_stream_t stream; | 69 | mu_stream_t stream; |
69 | size_t strpos; | 70 | size_t strpos; |
70 | 71 | ||
72 | /* Iterators */ | ||
73 | mu_iterator_t itr; | ||
74 | |||
71 | /* Methods */ | 75 | /* Methods */ |
72 | int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *); | 76 | int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *); |
73 | }; | 77 | }; | ... | ... |
mailbox/hdritr.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2008 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; if not, write to the | ||
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | Boston, MA 02110-1301 USA */ | ||
18 | |||
19 | /* Mail header iterators. */ | ||
20 | |||
21 | #ifdef HAVE_CONFIG_H | ||
22 | # include <config.h> | ||
23 | #endif | ||
24 | #include <stdlib.h> | ||
25 | #include <string.h> | ||
26 | |||
27 | #include <header0.h> | ||
28 | #include <mailutils/errno.h> | ||
29 | |||
30 | struct header_iterator | ||
31 | { | ||
32 | mu_header_t header; | ||
33 | size_t index; | ||
34 | }; | ||
35 | |||
36 | static int | ||
37 | hdr_first (void *owner) | ||
38 | { | ||
39 | struct header_iterator *itr = owner; | ||
40 | itr->index = 1; | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static int | ||
45 | hdr_next (void *owner) | ||
46 | { | ||
47 | struct header_iterator *itr = owner; | ||
48 | itr->index++; | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static int | ||
53 | hdr_getitem (void *owner, void **pret, const void **pkey) | ||
54 | { | ||
55 | struct header_iterator *itr = owner; | ||
56 | int rc; | ||
57 | size_t count; | ||
58 | |||
59 | rc = mu_header_get_field_count (itr->header, &count); | ||
60 | if (rc) | ||
61 | return rc; | ||
62 | if (itr->index > count) | ||
63 | return MU_ERR_NOENT; | ||
64 | |||
65 | rc = mu_header_sget_field_name (itr->header, itr->index, | ||
66 | (const char**) pkey); | ||
67 | if (rc == 0) | ||
68 | { | ||
69 | if (pkey) | ||
70 | rc = mu_header_sget_field_value (itr->header, itr->index, | ||
71 | (const char**) pret); | ||
72 | } | ||
73 | return rc; | ||
74 | } | ||
75 | |||
76 | static int | ||
77 | hdr_finished_p (void *owner) | ||
78 | { | ||
79 | struct header_iterator *itr = owner; | ||
80 | size_t count; | ||
81 | |||
82 | if (mu_header_get_field_count (itr->header, &count)) | ||
83 | return 1; | ||
84 | return itr->index > count; | ||
85 | } | ||
86 | |||
87 | static int | ||
88 | hdr_destroy (mu_iterator_t iterator, void *data) | ||
89 | { | ||
90 | struct header_iterator *itr = data; | ||
91 | mu_iterator_detach (&itr->header->itr, iterator); | ||
92 | free (data); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int | ||
97 | hdr_curitem_p (void *owner, void *item) | ||
98 | { | ||
99 | void *ptr; | ||
100 | |||
101 | if (hdr_getitem (owner, &ptr, NULL)) | ||
102 | return 0; | ||
103 | return ptr == item; | ||
104 | } | ||
105 | |||
106 | static int | ||
107 | hdr_data_dup (void **ptr, void *owner) | ||
108 | { | ||
109 | *ptr = malloc (sizeof (struct header_iterator)); | ||
110 | if (*ptr == NULL) | ||
111 | return ENOMEM; | ||
112 | memcpy (*ptr, owner, sizeof (struct header_iterator)); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | int | ||
117 | mu_header_get_iterator (mu_header_t hdr, mu_iterator_t *piterator) | ||
118 | { | ||
119 | mu_iterator_t iterator; | ||
120 | int status; | ||
121 | struct header_iterator *itr; | ||
122 | |||
123 | if (!hdr) | ||
124 | return EINVAL; | ||
125 | |||
126 | itr = calloc (1, sizeof *itr); | ||
127 | if (!itr) | ||
128 | return ENOMEM; | ||
129 | itr->header = hdr; | ||
130 | itr->index = 1; | ||
131 | |||
132 | status = mu_iterator_create (&iterator, itr); | ||
133 | if (status) | ||
134 | { | ||
135 | free (itr); | ||
136 | return status; | ||
137 | } | ||
138 | |||
139 | mu_iterator_set_first (iterator, hdr_first); | ||
140 | mu_iterator_set_next (iterator, hdr_next); | ||
141 | mu_iterator_set_getitem (iterator, hdr_getitem); | ||
142 | mu_iterator_set_finished_p (iterator, hdr_finished_p); | ||
143 | mu_iterator_set_curitem_p (iterator, hdr_curitem_p); | ||
144 | mu_iterator_set_destroy (iterator, hdr_destroy); | ||
145 | mu_iterator_set_dup (iterator, hdr_data_dup); | ||
146 | |||
147 | mu_iterator_attach (&hdr->itr, iterator); | ||
148 | |||
149 | *piterator = iterator; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | |||
154 | |||
155 | |||
156 | |||
157 | |||
158 | |||
159 |
... | @@ -579,6 +579,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n) | ... | @@ -579,6 +579,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n) |
579 | return MU_ERR_NOENT; | 579 | return MU_ERR_NOENT; |
580 | 580 | ||
581 | mu_hdrent_remove (header, ent); | 581 | mu_hdrent_remove (header, ent); |
582 | HEADER_SET_MODIFIED (header); | ||
582 | free (ent); | 583 | free (ent); |
583 | return 0; | 584 | return 0; |
584 | } | 585 | } | ... | ... |
-
Please register or sign in to post a comment