diff options
Diffstat (limited to 'src/lib-storage/mailbox-search-result.c')
-rw-r--r-- | src/lib-storage/mailbox-search-result.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/src/lib-storage/mailbox-search-result.c b/src/lib-storage/mailbox-search-result.c new file mode 100644 index 0000000..d239c72 --- /dev/null +++ b/src/lib-storage/mailbox-search-result.c @@ -0,0 +1,200 @@ +/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "mail-storage-private.h" +#include "mail-search.h" +#include "mailbox-search-result-private.h" + +static void +mailbox_search_result_analyze_args(struct mail_search_result *result, + struct mail_search_arg *arg) +{ + for (; arg != NULL; arg = arg->next) { + switch (arg->type) { + case SEARCH_OR: + case SEARCH_SUB: + mailbox_search_result_analyze_args(result, + arg->value.subargs); + break; + case SEARCH_FLAGS: + result->args_have_flags = TRUE; + break; + case SEARCH_KEYWORDS: + result->args_have_keywords = TRUE; + break; + case SEARCH_MODSEQ: + result->args_have_modseq = TRUE; + break; + default: + break; + } + } +} + +struct mail_search_result * +mailbox_search_result_alloc(struct mailbox *box, struct mail_search_args *args, + enum mailbox_search_result_flags flags) +{ + struct mail_search_result *result; + + result = i_new(struct mail_search_result, 1); + result->box = box; + result->flags = flags; + i_array_init(&result->uids, 32); + i_array_init(&result->never_uids, 128); + + if ((result->flags & MAILBOX_SEARCH_RESULT_FLAG_UPDATE) != 0) { + result->search_args = args; + mail_search_args_ref(result->search_args); + mailbox_search_result_analyze_args(result, args->args); + } + + array_push_back(&result->box->search_results, &result); + return result; +} + +void mailbox_search_result_free(struct mail_search_result **_result) +{ + struct mail_search_result *result = *_result; + struct mail_search_result *const *results; + unsigned int i, count; + + *_result = NULL; + + results = array_get(&result->box->search_results, &count); + for (i = 0; i < count; i++) { + if (results[i] == result) { + array_delete(&result->box->search_results, i, 1); + break; + } + } + i_assert(i != count); + + if (result->search_args != NULL) + mail_search_args_unref(&result->search_args); + + array_free(&result->uids); + array_free(&result->never_uids); + if (array_is_created(&result->removed_uids)) { + array_free(&result->removed_uids); + array_free(&result->added_uids); + } + i_free(result); +} + +struct mail_search_result * +mailbox_search_result_save(struct mail_search_context *ctx, + enum mailbox_search_result_flags flags) +{ + struct mail_search_result *result; + + result = mailbox_search_result_alloc(ctx->transaction->box, + ctx->args, flags); + array_push_back(&ctx->results, &result); + return result; +} + +void mailbox_search_result_initial_done(struct mail_search_result *result) +{ + if ((result->flags & MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC) != 0) { + i_array_init(&result->removed_uids, 32); + i_array_init(&result->added_uids, 32); + } + mail_search_args_seq2uid(result->search_args); +} + +void mailbox_search_results_initial_done(struct mail_search_context *ctx) +{ + struct mail_search_result *const *results; + unsigned int i, count; + + results = array_get(&ctx->results, &count); + for (i = 0; i < count; i++) + mailbox_search_result_initial_done(results[i]); +} + +void mailbox_search_result_add(struct mail_search_result *result, uint32_t uid) +{ + i_assert(uid > 0); + + if (seq_range_exists(&result->uids, uid)) + return; + + seq_range_array_add(&result->uids, uid); + if (array_is_created(&result->added_uids)) { + seq_range_array_add(&result->added_uids, uid); + seq_range_array_remove(&result->removed_uids, uid); + } +} + +void mailbox_search_result_remove(struct mail_search_result *result, + uint32_t uid) +{ + if (seq_range_array_remove(&result->uids, uid)) { + if (array_is_created(&result->removed_uids)) { + seq_range_array_add(&result->removed_uids, uid); + seq_range_array_remove(&result->added_uids, uid); + } + } +} + +void mailbox_search_results_add(struct mail_search_context *ctx, uint32_t uid) +{ + struct mail_search_result *const *results; + unsigned int i, count; + + results = array_get(&ctx->results, &count); + for (i = 0; i < count; i++) + mailbox_search_result_add(results[i], uid); +} + +void mailbox_search_results_remove(struct mailbox *box, uint32_t uid) +{ + struct mail_search_result *const *results; + unsigned int i, count; + + results = array_get(&box->search_results, &count); + for (i = 0; i < count; i++) + mailbox_search_result_remove(results[i], uid); +} + +void mailbox_search_result_never(struct mail_search_result *result, + uint32_t uid) +{ + seq_range_array_add(&result->never_uids, uid); +} + +void mailbox_search_results_never(struct mail_search_context *ctx, + uint32_t uid) +{ + struct mail_search_result *const *results; + unsigned int i, count; + + if (ctx->update_result != NULL) + mailbox_search_result_never(ctx->update_result, uid); + + results = array_get(&ctx->results, &count); + for (i = 0; i < count; i++) + mailbox_search_result_never(results[i], uid); +} + +const ARRAY_TYPE(seq_range) * +mailbox_search_result_get(struct mail_search_result *result) +{ + return &result->uids; +} + +void mailbox_search_result_sync(struct mail_search_result *result, + ARRAY_TYPE(seq_range) *removed_uids, + ARRAY_TYPE(seq_range) *added_uids) +{ + array_clear(removed_uids); + array_clear(added_uids); + + array_append_array(removed_uids, &result->removed_uids); + array_append_array(added_uids, &result->added_uids); + + array_clear(&result->removed_uids); + array_clear(&result->added_uids); +} |