dovecot-2.2: lib-storage: mail_search_args_simplify() handles no...

dovecot at dovecot.org dovecot at dovecot.org
Thu Apr 23 18:02:19 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/f2756661f594
changeset: 18463:f2756661f594
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Apr 23 20:50:23 2015 +0300
description:
lib-storage: mail_search_args_simplify() handles now SEARCH_BEFORE/ON/SINCE

diffstat:

 src/lib-storage/mail-search-args-simplify.c      |  188 ++++++++++++++++++----
 src/lib-storage/test-mail-search-args-simplify.c |   20 ++-
 2 files changed, 173 insertions(+), 35 deletions(-)

diffs (275 lines):

diff -r 25974d8e5b5f -r f2756661f594 src/lib-storage/mail-search-args-simplify.c
--- a/src/lib-storage/mail-search-args-simplify.c	Thu Apr 23 20:16:54 2015 +0300
+++ b/src/lib-storage/mail-search-args-simplify.c	Thu Apr 23 20:50:23 2015 +0300
@@ -1,21 +1,71 @@
 /* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "hash.h"
 #include "mail-search.h"
 
+struct mail_search_simplify_prev_arg {
+	struct mail_search_arg mask;
+	struct mail_search_arg *prev_arg;
+};
+
 struct mail_search_simplify_ctx {
-	struct mail_search_arg *prev_flags, *prev_not_flags;
-	struct mail_search_arg *prev_seqset, *prev_not_seqset;
-	struct mail_search_arg *prev_uidset, *prev_not_uidset;
+	pool_t pool;
+	/* arg mask => prev_arg */
+	HASH_TABLE(struct mail_search_arg *,
+		   struct mail_search_simplify_prev_arg *) prev_args;
+	bool parent_and;
 	bool removals;
 };
 
+static int mail_search_arg_cmp(const struct mail_search_arg *arg1,
+			       const struct mail_search_arg *arg2)
+{
+	return memcmp(arg1, arg2, sizeof(*arg1));
+}
+
+static unsigned int mail_search_arg_hash(const struct mail_search_arg *arg)
+{
+	return mem_hash(arg, sizeof(*arg));
+}
+
+static void mail_search_arg_get_base_mask(const struct mail_search_arg *arg,
+					  struct mail_search_arg *mask_r)
+{
+	memset(mask_r, 0, sizeof(*mask_r));
+	mask_r->type = arg->type;
+	mask_r->match_not = arg->match_not;
+	mask_r->value.search_flags = arg->value.search_flags;
+}
+
+static struct mail_search_arg **
+mail_search_args_simplify_get_prev_argp(struct mail_search_simplify_ctx *ctx,
+					const struct mail_search_arg *mask)
+{
+	struct mail_search_simplify_prev_arg *prev_arg;
+
+	prev_arg = hash_table_lookup(ctx->prev_args, mask);
+	if (prev_arg == NULL) {
+		prev_arg = p_new(ctx->pool, struct mail_search_simplify_prev_arg, 1);
+		prev_arg->mask = *mask;
+		hash_table_insert(ctx->prev_args, &prev_arg->mask, prev_arg);
+	}
+	return &prev_arg->prev_arg;
+}
+
 static bool mail_search_args_merge_flags(struct mail_search_simplify_ctx *ctx,
 					 struct mail_search_arg *args)
 {
+	struct mail_search_arg mask;
 	struct mail_search_arg **prev_argp;
 
-	prev_argp = !args->match_not ? &ctx->prev_flags : &ctx->prev_not_flags;
+	if (!((!args->match_not && ctx->parent_and) ||
+	      (args->match_not && !ctx->parent_and)))
+		return FALSE;
+
+	mail_search_arg_get_base_mask(args, &mask);
+	prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
+
 	if (*prev_argp == NULL) {
 		*prev_argp = args;
 		return FALSE;
@@ -28,15 +78,16 @@
 static bool mail_search_args_merge_set(struct mail_search_simplify_ctx *ctx,
 				       struct mail_search_arg *args)
 {
+	struct mail_search_arg mask;
 	struct mail_search_arg **prev_argp;
 
-	if (args->type == SEARCH_SEQSET) {
-		prev_argp = !args->match_not ? &ctx->prev_seqset :
-			&ctx->prev_not_seqset;
-	} else {
-		prev_argp = !args->match_not ? &ctx->prev_uidset :
-			&ctx->prev_not_uidset;
-	}
+	if (!((!args->match_not && ctx->parent_and) ||
+	      (args->match_not && !ctx->parent_and)))
+		return FALSE;
+
+	mail_search_arg_get_base_mask(args, &mask);
+	prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
+
 	if (*prev_argp == NULL) {
 		*prev_argp = args;
 		return FALSE;
@@ -47,6 +98,67 @@
 	}
 }
 
+static bool mail_search_args_merge_time(struct mail_search_simplify_ctx *ctx,
+					struct mail_search_arg *args)
+{
+	struct mail_search_arg mask;
+	struct mail_search_arg **prev_argp, *prev_arg;
+
+	mail_search_arg_get_base_mask(args, &mask);
+	mask.value.date_type = args->value.date_type;
+	prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
+
+	if (*prev_argp == NULL) {
+		*prev_argp = args;
+		return FALSE;
+	}
+
+	prev_arg = *prev_argp;
+	switch (args->type) {
+	case SEARCH_BEFORE:
+		if (ctx->parent_and) {
+			if (prev_arg->value.time < args->value.time) {
+				/* prev_arg < 5 AND arg < 10 */
+			} else {
+				/* prev_arg < 10 AND arg < 5 */
+				prev_arg->value.time = args->value.time;
+			}
+		} else {
+			if (prev_arg->value.time < args->value.time) {
+				/* prev_arg < 5 OR arg < 10 */
+				prev_arg->value.time = args->value.time;
+			} else {
+				/* prev_arg < 10 OR arg < 5 */
+			}
+		}
+		return TRUE;
+	case SEARCH_ON:
+		if (prev_arg->value.time == args->value.time)
+			return TRUE;
+		return FALSE;
+	case SEARCH_SINCE:
+		if (ctx->parent_and) {
+			if (prev_arg->value.time < args->value.time) {
+				/* prev_arg >= 5 AND arg >= 10 */
+				prev_arg->value.time = args->value.time;
+			} else {
+				/* prev_arg >= 10 AND arg >= 5 */
+			}
+		} else {
+			if (prev_arg->value.time < args->value.time) {
+				/* prev_arg >= 5 OR arg >= 10 */
+			} else {
+				/* prev_arg >= 10 OR arg >= 5 */
+				prev_arg->value.time = args->value.time;
+			}
+		}
+		return TRUE;
+	default:
+		break;
+	}
+	return FALSE;
+}
+
 static bool
 mail_search_args_simplify_sub(struct mailbox *box,
 			      struct mail_search_arg *args, bool parent_and)
@@ -55,6 +167,11 @@
 	struct mail_search_arg *sub, *prev_arg = NULL;
 
 	memset(&ctx, 0, sizeof(ctx));
+	ctx.parent_and = parent_and;
+	ctx.pool = pool_alloconly_create("mail search args simplify", 1024);
+	hash_table_create(&ctx.prev_args, ctx.pool, 0, mail_search_arg_hash,
+			  mail_search_arg_cmp);
+
 	while (args != NULL) {
 		if (args->match_not && (args->type == SEARCH_SUB ||
 					args->type == SEARCH_OR)) {
@@ -92,35 +209,38 @@
 				ctx.removals = TRUE;
 		}
 
-		if ((!args->match_not && parent_and) ||
-		    (args->match_not && !parent_and)) {
-			/* try to merge arguments */
-			bool merged;
+		/* try to merge arguments */
+		bool merged;
 
-			switch (args->type) {
-			case SEARCH_FLAGS:
-				merged = mail_search_args_merge_flags(&ctx, args);
-				break;
-			case SEARCH_SEQSET:
-			case SEARCH_UIDSET:
-				merged = mail_search_args_merge_set(&ctx, args);
-				break;
-			case SEARCH_BEFORE:
-			default:
-				merged = FALSE;
-				break;
-			}
-			if (merged) {
-				prev_arg->next = args->next;
-				args = args->next;
-				ctx.removals = TRUE;
-				continue;
-			}
+		switch (args->type) {
+		case SEARCH_FLAGS:
+			merged = mail_search_args_merge_flags(&ctx, args);
+			break;
+		case SEARCH_SEQSET:
+		case SEARCH_UIDSET:
+			merged = mail_search_args_merge_set(&ctx, args);
+			break;
+		case SEARCH_BEFORE:
+		case SEARCH_ON:
+		case SEARCH_SINCE:
+			merged = mail_search_args_merge_time(&ctx, args);
+			break;
+		default:
+			merged = FALSE;
+			break;
+		}
+		if (merged) {
+			prev_arg->next = args->next;
+			args = args->next;
+			ctx.removals = TRUE;
+			continue;
 		}
 
 		prev_arg = args;
 		args = args->next;
 	}
+	hash_table_destroy(&ctx.prev_args);
+	pool_unref(&ctx.pool);
 	return ctx.removals;
 }
 
diff -r 25974d8e5b5f -r f2756661f594 src/lib-storage/test-mail-search-args-simplify.c
--- a/src/lib-storage/test-mail-search-args-simplify.c	Thu Apr 23 20:16:54 2015 +0300
+++ b/src/lib-storage/test-mail-search-args-simplify.c	Thu Apr 23 20:50:23 2015 +0300
@@ -49,7 +49,25 @@
 	{ "OR UID 1:5 OR NOT UID 10:20 NOT UID 30:40", "(OR UID 1:5 NOT UID 10:20,30:40)" },
 
 	{ "1:5 UID 10:20", "1:5 UID 10:20" },
-	{ "1:5 NOT UID 10:20", "1:5 NOT UID 10:20" }
+	{ "1:5 NOT UID 10:20", "1:5 NOT UID 10:20" },
+
+	{ "BEFORE 03-Aug-2014 BEFORE 01-Aug-2014 BEFORE 02-Aug-2014", "BEFORE \"01-Aug-2014\"" },
+	{ "OR BEFORE 01-Aug-2014 BEFORE 02-Aug-2014", "BEFORE \"02-Aug-2014\"" },
+	{ "OR BEFORE 01-Aug-2014 OR BEFORE 03-Aug-2014 BEFORE 02-Aug-2014", "BEFORE \"03-Aug-2014\"" },
+	{ "BEFORE 03-Aug-2014 NOT BEFORE 01-Aug-2014 BEFORE 02-Aug-2014", "BEFORE \"02-Aug-2014\" NOT BEFORE \"01-Aug-2014\"" },
+	{ "SENTBEFORE 03-Aug-2014 SENTBEFORE 01-Aug-2014 SENTBEFORE 02-Aug-2014", "SENTBEFORE \"01-Aug-2014\"" },
+	{ "SENTBEFORE 03-Aug-2014 BEFORE 01-Aug-2014 SENTBEFORE 02-Aug-2014", "SENTBEFORE \"02-Aug-2014\" BEFORE \"01-Aug-2014\"" },
+
+	{ "ON 03-Aug-2014 ON 03-Aug-2014", "ON \"03-Aug-2014\"" },
+	{ "ON 03-Aug-2014 ON 04-Aug-2014", "ON \"03-Aug-2014\" ON \"04-Aug-2014\"" }, /* this could be replaced with e.g. NOT ALL */
+	{ "OR ON 03-Aug-2014 ON 04-Aug-2014", "(OR ON \"03-Aug-2014\" ON \"04-Aug-2014\")" },
+
+	{ "SINCE 03-Aug-2014 SINCE 01-Aug-2014 SINCE 02-Aug-2014", "SINCE \"03-Aug-2014\"" },
+	{ "OR SINCE 01-Aug-2014 SINCE 02-Aug-2014", "SINCE \"01-Aug-2014\"" },
+	{ "OR SINCE 01-Aug-2014 OR SINCE 03-Aug-2014 SINCE 02-Aug-2014", "SINCE \"01-Aug-2014\"" },
+	{ "SINCE 03-Aug-2014 NOT SINCE 01-Aug-2014 SINCE 02-Aug-2014", "SINCE \"03-Aug-2014\" NOT SINCE \"01-Aug-2014\"" },
+	{ "SENTSINCE 03-Aug-2014 SENTSINCE 01-Aug-2014 SENTSINCE 02-Aug-2014", "SENTSINCE \"03-Aug-2014\"" },
+	{ "SENTSINCE 03-Aug-2014 SINCE 01-Aug-2014 SENTSINCE 02-Aug-2014", "SENTSINCE \"03-Aug-2014\" SINCE \"01-Aug-2014\"" },
 };
 
 static struct mail_search_args *


More information about the dovecot-cvs mailing list