diff src/lib-storage/index/index-sort-string.c @ 7859:f431c67621ed HEAD

Reversing the primary sort criterion reversed also reversed secondary criterions. Fixed reverse sorting the first condition.
author Timo Sirainen <tss@iki.fi>
date Fri, 13 Jun 2008 04:39:49 +0300
parents dd899a1841d9
children d75fdd0fb8b2
line wrap: on
line diff
--- a/src/lib-storage/index/index-sort-string.c	Fri Jun 13 04:36:19 2008 +0300
+++ b/src/lib-storage/index/index-sort-string.c	Fri Jun 13 04:39:49 2008 +0300
@@ -39,11 +39,11 @@
 	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 @@
 	}
 
 	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 @@
 
 	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 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 @@
 
 	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 @@
 		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++) {