Coverage Report

Created: 2026-07-16 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/lib-sieve/sieve-stringlist.c
Line
Count
Source
1
/* Copyright (c) Pigeonhole authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "array.h"
5
#include "str.h"
6
7
#include "sieve-common.h"
8
#include "sieve-stringlist.h"
9
10
/*
11
 * Default implementation
12
 */
13
14
int sieve_stringlist_read_all(struct sieve_stringlist *strlist, pool_t pool,
15
            const char *const **list_r)
16
0
{
17
0
  if (strlist->read_all == NULL) {
18
0
    ARRAY(const char *) items;
19
0
    string_t *item;
20
0
    int ret;
21
22
0
    sieve_stringlist_reset(strlist);
23
24
0
    p_array_init(&items, pool, 4);
25
26
0
    item = NULL;
27
0
    while ((ret = sieve_stringlist_next_item(strlist, &item)) > 0) {
28
0
      const char *stritem = p_strdup(pool, str_c(item));
29
30
0
      array_append(&items, &stritem, 1);
31
0
    }
32
33
0
    (void)array_append_space(&items);
34
0
    *list_r = array_idx(&items, 0);
35
36
0
    return (ret < 0 ? -1 : 1);
37
0
  }
38
39
0
  return strlist->read_all(strlist, pool, list_r);
40
0
}
41
42
int sieve_stringlist_get_length(struct sieve_stringlist *strlist)
43
0
{
44
0
  if (strlist->get_length == NULL) {
45
0
    string_t *item;
46
0
    int count = 0;
47
0
    int ret;
48
49
0
    sieve_stringlist_reset(strlist);
50
0
    while ((ret = sieve_stringlist_next_item(strlist, &item)) > 0)
51
0
      count++;
52
53
0
    sieve_stringlist_reset(strlist);
54
55
0
    return (ret < 0 ? -1 : count);
56
0
  }
57
58
0
  return strlist->get_length(strlist);
59
0
}
60
61
/*
62
 * Single Stringlist
63
 */
64
65
/* Object */
66
67
static int
68
sieve_single_stringlist_next_item(struct sieve_stringlist *_strlist,
69
          string_t **str_r);
70
static void sieve_single_stringlist_reset(struct sieve_stringlist *_strlist);
71
static int
72
sieve_single_stringlist_get_length(struct sieve_stringlist *_strlist);
73
74
struct sieve_single_stringlist {
75
  struct sieve_stringlist strlist;
76
77
  string_t *value;
78
79
  bool end:1;
80
  bool count_empty:1;
81
};
82
83
struct sieve_stringlist *
84
sieve_single_stringlist_create(const struct sieve_runtime_env *renv,
85
             string_t *str, bool count_empty)
86
0
{
87
0
  struct sieve_single_stringlist *strlist;
88
89
0
  strlist = t_new(struct sieve_single_stringlist, 1);
90
0
  strlist->strlist.runenv = renv;
91
0
  strlist->strlist.exec_status = SIEVE_EXEC_OK;
92
0
  strlist->strlist.next_item = sieve_single_stringlist_next_item;
93
0
  strlist->strlist.reset = sieve_single_stringlist_reset;
94
0
  strlist->strlist.get_length = sieve_single_stringlist_get_length;
95
0
  strlist->count_empty = count_empty;
96
0
  strlist->value = str;
97
98
0
  return &strlist->strlist;
99
0
}
100
101
struct sieve_stringlist *
102
sieve_single_stringlist_create_cstr(const struct sieve_runtime_env *renv,
103
            const char *cstr, bool count_empty)
104
0
{
105
0
  string_t *str = t_str_new_const(cstr, strlen(cstr));
106
107
0
  return sieve_single_stringlist_create(renv, str, count_empty);
108
0
}
109
110
/* Implementation */
111
112
static int
113
sieve_single_stringlist_next_item(struct sieve_stringlist *_strlist,
114
          string_t **str_r)
115
0
{
116
0
  struct sieve_single_stringlist *strlist =
117
0
    (struct sieve_single_stringlist *)_strlist;
118
119
0
  if (strlist->end) {
120
0
    *str_r = NULL;
121
0
    return 0;
122
0
  }
123
124
0
  *str_r = strlist->value;
125
0
  strlist->end = TRUE;
126
0
  return 1;
127
0
}
128
129
static void sieve_single_stringlist_reset(struct sieve_stringlist *_strlist)
130
0
{
131
0
  struct sieve_single_stringlist *strlist =
132
0
    (struct sieve_single_stringlist *)_strlist;
133
134
0
  strlist->end = FALSE;
135
0
}
136
137
static int sieve_single_stringlist_get_length(struct sieve_stringlist *_strlist)
138
0
{
139
0
  struct sieve_single_stringlist *strlist =
140
0
    (struct sieve_single_stringlist *)_strlist;
141
142
0
  return (strlist->count_empty || str_len(strlist->value) > 0 ? 1 : 0);
143
0
}
144
145
/*
146
 * Index Stringlist
147
 */
148
149
/* Object */
150
151
static int
152
sieve_index_stringlist_next_item(struct sieve_stringlist *_strlist,
153
         string_t **str_r);
154
static void sieve_index_stringlist_reset(struct sieve_stringlist *_strlist);
155
static int sieve_index_stringlist_get_length(struct sieve_stringlist *_strlist);
156
static void
157
sieve_index_stringlist_set_trace(struct sieve_stringlist *strlist, bool trace);
158
159
struct sieve_index_stringlist {
160
  struct sieve_stringlist strlist;
161
162
  struct sieve_stringlist *source;
163
164
  int index;
165
  bool end:1;
166
};
167
168
struct sieve_stringlist *
169
sieve_index_stringlist_create(const struct sieve_runtime_env *renv,
170
            struct sieve_stringlist *source, int index)
171
0
{
172
0
  struct sieve_index_stringlist *strlist;
173
174
0
  strlist = t_new(struct sieve_index_stringlist, 1);
175
0
  strlist->strlist.runenv = renv;
176
0
  strlist->strlist.exec_status = SIEVE_EXEC_OK;
177
0
  strlist->strlist.next_item = sieve_index_stringlist_next_item;
178
0
  strlist->strlist.reset = sieve_index_stringlist_reset;
179
0
  strlist->strlist.get_length = sieve_index_stringlist_get_length;
180
0
  strlist->strlist.set_trace = sieve_index_stringlist_set_trace;
181
0
  strlist->source = source;
182
0
  strlist->index = index;
183
184
0
  return &strlist->strlist;
185
0
}
186
187
/* Implementation */
188
189
static int
190
sieve_index_stringlist_next_item(struct sieve_stringlist *_strlist,
191
         string_t **str_r)
192
0
{
193
0
  struct sieve_index_stringlist *strlist =
194
0
    (struct sieve_index_stringlist *)_strlist;
195
0
  int index, ret;
196
197
0
  if (strlist->end) {
198
0
    *str_r = NULL;
199
0
    return 0;
200
0
  }
201
202
0
  if (strlist->index < 0) {
203
0
    int len = sieve_stringlist_get_length(strlist->source);
204
205
0
    if (len < 0) {
206
0
      _strlist->exec_status = strlist->source->exec_status;
207
0
      return -1;
208
0
    }
209
210
0
    if (len < -strlist->index) {
211
0
      *str_r = NULL;
212
0
      strlist->end = TRUE;
213
0
      return 0;
214
0
    }
215
0
    index = len + 1 + strlist->index;
216
0
  } else {
217
0
    index = strlist->index;
218
0
  }
219
220
0
  i_assert(index > 0);
221
0
  while (index > 0) {
222
0
    ret = sieve_stringlist_next_item(strlist->source, str_r);
223
0
    if (ret <= 0) {
224
0
      if (ret < 0) {
225
0
        _strlist->exec_status =
226
0
          strlist->source->exec_status;
227
0
      }
228
0
      return ret;
229
0
    }
230
231
0
    index--;
232
0
  }
233
234
0
  strlist->end = TRUE;
235
0
  return 1;
236
0
}
237
238
static void sieve_index_stringlist_reset(struct sieve_stringlist *_strlist)
239
0
{
240
0
  struct sieve_index_stringlist *strlist =
241
0
    (struct sieve_index_stringlist *)_strlist;
242
243
0
  sieve_stringlist_reset(strlist->source);
244
0
  strlist->end = FALSE;
245
0
}
246
247
static int sieve_index_stringlist_get_length(struct sieve_stringlist *_strlist)
248
0
{
249
0
  struct sieve_index_stringlist *strlist =
250
0
    (struct sieve_index_stringlist *)_strlist;
251
0
  int len;
252
253
0
  len = sieve_stringlist_get_length(strlist->source);
254
0
  if (len < 0) {
255
0
    _strlist->exec_status = strlist->source->exec_status;
256
0
    return -1;
257
0
  }
258
259
0
  if (strlist->index < 0) {
260
0
    if (-strlist->index >= len)
261
0
      return 0;
262
0
  } else if (strlist->index >= len) {
263
0
      return 0;
264
0
  }
265
266
0
  return 1;
267
0
}
268
269
static void
270
sieve_index_stringlist_set_trace(struct sieve_stringlist *_strlist, bool trace)
271
0
{
272
0
  struct sieve_index_stringlist *strlist =
273
0
    (struct sieve_index_stringlist *)_strlist;
274
275
0
  sieve_stringlist_set_trace(strlist->source, trace);
276
0
}