summaryrefslogtreecommitdiffstats
path: root/src/lib-fts/fts-filter-contractions.c
blob: 11afbb98b52c99b322f5cfb497e4008f77a0c399 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "str.h"
#include "fts-language.h"
#include "fts-filter-private.h"
#include "fts-common.h"
#include "unichar.h"

static int
fts_filter_contractions_create(const struct fts_language *lang,
			       const char *const *settings,
			       struct fts_filter **filter_r,
			       const char **error_r)
{
	struct fts_filter *filter;

	if (settings[0] != NULL) {
		*error_r = t_strdup_printf("Unknown setting: %s", settings[0]);
		return -1;
	}
	if (strcmp(lang->name, "fr") != 0) {
		*error_r = t_strdup_printf("Unsupported language: %s", lang->name);
		return -1;
	}

	filter = i_new(struct fts_filter, 1);
	*filter = *fts_filter_contractions;
	filter->token = str_new(default_pool, 64);
	*filter_r = filter;
	return 0;
}

static int
fts_filter_contractions_filter(struct fts_filter *filter ATTR_UNUSED,
			    const char **_token,
			    const char **error_r ATTR_UNUSED)
{
	int char_size, pos = 0;
	unichar_t apostrophe;
	const char *token = *_token;

	switch (token[pos]) {
	case 'q':
		pos++;
		if (token[pos] == '\0' || token[pos] != 'u')
			break;
		/* fall through */
	case 'c':
	case 'd':
	case 'j':
	case 'l':
	case 'm':
	case 'n':
	case 's':
	case 't':
		pos++;
		if (token[pos] == '\0')
			break;
		char_size = uni_utf8_get_char(token + pos, &apostrophe);
		i_assert(char_size > 0);
		if (IS_APOSTROPHE(apostrophe)) {
			pos += char_size;
			*_token = token + pos;
		}
		if (token[pos] == '\0') /* nothing left */
			return 0;
		break;
	default:
		/* do nothing */
		break;
	}

	return 1;
}

static const struct fts_filter fts_filter_contractions_real = {
	.class_name = "contractions",
	.v = {
		fts_filter_contractions_create,
		fts_filter_contractions_filter,
		NULL
	}
};

const struct fts_filter *fts_filter_contractions = &fts_filter_contractions_real;