Mercurial > dovecot > original-hg > dovecot-1.2
diff src/lib-storage/index/index-search.c @ 7619:56f55bd35aa5 HEAD
Moved IMAP messageset handling to lib-imap/ and searching to lib-storage/.
Rewrote messageset handling to use struct seq_range instead.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 14 Mar 2008 11:59:36 +0200 |
parents | 6dbd70663adf |
children | 4b8c1c164d8f |
line wrap: on
line diff
--- a/src/lib-storage/index/index-search.c Fri Mar 14 09:44:34 2008 +0200 +++ b/src/lib-storage/index/index-search.c Fri Mar 14 11:59:36 2008 +0200 @@ -89,22 +89,11 @@ } } -static int seqset_contains(struct mail_search_seqset *set, uint32_t seq) -{ - while (set != NULL) { - if (seq >= set->seq1 && seq <= set->seq2) - return TRUE; - set = set->next; - } - - return FALSE; -} - static void search_seqset_arg(struct mail_search_arg *arg, struct index_search_context *ctx) { if (arg->type == SEARCH_SEQSET) { - if (seqset_contains(arg->value.seqset, ctx->mail_ctx.seq)) + if (seq_range_exists(&arg->value.seqset, ctx->mail_ctx.seq)) ARG_SET_RESULT(arg, 1); else ARG_SET_RESULT(arg, 0); @@ -146,7 +135,7 @@ switch (arg->type) { case SEARCH_UIDSET: - return seqset_contains(arg->value.seqset, rec->uid); + return seq_range_exists(&arg->value.seqset, rec->uid); case SEARCH_FLAGS: flags = rec->flags; if ((arg->value.flags & MAIL_RECENT) != 0 && @@ -605,106 +594,57 @@ } static bool search_msgset_fix_limits(const struct mail_index_header *hdr, - struct mail_search_seqset *set, bool not) + ARRAY_TYPE(seq_range) *seqset, bool not) { - if (set == NULL) - return FALSE; - - for (; set != NULL; set = set->next) { - if (set->seq1 > hdr->messages_count) { - if (set->seq1 != (uint32_t)-1 && - set->seq2 != (uint32_t)-1) { - if (not) - continue; + struct seq_range *range; + unsigned int count; - /* completely outside our range */ - return FALSE; - } - /* either seq1 or seq2 is '*', so the last message is - in range. */ - set->seq1 = hdr->messages_count; - } - if (set->seq2 > hdr->messages_count) - set->seq2 = hdr->messages_count; - - if (set->seq1 == 0 || set->seq2 == 0) { - /* this shouldn't happen. treat as nonexisting. */ - return FALSE; - } - } - return TRUE; -} - -static int mail_search_seqset_cmp(const void *p1, const void *p2) -{ - struct mail_search_seqset *const *set1 = p1, *const *set2 = p2; - - return (*set1)->seq1 < (*set2)->seq2 ? -1 : - ((*set1)->seq1 > (*set2)->seq2 ? 1 : 0); -} + i_assert(hdr->messages_count > 0); -static struct mail_search_seqset * -search_msgset_sort(struct mail_search_seqset *set) -{ - struct mail_search_seqset **sets, *cur; - unsigned int i, count; - - for (cur = set, count = 0; cur != NULL; cur = cur->next) - count++; - - /* @UNSAFE */ - sets = i_new(struct mail_search_seqset *, count); - for (i = 0, cur = set; i < count; i++, cur = cur->next) - sets[i] = cur; - qsort(sets, count, sizeof(*sets), mail_search_seqset_cmp); - for (i = 0; i < count-1; i++) - sets[i]->next = sets[i+1]; - sets[i]->next = NULL; - set = sets[0]; - i_free(sets); - return set; -} - -static void search_msgset_compress(struct mail_search_seqset *set, - struct mail_search_seqset **last_r) -{ - struct mail_search_seqset *cur; - - for (cur = set; cur->next != NULL; ) { - if (cur->seq2 + 1 >= cur->next->seq1) { - if (cur->seq2 < cur->next->seq2) - cur->seq2 = cur->next->seq2; - cur->next = cur->next->next; - } else { - cur = cur->next; + range = array_get_modifiable(seqset, &count); + if (count > 0) { + i_assert(range[0].seq1 != 0); + if (range[count-1].seq2 == (uint32_t)-1) { + /* "*" used, make sure the last message is in the range + (e.g. with count+1:* we still want to include it) */ + seq_range_array_add(seqset, 0, hdr->messages_count); } + /* remove all non-existing messages */ + seq_range_array_remove_range(seqset, hdr->messages_count + 1, + (uint32_t)-1); } - *last_r = cur; + if (!not) + return array_count(seqset) > 0; + else { + /* if all messages are in the range, it can't match */ + range = array_get_modifiable(seqset, &count); + return range[0].seq1 == 1 && + range[count-1].seq2 == hdr->messages_count; + } } static void search_msgset_fix(const struct mail_index_header *hdr, - struct mail_search_seqset **set_p, + ARRAY_TYPE(seq_range) *seqset, uint32_t *seq1_r, uint32_t *seq2_r, bool not) { - struct mail_search_seqset *set = *set_p; - struct mail_search_seqset *last; + const struct seq_range *range; + unsigned int count; uint32_t min_seq, max_seq; - if (!search_msgset_fix_limits(hdr, set, not)) { + if (!search_msgset_fix_limits(hdr, seqset, not)) { *seq1_r = (uint32_t)-1; *seq2_r = 0; return; } - set = *set_p = search_msgset_sort(set); - search_msgset_compress(set, &last); + range = array_get(seqset, &count); if (!not) { - min_seq = set->seq1; - max_seq = last->seq2; + min_seq = range[0].seq1; + max_seq = range[count-1].seq2; } else { - min_seq = set->seq1 > 1 ? 1 : set->seq2 + 1; - max_seq = last->seq2 < hdr->messages_count ? - hdr->messages_count : last->seq1 - 1; + min_seq = range[0].seq1 > 1 ? 1 : range[0].seq2 + 1; + max_seq = range[count-1].seq2 < hdr->messages_count ? + hdr->messages_count : range[count-1].seq1 - 1; if (min_seq > max_seq) { *seq1_r = (uint32_t)-1; *seq2_r = 0;