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;
+}
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