]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Reversing the primary sort criterion reversed also reversed secondary
authorTimo Sirainen <tss@iki.fi>
Fri, 13 Jun 2008 01:39:49 +0000 (04:39 +0300)
committerTimo Sirainen <tss@iki.fi>
Fri, 13 Jun 2008 01:39:49 +0000 (04:39 +0300)
criterions.
Fixed reverse sorting the first condition.

--HG--
branch : HEAD

src/lib-storage/index/index-sort-private.h
src/lib-storage/index/index-sort-string.c
src/lib-storage/index/index-sort.c

index 83e2cfb7941a428e0006135d2dff1ccf6ce23eb9..327332176d3564afd80e73d4e29302428113860f 100644 (file)
@@ -15,8 +15,6 @@ struct mail_search_sort_program {
 
        ARRAY_TYPE(uint32_t) seqs;
        unsigned int iter_idx;
-
-       unsigned int reverse:1;
 };
 
 int index_sort_header_get(struct mail *mail, uint32_t seq,
index 81b837789e4a578c38e0b7e33246e350224b21e8..dc17c83b71064becace24d354618bb73c5785f19 100644 (file)
@@ -39,11 +39,11 @@ struct sort_string_context {
        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);
@@ -72,6 +72,7 @@ void index_sort_list_init_string(struct mail_search_sort_program *program)
        }
 
        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),
@@ -219,7 +220,7 @@ static int sort_node_zero_string_cmp(const void *p1, const void *p2)
 
        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,
@@ -671,16 +672,16 @@ static void index_sort_write_changed_sort_ids(struct sort_string_context *ctx)
 
 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);
 }
 
@@ -744,7 +745,7 @@ void index_sort_list_finish_string(struct mail_search_sort_program *program)
 
        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),
@@ -770,17 +771,35 @@ void index_sort_list_finish_string(struct mail_search_sort_program *program)
                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++) {
index 7312daf402028fe921a0ff262ddc0b76705052a6..58fdf051600975375b6493b79e9faa65bf23362a 100644 (file)
@@ -26,6 +26,7 @@ ARRAY_DEFINE_TYPE(mail_sort_node_size, struct mail_sort_node_size);
 struct sort_cmp_context {
        struct mail_search_sort_program *program;
        struct mail *mail;
+       bool reverse;
 };
 
 static struct sort_cmp_context static_node_cmp_context;
@@ -87,9 +88,9 @@ static int sort_node_date_cmp(const void *p1, const void *p2)
        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,
@@ -117,9 +118,9 @@ static int sort_node_size_cmp(const void *p1, const void *p2)
        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,
@@ -146,11 +147,10 @@ void index_sort_list_finish(struct mail_search_sort_program *program)
        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,
@@ -158,17 +158,10 @@ 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;
 }
@@ -188,11 +181,7 @@ index_sort_program_init(struct mailbox_transaction_context *t,
        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;
@@ -387,7 +376,6 @@ int index_sort_node_cmp_type(struct mail *mail,
                                                seq1, seq2);
        }
 
-       /* primary reversion isn't in sort_program */
        if ((*sort_program & MAIL_SORT_FLAG_REVERSE) != 0)
                ret = ret < 0 ? 1 : -1;
        return ret;