Coverage Report

Created: 2026-04-12 07:00

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