/src/pigeonhole/src/lib-sieve/cmp-i-ascii-casemap.c
Line | Count | Source |
1 | | /* Copyright (c) Pigeonhole authors, see top-level COPYING file */ |
2 | | |
3 | | /* Comparator 'i;ascii-casemap': |
4 | | * |
5 | | */ |
6 | | |
7 | | #include "lib.h" |
8 | | |
9 | | #include "sieve-common.h" |
10 | | #include "sieve-comparators.h" |
11 | | |
12 | | #include <string.h> |
13 | | #include <stdio.h> |
14 | | #include <ctype.h> |
15 | | |
16 | | /* |
17 | | * Forward declarations |
18 | | */ |
19 | | |
20 | | static int |
21 | | cmp_i_ascii_casemap_compare(const struct sieve_comparator *cmp, |
22 | | const char *val1, size_t val1_size, |
23 | | const char *val2, size_t val2_size); |
24 | | static bool |
25 | | cmp_i_ascii_casemap_char_match(const struct sieve_comparator *cmp, |
26 | | const char **val1, const char *val1_end, |
27 | | const char **val2, const char *val2_end); |
28 | | |
29 | | /* |
30 | | * Comparator object |
31 | | */ |
32 | | |
33 | | const struct sieve_comparator_def i_ascii_casemap_comparator = { |
34 | | SIEVE_OBJECT("i;ascii-casemap", &comparator_operand, |
35 | | SIEVE_COMPARATOR_I_ASCII_CASEMAP), |
36 | | .flags = |
37 | | SIEVE_COMPARATOR_FLAG_ORDERING | |
38 | | SIEVE_COMPARATOR_FLAG_EQUALITY | |
39 | | SIEVE_COMPARATOR_FLAG_SUBSTRING_MATCH | |
40 | | SIEVE_COMPARATOR_FLAG_PREFIX_MATCH, |
41 | | .compare = cmp_i_ascii_casemap_compare, |
42 | | .char_match = cmp_i_ascii_casemap_char_match, |
43 | | .char_skip = sieve_comparator_octet_skip |
44 | | }; |
45 | | |
46 | | /* |
47 | | * Comparator implementation |
48 | | */ |
49 | | |
50 | | static int |
51 | | cmp_i_ascii_casemap_compare(const struct sieve_comparator *cmp ATTR_UNUSED, |
52 | | const char *val1, size_t val1_size, |
53 | | const char *val2, size_t val2_size) |
54 | 0 | { |
55 | 0 | size_t size = I_MIN(val1_size, val2_size); |
56 | 0 | int ret = strncasecmp(val1, val2, size); |
57 | |
|
58 | 0 | return (ret != 0 ? ret : (int)val1_size - (int)val2_size); |
59 | 0 | } |
60 | | |
61 | | static bool |
62 | | cmp_i_ascii_casemap_char_match(const struct sieve_comparator *cmp ATTR_UNUSED, |
63 | | const char **val, const char *val_end, |
64 | | const char **key, const char *key_end) |
65 | 0 | { |
66 | 0 | const char *val_begin = *val; |
67 | 0 | const char *key_begin = *key; |
68 | |
|
69 | 0 | while (*val < val_end && *key < key_end && |
70 | 0 | i_tolower(**val) == i_tolower(**key)) { |
71 | 0 | (*val)++; |
72 | 0 | (*key)++; |
73 | 0 | } |
74 | |
|
75 | 0 | if (*key < key_end) { |
76 | | /* Reset */ |
77 | 0 | *val = val_begin; |
78 | 0 | *key = key_begin; |
79 | |
|
80 | 0 | return FALSE; |
81 | 0 | } |
82 | 0 | return TRUE; |
83 | 0 | } |