(msgset_preproc): Expand the second part
of the message spec as well (the one after dash). (mh_msgset_parse): Fill message set with message ordinal numbers. (mh_search_message): Binary search for a message with the given sequence number. (mh_get_message): Retrieve the message with the given sequence number.
Showing
1 changed file
with
141 additions
and
6 deletions
... | @@ -136,7 +136,7 @@ static struct msgset_keyword { | ... | @@ -136,7 +136,7 @@ static struct msgset_keyword { |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static char * | 138 | static char * |
139 | msgset_preproc (mailbox_t mbox, char *arg) | 139 | msgset_preproc_part (mailbox_t mbox, char *arg, char **rest) |
140 | { | 140 | { |
141 | struct msgset_keyword *p; | 141 | struct msgset_keyword *p; |
142 | 142 | ||
... | @@ -157,12 +157,46 @@ msgset_preproc (mailbox_t mbox, char *arg) | ... | @@ -157,12 +157,46 @@ msgset_preproc (mailbox_t mbox, char *arg) |
157 | exit (1); | 157 | exit (1); |
158 | } | 158 | } |
159 | message_get_uid (msg, &uid); | 159 | message_get_uid (msg, &uid); |
160 | asprintf (&ret, "%lu%s", (unsigned long) uid, arg + strlen (p->name)); | 160 | asprintf (&ret, "%lu", (unsigned long) uid); |
161 | *rest = arg + strlen (p->name); | ||
161 | return ret; | 162 | return ret; |
162 | } | 163 | } |
164 | *rest = arg + strlen (arg); | ||
163 | return strdup (arg); | 165 | return strdup (arg); |
164 | } | 166 | } |
165 | 167 | ||
168 | static char * | ||
169 | msgset_preproc (mailbox_t mbox, char *arg) | ||
170 | { | ||
171 | char *buf, *tail; | ||
172 | |||
173 | if (strcmp (arg, "all") == 0) | ||
174 | { | ||
175 | /* Special case */ | ||
176 | arg = "first-last"; | ||
177 | } | ||
178 | |||
179 | buf = msgset_preproc_part (mbox, arg, &tail); | ||
180 | if (tail[0] == '-') | ||
181 | { | ||
182 | char *rest = msgset_preproc_part (mbox, tail+1, &tail); | ||
183 | char *p = NULL; | ||
184 | asprintf (&p, "%s-%s", buf, rest); | ||
185 | free (rest); | ||
186 | free (buf); | ||
187 | buf = p; | ||
188 | } | ||
189 | |||
190 | if (tail[0]) | ||
191 | { | ||
192 | char *p = NULL; | ||
193 | asprintf (&p, "%s%s", buf, tail); | ||
194 | free (buf); | ||
195 | buf = p; | ||
196 | } | ||
197 | return buf; | ||
198 | } | ||
199 | |||
166 | static int | 200 | static int |
167 | comp_mesg (const void *a, const void *b) | 201 | comp_mesg (const void *a, const void *b) |
168 | { | 202 | { |
... | @@ -195,13 +229,20 @@ mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv) | ... | @@ -195,13 +229,20 @@ mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv) |
195 | { | 229 | { |
196 | char *p = NULL; | 230 | char *p = NULL; |
197 | size_t start, end; | 231 | size_t start, end; |
232 | size_t msg_first, n; | ||
198 | long num; | 233 | long num; |
199 | char *arg = msgset_preproc (mbox, argv[i]); | 234 | char *arg = msgset_preproc (mbox, argv[i]); |
200 | start = strtoul (arg, &p, 0); | 235 | start = strtoul (arg, &p, 0); |
201 | switch (*p) | 236 | switch (*p) |
202 | { | 237 | { |
203 | case 0: | 238 | case 0: |
204 | msglist[msgno++] = start; | 239 | n = mh_get_message (mbox, start, NULL); |
240 | if (!n) | ||
241 | { | ||
242 | mh_error ("message %d does not exist", start); | ||
243 | exit (1); | ||
244 | } | ||
245 | msglist[msgno++] = n; | ||
205 | break; | 246 | break; |
206 | 247 | ||
207 | case '-': | 248 | case '-': |
... | @@ -215,8 +256,18 @@ mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv) | ... | @@ -215,8 +256,18 @@ mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv) |
215 | end = t; | 256 | end = t; |
216 | } | 257 | } |
217 | _expand (&msgcnt, &msglist, end - start); | 258 | _expand (&msgcnt, &msglist, end - start); |
259 | msg_first = msgno; | ||
218 | for (; start <= end; start++) | 260 | for (; start <= end; start++) |
219 | msglist[msgno++] = start; | 261 | { |
262 | n = mh_get_message (mbox, start, NULL); | ||
263 | if (n) | ||
264 | msglist[msgno++] = n; | ||
265 | } | ||
266 | if (msgno == msg_first) | ||
267 | { | ||
268 | mh_error ("no messages in range %s", argv[i]); | ||
269 | exit (1); | ||
270 | } | ||
220 | break; | 271 | break; |
221 | 272 | ||
222 | case ':': | 273 | case ':': |
... | @@ -227,12 +278,24 @@ mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv) | ... | @@ -227,12 +278,24 @@ mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv) |
227 | if (end < start) | 278 | if (end < start) |
228 | { | 279 | { |
229 | size_t t = start; | 280 | size_t t = start; |
230 | start = end; | 281 | start = end + 1; |
231 | end = t; | 282 | end = t; |
232 | } | 283 | } |
284 | else | ||
285 | end--; | ||
233 | _expand (&msgcnt, &msglist, end - start); | 286 | _expand (&msgcnt, &msglist, end - start); |
287 | msg_first = msgno; | ||
234 | for (; start <= end; start++) | 288 | for (; start <= end; start++) |
235 | msglist[msgno++] = start; | 289 | { |
290 | n = mh_get_message (mbox, start, NULL); | ||
291 | if (n) | ||
292 | msglist[msgno++] = n; | ||
293 | } | ||
294 | if (msgno == msg_first) | ||
295 | { | ||
296 | mh_error ("no messages in range %s", argv[i]); | ||
297 | exit (1); | ||
298 | } | ||
236 | break; | 299 | break; |
237 | 300 | ||
238 | default: | 301 | default: |
... | @@ -241,6 +304,8 @@ mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv) | ... | @@ -241,6 +304,8 @@ mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv) |
241 | free (arg); | 304 | free (arg); |
242 | } | 305 | } |
243 | 306 | ||
307 | msgcnt = msgno; | ||
308 | |||
244 | /* Sort the resulting message set */ | 309 | /* Sort the resulting message set */ |
245 | qsort (msglist, msgcnt, sizeof (*msglist), comp_mesg); | 310 | qsort (msglist, msgcnt, sizeof (*msglist), comp_mesg); |
246 | 311 | ||
... | @@ -265,3 +330,73 @@ mh_msgset_member (mh_msgset_t *msgset, size_t num) | ... | @@ -265,3 +330,73 @@ mh_msgset_member (mh_msgset_t *msgset, size_t num) |
265 | return i + 1; | 330 | return i + 1; |
266 | return 0; | 331 | return 0; |
267 | } | 332 | } |
333 | |||
334 | /* Auxiliary function. Performs binary search for a message with the | ||
335 | given sequence number */ | ||
336 | static size_t | ||
337 | mh_search_message (mailbox_t mbox, size_t start, size_t stop, | ||
338 | size_t seqno, message_t *mesg) | ||
339 | { | ||
340 | message_t mid_msg = NULL; | ||
341 | size_t num = 0, middle; | ||
342 | |||
343 | middle = (start + stop) / 2; | ||
344 | if (mailbox_get_message (mbox, middle, &mid_msg) | ||
345 | || mh_message_number (mid_msg, &num)) | ||
346 | return 0; | ||
347 | |||
348 | if (num == seqno) | ||
349 | { | ||
350 | if (mesg) | ||
351 | *mesg = mid_msg; | ||
352 | return middle; | ||
353 | } | ||
354 | |||
355 | if (start >= stop) | ||
356 | return 0; | ||
357 | |||
358 | if (num > seqno) | ||
359 | return mh_search_message (mbox, start, middle-1, seqno, mesg); | ||
360 | else /*if (num < seqno)*/ | ||
361 | return mh_search_message (mbox, middle+1, stop, seqno, mesg); | ||
362 | } | ||
363 | |||
364 | /* Retrieve the message with the given sequence number. | ||
365 | Returns ordinal number of the message in the mailbox if found, | ||
366 | zero otherwise. The retrieved message is stored in the location | ||
367 | pointed to by mesg, unless it is NULL. */ | ||
368 | |||
369 | size_t | ||
370 | mh_get_message (mailbox_t mbox, size_t seqno, message_t *mesg) | ||
371 | { | ||
372 | size_t num, count; | ||
373 | message_t msg; | ||
374 | |||
375 | if (mailbox_get_message (mbox, 1, &msg) | ||
376 | || mh_message_number (msg, &num)) | ||
377 | return 0; | ||
378 | if (seqno < num) | ||
379 | return 0; | ||
380 | else if (seqno == num) | ||
381 | { | ||
382 | if (mesg) | ||
383 | *mesg = msg; | ||
384 | return 1; | ||
385 | } | ||
386 | |||
387 | if (mailbox_messages_count (mbox, &count) | ||
388 | || mailbox_get_message (mbox, count, &msg) | ||
389 | || mh_message_number (msg, &num)) | ||
390 | return 0; | ||
391 | if (seqno > num) | ||
392 | return 0; | ||
393 | else if (seqno == num) | ||
394 | { | ||
395 | if (mesg) | ||
396 | *mesg = msg; | ||
397 | return count; | ||
398 | } | ||
399 | |||
400 | return mh_search_message (mbox, 1, count, seqno, mesg); | ||
401 | } | ||
402 | ... | ... |
-
Please register or sign in to post a comment