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/plugins/relational/mcht-count.c
Line
Count
Source
1
/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2
 */
3
4
/* Match-type ':count'
5
 */
6
7
#include "lib.h"
8
#include "str.h"
9
#include "str-sanitize.h"
10
11
#include "sieve-common.h"
12
#include "sieve-ast.h"
13
#include "sieve-stringlist.h"
14
#include "sieve-code.h"
15
#include "sieve-extensions.h"
16
#include "sieve-commands.h"
17
#include "sieve-comparators.h"
18
#include "sieve-match-types.h"
19
#include "sieve-validator.h"
20
#include "sieve-generator.h"
21
#include "sieve-interpreter.h"
22
#include "sieve-runtime-trace.h"
23
#include "sieve-match.h"
24
25
#include "ext-relational-common.h"
26
27
/*
28
 * Forward declarations
29
 */
30
31
static int
32
mcht_count_match(struct sieve_match_context *mctx,
33
     struct sieve_stringlist *value_list,
34
     struct sieve_stringlist *key_list);
35
36
/*
37
 * Match-type objects
38
 */
39
40
const struct sieve_match_type_def count_match_type = {
41
  SIEVE_OBJECT("count",
42
    &rel_match_type_operand, RELATIONAL_COUNT),
43
  .validate = mcht_relational_validate,
44
};
45
46
#define COUNT_MATCH_TYPE(name, rel_match)                           \
47
const struct sieve_match_type_def rel_match_count_ ## name = {      \
48
  SIEVE_OBJECT("count-" #name,                                \
49
         &rel_match_type_operand,                       \
50
         REL_MATCH_INDEX(RELATIONAL_COUNT, rel_match)), \
51
  .match = mcht_count_match,                                  \
52
}
53
54
COUNT_MATCH_TYPE(gt, REL_MATCH_GREATER);
55
COUNT_MATCH_TYPE(ge, REL_MATCH_GREATER_EQUAL);
56
COUNT_MATCH_TYPE(lt, REL_MATCH_LESS);
57
COUNT_MATCH_TYPE(le, REL_MATCH_LESS_EQUAL);
58
COUNT_MATCH_TYPE(eq, REL_MATCH_EQUAL);
59
COUNT_MATCH_TYPE(ne, REL_MATCH_NOT_EQUAL);
60
61
/*
62
 * Match-type implementation
63
 */
64
65
static int
66
mcht_count_match(struct sieve_match_context *mctx,
67
     struct sieve_stringlist *value_list,
68
     struct sieve_stringlist *key_list)
69
0
{
70
0
  const struct sieve_runtime_env *renv = mctx->runenv;
71
0
  bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING);
72
0
  int count;
73
0
  string_t *key_item;
74
0
  int match, ret;
75
76
0
  count = sieve_stringlist_get_length(value_list);
77
0
  if (count < 0) {
78
0
    mctx->exec_status = value_list->exec_status;
79
0
    return -1;
80
0
  }
81
82
0
  sieve_stringlist_reset(key_list);
83
84
0
  string_t *value = t_str_new(20);
85
0
  str_printfa(value, "%d", count);
86
87
0
  if (trace) {
88
0
    sieve_runtime_trace(renv, 0, "matching count value '%s'",
89
0
            str_sanitize(str_c(value), 80));
90
0
  }
91
92
0
  sieve_runtime_trace_descend(renv);
93
94
  /* Match to all key values */
95
0
  key_item = NULL;
96
0
  match = 0;
97
0
  while (match == 0 &&
98
0
         (ret = sieve_stringlist_next_item(key_list, &key_item)) > 0)
99
0
  {
100
0
    match = mcht_value_match_key(
101
0
      mctx, str_c(value), str_len(value),
102
0
      str_c(key_item), str_len(key_item));
103
104
0
    if (trace) {
105
0
      sieve_runtime_trace(renv, 0, "with key '%s' => %d",
106
0
              str_sanitize(str_c(key_item), 80),
107
0
              ret);
108
0
    }
109
0
  }
110
111
0
  sieve_runtime_trace_ascend(renv);
112
113
0
  if (ret < 0) {
114
0
    mctx->exec_status = key_list->exec_status;
115
0
    match = -1;
116
0
  }
117
0
  return match;
118
0
}