dovecot-2.2: fts: Change filter API to be able to return errors

dovecot at dovecot.org dovecot at dovecot.org
Sat May 9 08:32:19 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/95a827d97e5b
changeset: 18552:95a827d97e5b
user:      Teemu Huovila <teemu.huovila at dovecot.fi>
date:      Sat May 09 11:06:45 2015 +0300
description:
fts: Change filter API to be able to return errors

Modify fts_filter_filter() to return integer status codes. It returns
1 if a token was returned, 0 if it was filtered away and -1 on error.

diffstat:

 src/lib-fts/fts-filter-normalizer-icu.c    |  42 +++++++------
 src/lib-fts/fts-filter-normalizer-simple.c |  15 ++-
 src/lib-fts/fts-filter-private.h           |   2 +-
 src/lib-fts/fts-filter-stemmer-snowball.c  |  16 ++--
 src/lib-fts/fts-filter-stopwords.c         |  14 ++-
 src/lib-fts/fts-filter.c                   |  14 ++--
 src/lib-fts/fts-filter.h                   |   9 +-
 src/lib-fts/test-fts-filter.c              |  95 +++++++++++++++++------------
 src/plugins/fts/fts-build-mail.c           |   6 +-
 src/plugins/fts/fts-search-args.c          |   8 +-
 10 files changed, 126 insertions(+), 95 deletions(-)

diffs (truncated from 584 to 300 lines):

diff -r 7fe766887394 -r 95a827d97e5b src/lib-fts/fts-filter-normalizer-icu.c
--- a/src/lib-fts/fts-filter-normalizer-icu.c	Sat May 09 11:05:04 2015 +0300
+++ b/src/lib-fts/fts-filter-normalizer-icu.c	Sat May 09 11:06:45 2015 +0300
@@ -98,8 +98,9 @@
 	return 0;
 }
 
-static int make_utf8(const UChar *src, char **dst, const char **error_r)
+static int make_utf8(const UChar *src, const char **_dst, const char **error_r)
 {
+	char *dst;
 	char *retp = NULL;
 	int32_t dsize = 0;
 	int32_t dsize_actual = 0;
@@ -120,9 +121,9 @@
 	i_assert(NULL == retp);
 
 	dsize++; /* room for '\0' byte */
-	*dst = t_malloc(dsize);
+	dst = t_malloc(dsize);
 	err = U_ZERO_ERROR;
-	retp = u_strToUTF8WithSub(*dst, dsize, &dsize_actual, src, usrc_len,
+	retp = u_strToUTF8WithSub(dst, dsize, &dsize_actual, src, usrc_len,
 	                         UNICODE_REPLACEMENT_CHAR, &sub_num, &err);
 	if (U_FAILURE(err))
 		i_panic("Lib ICU u_strToUTF8WithSub() failed: %s",
@@ -137,8 +138,9 @@
 		                    " Substitutions (%d) were made.", sub_num);
 		return -1;
 	}
-	i_assert(retp == *dst);
+	i_assert(retp == dst);
 
+	*_dst = dst;
 	return 0;
 }
 
@@ -212,27 +214,24 @@
 	return 0;
 }
 
-/* Returns 0 on success and -1 on error. */
-/* TODO: delay errors until _deinit() and return some other values? */
-static const char *
-fts_filter_normalizer_icu_filter(struct fts_filter *filter, const char *token)
+static int
+fts_filter_normalizer_icu_filter(struct fts_filter *filter, const char **token)
 {
 	UErrorCode err = U_ZERO_ERROR;
 	UChar *utext = NULL;
 	int32_t utext_cap = 0;
 	int32_t utext_len = -1;
 	int32_t utext_limit;
-	char *normalized = NULL;
 	struct fts_filter_normalizer *np =
 		(struct fts_filter_normalizer *)filter;
 
 	/* TODO: fix error handling */
 	if (np->error != NULL)
-		return NULL;
+		goto err_exit;
 
-	if (make_uchar(token, &utext, &utext_cap) < 0) {
+	if (make_uchar(*token, &utext, &utext_cap) < 0) {
 		fts_filter_normalizer_icu_error(&np->error, "Conversion to UChar failed");
-		return NULL;
+		goto err_exit;
 	}
 	/*
 	   TODO: Some problems here.  How much longer can the result
@@ -249,8 +248,9 @@
 		   size utrans_transUChars indicated */
 		utext_len++; /* room for '\0' bytes(2) */
 		utext_cap = utext_len;
-		if (make_uchar(token, &utext, &utext_cap) < 0)
-			return NULL;
+		if (make_uchar(*token, &utext, &utext_cap) < 0) {
+			goto err_exit;
+		}
 		i_assert(utext_cap ==  utext_len);
 		utext_limit = u_strlen(utext);
 		utext_len = -1;
@@ -262,13 +262,17 @@
 
 	if (U_FAILURE(err)) {
 		icu_error(&np->error, err, "utrans_transUChars()");
-		return NULL;
+		goto err_exit;
 	}
 
-	if (make_utf8(utext, &normalized, &np->error) < 0)
-		return NULL;
+	if (make_utf8(utext, token, &np->error) < 0) {
+		goto err_exit;
+	}
 
-	return normalized;
+	return 1;
+ err_exit:
+	*token = NULL;
+	return -1;
 }
 
 #else
@@ -289,7 +293,7 @@
 	return -1;
 }
 
-static const char *
+static int
 fts_filter_normalizer_icu_filter(struct fts_filter *filter ATTR_UNUSED,
 				 const char *token ATTR_UNUSED)
 {
diff -r 7fe766887394 -r 95a827d97e5b src/lib-fts/fts-filter-normalizer-simple.c
--- a/src/lib-fts/fts-filter-normalizer-simple.c	Sat May 09 11:05:04 2015 +0300
+++ b/src/lib-fts/fts-filter-normalizer-simple.c	Sat May 09 11:06:45 2015 +0300
@@ -48,18 +48,21 @@
 	return 0;
 }
 
-static const char *
+static int
 fts_filter_normalizer_simple_filter(struct fts_filter *_filter,
-				    const char *token)
+				    const char **token)
 {
 	struct fts_filter_normalizer_simple *filter =
 		(struct fts_filter_normalizer_simple *)_filter;
 
 	str_truncate(filter->str, 0);
-	if (uni_utf8_to_decomposed_titlecase(token, strlen(token),
-					     filter->str) < 0)
-		return NULL;
-	return str_c(filter->str);
+	if (uni_utf8_to_decomposed_titlecase(*token, strlen(*token),
+	                                     filter->str) < 0) {
+		*token = NULL;
+		return -1;
+	}
+	*token = str_c(filter->str);
+	return 1;
 }
 
 static const struct fts_filter_vfuncs normalizer_filter_vfuncs = {
diff -r 7fe766887394 -r 95a827d97e5b src/lib-fts/fts-filter-private.h
--- a/src/lib-fts/fts-filter-private.h	Sat May 09 11:05:04 2015 +0300
+++ b/src/lib-fts/fts-filter-private.h	Sat May 09 11:06:45 2015 +0300
@@ -17,7 +17,7 @@
 	              const char *const *settings,
 	              struct fts_filter **filter_r,
 	              const char **error_r);
-	const char * (*filter)(struct fts_filter *filter, const char *token);
+	int (*filter)(struct fts_filter *filter, const char **token);
 	void (*destroy)(struct fts_filter *filter);
 };
 
diff -r 7fe766887394 -r 95a827d97e5b src/lib-fts/fts-filter-stemmer-snowball.c
--- a/src/lib-fts/fts-filter-stemmer-snowball.c	Sat May 09 11:05:04 2015 +0300
+++ b/src/lib-fts/fts-filter-stemmer-snowball.c	Sat May 09 11:06:45 2015 +0300
@@ -66,18 +66,20 @@
 	return 0;
 }
 
-static const char *
+static int
 fts_filter_stemmer_snowball_filter(struct fts_filter *filter,
-                                   const char *token)
+                                   const char **token)
 {
 	const sb_symbol *base;
 	int len;
 	struct fts_filter_stemmer_snowball *sp =
 		(struct fts_filter_stemmer_snowball *) filter;
 
-	base = sb_stemmer_stem(sp->stemmer, (const unsigned char *)token, strlen(token));
+	base = sb_stemmer_stem(sp->stemmer, (const unsigned char *)*token, strlen(*token));
 	len = sb_stemmer_length(sp->stemmer);
-	return t_strdup_until(base, base + len);
+	*token = t_strdup_until(base, base + len);
+
+	return *token != NULL? 1: -1;
 }
 
 #else
@@ -101,11 +103,11 @@
 {
 }
 
-static const char *
+static int
 fts_filter_stemmer_snowball_filter(struct fts_filter *filter ATTR_UNUSED,
-                                   const char *token ATTR_UNUSED)
+                                   const char **token ATTR_UNUSED)
 {
-	return NULL;
+	return -1;
 }
 
 #endif
diff -r 7fe766887394 -r 95a827d97e5b src/lib-fts/fts-filter-stopwords.c
--- a/src/lib-fts/fts-filter-stopwords.c	Sat May 09 11:05:04 2015 +0300
+++ b/src/lib-fts/fts-filter-stopwords.c	Sat May 09 11:06:45 2015 +0300
@@ -125,18 +125,20 @@
 	return ret;
 }
 
-static const char *
-fts_filter_stopwords_filter(struct fts_filter *filter, const char *token)
+static int
+fts_filter_stopwords_filter(struct fts_filter *filter, const char **token)
 {
 	const char *stopword;
 	struct fts_filter_stopwords *sp =
 		(struct fts_filter_stopwords *) filter;
 
-	stopword = hash_table_lookup(sp->stopwords, token);
-	if (stopword != NULL)
-		return NULL;
+	stopword = hash_table_lookup(sp->stopwords, *token);
+	if (stopword != NULL) {
+		*token = NULL;
+		return 0;
+	}
 	else
-		return token;
+		return 1;
 }
 
 const struct fts_filter_vfuncs stopwords_filter_vfuncs = {
diff -r 7fe766887394 -r 95a827d97e5b src/lib-fts/fts-filter.c
--- a/src/lib-fts/fts-filter.c	Sat May 09 11:05:04 2015 +0300
+++ b/src/lib-fts/fts-filter.c	Sat May 09 11:06:45 2015 +0300
@@ -92,19 +92,19 @@
 
 /* TODO: Avoid multiple allocations by using a buffer in v->filter?
  Do this non-recursively? */
-const char *
-fts_filter_filter(struct fts_filter *filter, const char *token)
+int
+fts_filter_filter(struct fts_filter *filter, const char **token)
 
 {
-	const char *filtered = NULL;
+	int ret;
 
 	if (filter->parent == NULL)
 		return filter->v->filter(filter, token);
 
-	filtered = fts_filter_filter(filter->parent, token);
+	ret = fts_filter_filter(filter->parent, token);
 
-	if(filtered != NULL)
-		return filter->v->filter(filter, filtered);
+	if(ret > 0)
+		return filter->v->filter(filter, token);
 
-	return NULL;
+	return ret;
 }
diff -r 7fe766887394 -r 95a827d97e5b src/lib-fts/fts-filter.h
--- a/src/lib-fts/fts-filter.h	Sat May 09 11:05:04 2015 +0300
+++ b/src/lib-fts/fts-filter.h	Sat May 09 11:06:45 2015 +0300
@@ -58,8 +58,11 @@
 void fts_filter_ref(struct fts_filter *filter);
 void fts_filter_unref(struct fts_filter **filter);
 
-/* Returns the filtered token or NULL, if it was completely removed */
-const char *
-fts_filter_filter(struct fts_filter *filter, const char *token);
+/* Returns 1 if token is returned in *token, 0 if token was filtered
+   out and -1 on error.
+   Input is also given via *token.
+*/
+int
+fts_filter_filter(struct fts_filter *filter, const char **token);
 
 #endif
diff -r 7fe766887394 -r 95a827d97e5b src/lib-fts/test-fts-filter.c
--- a/src/lib-fts/test-fts-filter.c	Sat May 09 11:05:04 2015 +0300
+++ b/src/lib-fts/test-fts-filter.c	Sat May 09 11:06:45 2015 +0300
@@ -24,7 +24,7 @@
 	                       "drive", NULL, NULL, NULL, "reason",
 	                       NULL, NULL, NULL,  "sing"};
 	const char **ip, **op;
-	const char *filtered;
+	const char *token;
 
 	test_begin("fts filter stopwords, English");
 	filter_class = fts_filter_find(STOPWORDS_FILTER_NAME);
@@ -34,12 +34,14 @@
 	ip = input;
 	op = output;
 	while (*ip != NULL) {
-		filtered = fts_filter_filter(filter, *ip);
-		if (filtered == NULL)
+		token = *ip;
+		ret = fts_filter_filter(filter, &token);
+		test_assert(ret >= 0);
+		if (ret == 0)
 			test_assert(*op == NULL);


More information about the dovecot-cvs mailing list