From: Timo Sirainen Date: Tue, 4 Feb 2020 15:20:15 +0000 (+0200) Subject: imap: Add imap_search_seqset_iter_*() API for batched iteration of a seqset X-Git-Tag: 2.3.10~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2ed8d08c65d8d6011e16f1dd60d5c49809b30c90;p=thirdparty%2Fdovecot%2Fcore.git imap: Add imap_search_seqset_iter_*() API for batched iteration of a seqset --- diff --git a/src/imap/imap-search-args.c b/src/imap/imap-search-args.c index 59d332b003..eb506d904a 100644 --- a/src/imap/imap-search-args.c +++ b/src/imap/imap-search-args.c @@ -224,3 +224,85 @@ void imap_search_add_changed_since(struct mail_search_args *search_args, search_arg->next = search_args->args->next; search_args->args->next = search_arg; } + +struct imap_search_seqset_iter { + struct mail_search_args *search_args; + ARRAY_TYPE(seq_range) seqset_left; + unsigned int batch_size; +}; + +static void imap_search_seqset_next_batch(struct imap_search_seqset_iter *iter) +{ + array_clear(&iter->search_args->args->value.seqset); + seq_range_array_merge_n(&iter->search_args->args->value.seqset, + &iter->seqset_left, iter->batch_size); +} + +struct imap_search_seqset_iter * +imap_search_seqset_iter_init(struct mail_search_args *search_args, + uint32_t messages_count, unsigned int batch_size) +{ + struct imap_search_seqset_iter *iter; + + i_assert(search_args->args->next == NULL); + + iter = i_new(struct imap_search_seqset_iter, 1); + iter->search_args = search_args; + iter->batch_size = batch_size; + mail_search_args_ref(iter->search_args); + + /* Assume that the search query is always a seqset or SEARCH_ALL. */ + switch (search_args->args->type) { + case SEARCH_SEQSET: + break; + case SEARCH_ALL: + if (search_args->args->match_not) { + /* $ used before search result was saved */ + return iter; + } + /* 1:* - convert to seqset */ + search_args->args->type = SEARCH_SEQSET; + p_array_init(&search_args->args->value.seqset, + search_args->pool, 1); + seq_range_array_add_range(&search_args->args->value.seqset, + 1, messages_count); + break; + default: + i_panic("Unexpected search_args type %d", + search_args->args->type); + } + + i_assert(search_args->args->type == SEARCH_SEQSET); + + i_array_init(&iter->seqset_left, + array_count(&search_args->args->value.seqset)); + array_append_array(&iter->seqset_left, &search_args->args->value.seqset); + imap_search_seqset_next_batch(iter); + return iter; +} + +void imap_search_seqset_iter_deinit(struct imap_search_seqset_iter **_iter) +{ + struct imap_search_seqset_iter *iter = *_iter; + + if (iter == NULL) + return; + + mail_search_args_unref(&iter->search_args); + array_free(&iter->seqset_left); + i_free(iter); +} + +bool imap_search_seqset_iter_next(struct imap_search_seqset_iter *iter) +{ + if (!array_is_created(&iter->seqset_left)) + return FALSE; + + /* remove the last batch of searched mails from seqset_left */ + seq_range_array_invert(&iter->search_args->args->value.seqset, + 1, UINT32_MAX); + seq_range_array_intersect(&iter->seqset_left, + &iter->search_args->args->value.seqset); + imap_search_seqset_next_batch(iter); + return array_count(&iter->search_args->args->value.seqset) > 0; +} diff --git a/src/imap/imap-search-args.h b/src/imap/imap-search-args.h index abcc87bc31..32c95c49ca 100644 --- a/src/imap/imap-search-args.h +++ b/src/imap/imap-search-args.h @@ -28,4 +28,16 @@ int imap_search_get_seqset(struct client_command_context *cmd, void imap_search_add_changed_since(struct mail_search_args *search_args, uint64_t modseq); +/* Iterate search_args in batches of messages. The search_args itself is + modified each time imap_search_seqset_iter_next() is called. Note that + search_args is expected to come from imap_search_get_anyset(), i.e. it + must contain only SEARCH_SEQSET or SEARCH_ALL arg. */ +struct imap_search_seqset_iter * +imap_search_seqset_iter_init(struct mail_search_args *search_args, + uint32_t messages_count, unsigned int batch_size); +/* Iterate the next batch. Returns TRUE if the batch was updated, FALSE if + all the batches have been iterated. */ +bool imap_search_seqset_iter_next(struct imap_search_seqset_iter *iter); +void imap_search_seqset_iter_deinit(struct imap_search_seqset_iter **iter); + #endif