unsigned int regetting:1;
unsigned int have_all_wanted:1;
unsigned int no_writing:1;
+ unsigned int reverse:1;
};
static char expunged_msg;
static struct sort_string_context *static_zero_cmp_context;
-static struct mail_search_sort_program *static_sort_node_cmp_context;
static void index_sort_node_add(struct sort_string_context *ctx,
struct mail_sort_node *node);
}
program->context = ctx = i_new(struct sort_string_context, 1);
+ ctx->reverse = (program->sort_program[0] & MAIL_SORT_FLAG_REVERSE) != 0;
ctx->program = program;
ctx->ext_id = mail_index_ext_register(ibox->index, name, 0,
sizeof(uint32_t),
ret = strcmp(ctx->sort_strings[n1->seq], ctx->sort_strings[n2->seq]);
if (ret != 0)
- return ret;
+ return !ctx->reverse ? ret : -ret;
return index_sort_node_cmp_type(ctx->program->temp_mail,
ctx->program->sort_program + 1,
static int sort_node_cmp(const void *p1, const void *p2)
{
- struct mail_search_sort_program *program = static_sort_node_cmp_context;
+ struct sort_string_context *ctx = static_zero_cmp_context;
const struct mail_sort_node *n1 = p1, *n2 = p2;
if (n1->sort_id < n2->sort_id)
- return -1;
+ return !ctx->reverse ? -1 : 1;
if (n1->sort_id > n2->sort_id)
- return 1;
+ return !ctx->reverse ? 1 : -1;
- return index_sort_node_cmp_type(program->temp_mail,
- program->sort_program + 1,
+ return index_sort_node_cmp_type(ctx->program->temp_mail,
+ ctx->program->sort_program + 1,
n1->seq, n2->seq);
}
nodes = array_get_modifiable(&ctx->nonzero_nodes, &count);
- static_sort_node_cmp_context = program;
+ static_zero_cmp_context = ctx;
if (array_count(&ctx->zero_nodes) == 0) {
/* fast path: we have all sort IDs */
qsort(nodes, count, sizeof(struct mail_sort_node),
for (;;) {
/* sort all messages without sort IDs */
index_sort_zeroes(ctx);
+
+ if (ctx->reverse) {
+ /* sort lists are descending currently, but
+ merging and sort ID assigning works only
+ with ascending lists. reverse the lists
+ temporarily. we can't do this while earlier
+ because secondary sort conditions must not
+ be reversed in results (but while assigning
+ sort IDs it doesn't matter). */
+ array_reverse(&ctx->nonzero_nodes);
+ array_reverse(&ctx->zero_nodes);
+ }
+
/* merge zero and non-zero arrays into sorted_nodes */
index_sort_merge(ctx);
/* give sort IDs to messages missing them */
if (index_sort_add_sort_ids(ctx) == 0)
break;
- /* broken, try again */
+ /* broken, try again with sort IDs reset */
index_sort_list_reset_broken(ctx);
}
index_sort_write_changed_sort_ids(ctx);
+ if (ctx->reverse) {
+ /* restore the correct sort order */
+ array_reverse(&ctx->sorted_nodes);
+ }
+
nodes = array_get_modifiable(&ctx->sorted_nodes, &count);
array_clear(&program->seqs);
for (i = 0; i < count; i++) {
struct sort_cmp_context {
struct mail_search_sort_program *program;
struct mail *mail;
+ bool reverse;
};
static struct sort_cmp_context static_node_cmp_context;
const struct mail_sort_node_date *n1 = p1, *n2 = p2;
if (n1->date < n2->date)
- return -1;
+ return !ctx->reverse ? -1 : 1;
if (n1->date > n2->date)
- return 1;
+ return !ctx->reverse ? 1 : -1;
return index_sort_node_cmp_type(ctx->mail,
ctx->program->sort_program + 1,
const struct mail_sort_node_size *n1 = p1, *n2 = p2;
if (n1->size < n2->size)
- return -1;
+ return !ctx->reverse ? -1 : 1;
if (n1->size > n2->size)
- return 1;
+ return !ctx->reverse ? 1 : -1;
return index_sort_node_cmp_type(ctx->mail,
ctx->program->sort_program + 1,
memset(&static_node_cmp_context, 0, sizeof(static_node_cmp_context));
static_node_cmp_context.program = program;
static_node_cmp_context.mail = program->temp_mail;
+ static_node_cmp_context.reverse =
+ (program->sort_program[0] & MAIL_SORT_FLAG_REVERSE) != 0;
program->sort_list_finish(program);
-
- if (program->reverse)
- program->iter_idx = array_count(&program->seqs);
}
bool index_sort_list_next(struct mail_search_sort_program *program,
{
const uint32_t *seqp;
- if (!program->reverse) {
- if (program->iter_idx == array_count(&program->seqs))
- return FALSE;
-
- seqp = array_idx(&program->seqs, program->iter_idx++);
- } else {
- if (program->iter_idx == 0)
- return FALSE;
+ if (program->iter_idx == array_count(&program->seqs))
+ return FALSE;
- seqp = array_idx(&program->seqs, --program->iter_idx);
- }
+ seqp = array_idx(&program->seqs, program->iter_idx++);
mail_set_seq(mail, *seqp);
return TRUE;
}
program->t = t;
program->temp_mail = mail_alloc(t, 0, NULL);
- /* primary reversion isn't stored to sort_program. we handle it by
- iterating backwards at the end. */
- program->reverse = (sort_program[0] & MAIL_SORT_FLAG_REVERSE) != 0;
- program->sort_program[0] = sort_program[0] & ~MAIL_SORT_FLAG_REVERSE;
- for (i = 1; i < MAX_SORT_PROGRAM_SIZE; i++) {
+ for (i = 0; i < MAX_SORT_PROGRAM_SIZE; i++) {
program->sort_program[i] = sort_program[i];
if (sort_program[i] == MAIL_SORT_END)
break;
seq1, seq2);
}
- /* primary reversion isn't in sort_program */
if ((*sort_program & MAIL_SORT_FLAG_REVERSE) != 0)
ret = ret < 0 ? 1 : -1;
return ret;