Coverage Report

Created: 2026-08-13 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib/array.c
Line
Count
Source
1
/* Copyright (c) Dovecot authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "array.h"
5
6
7
void *
8
array_idx_modifiable_i(const struct array *array, unsigned int idx)
9
0
{
10
0
  i_assert(idx < array->buffer->used / array->element_size);
11
0
  return PTR_OFFSET(array->buffer->data,
12
0
        MALLOC_MULTIPLY(idx, array->element_size));
13
0
}
14
15
void *array_idx_get_space_i(struct array *array, unsigned int idx)
16
0
{
17
0
  return buffer_get_space_unsafe(array->buffer,
18
0
               MALLOC_MULTIPLY(idx, array->element_size),
19
0
               array->element_size);
20
0
}
21
22
void array_idx_set_i(struct array *array, unsigned int idx, const void *data)
23
0
{
24
0
  buffer_write(array->buffer, MALLOC_MULTIPLY(idx, array->element_size),
25
0
         data, array->element_size);
26
0
}
27
28
void array_idx_clear_i(struct array *array, unsigned int idx)
29
0
{
30
0
  buffer_write_zero(array->buffer,
31
0
        MALLOC_MULTIPLY(idx, array->element_size),
32
0
        array->element_size);
33
0
}
34
35
void *array_insert_space_i(struct array *array, unsigned int idx)
36
0
{
37
0
  void *data;
38
0
  size_t pos;
39
40
0
  pos = MALLOC_MULTIPLY(idx, array->element_size);
41
0
  buffer_copy(array->buffer, MALLOC_ADD(pos, array->element_size),
42
0
        array->buffer, pos, SIZE_MAX);
43
44
0
  data = buffer_get_space_unsafe(array->buffer, pos, array->element_size);
45
0
  memset(data, 0, array->element_size);
46
0
  return data;
47
0
}
48
49
bool array_cmp_i(const struct array *array1, const struct array *array2)
50
0
{
51
0
  if (!array_is_created_i(array1) || array1->buffer->used == 0)
52
0
    return !array_is_created_i(array2) || array2->buffer->used == 0;
53
54
0
  if (!array_is_created_i(array2))
55
0
    return FALSE;
56
57
0
  return buffer_cmp(array1->buffer, array2->buffer);
58
0
}
59
60
bool array_equal_fn_i(const struct array *array1, const struct array *array2,
61
          int (*cmp)(const void *, const void*))
62
0
{
63
0
  unsigned int count1, count2, i;
64
0
  size_t size;
65
66
0
  if (!array_is_created_i(array1) || array1->buffer->used == 0)
67
0
    return !array_is_created_i(array2) || array2->buffer->used == 0;
68
69
0
  if (!array_is_created_i(array2))
70
0
    return FALSE;
71
72
0
  count1 = array_count_i(array1); count2 = array_count_i(array2);
73
0
  if (count1 != count2)
74
0
    return FALSE;
75
76
0
  size = array1->element_size;
77
0
  i_assert(size == array2->element_size);
78
79
0
  for (i = 0; i < count1; i++) {
80
0
    if (cmp(CONST_PTR_OFFSET(array1->buffer->data, i * size),
81
0
      CONST_PTR_OFFSET(array2->buffer->data, i * size)) != 0)
82
0
      return FALSE;
83
0
  }
84
0
  return TRUE;
85
0
}
86
87
bool array_equal_fn_ctx_i(const struct array *array1, const struct array *array2,
88
        int (*cmp)(const void *, const void *, const void *),
89
        const void *context)
90
0
{
91
0
  unsigned int count1, count2, i;
92
0
  size_t size;
93
94
0
  if (!array_is_created_i(array1) || array1->buffer->used == 0)
95
0
    return !array_is_created_i(array2) || array2->buffer->used == 0;
96
97
0
  if (!array_is_created_i(array2))
98
0
    return FALSE;
99
100
0
  count1 = array_count_i(array1); count2 = array_count_i(array2);
101
0
  if (count1 != count2)
102
0
    return FALSE;
103
104
0
  size = array1->element_size;
105
0
  i_assert(size == array2->element_size);
106
107
0
  for (i = 0; i < count1; i++) {
108
0
    if (cmp(CONST_PTR_OFFSET(array1->buffer->data, i * size),
109
0
      CONST_PTR_OFFSET(array2->buffer->data, i * size), context) != 0)
110
0
      return FALSE;
111
0
  }
112
0
  return TRUE;
113
0
}
114
115
void array_reverse_i(struct array *array)
116
0
{
117
0
  const size_t element_size = array->element_size;
118
0
  unsigned int i, count = array_count_i(array);
119
0
  size_t size;
120
0
  void *data, *tmp;
121
122
0
  data = buffer_get_modifiable_data(array->buffer, &size);
123
0
  tmp = t_buffer_get(array->element_size);
124
0
  for (i = 0; i+1 < count; i++, count--) {
125
0
    memcpy(tmp, PTR_OFFSET(data, i * element_size), element_size);
126
0
    memcpy(PTR_OFFSET(data, i * element_size),
127
0
           PTR_OFFSET(data, (count-1) * element_size),
128
0
           element_size);
129
0
    memcpy(PTR_OFFSET(data, (count-1) * element_size), tmp,
130
0
           element_size);
131
0
  }
132
0
}
133
134
void array_sort_i(struct array *array, int (*cmp)(const void *, const void *))
135
1.46k
{
136
1.46k
  unsigned int count;
137
138
1.46k
  count = array_count_i(array);
139
1.46k
  if (count == 0)
140
0
    return;
141
1.46k
  qsort(buffer_get_modifiable_data(array->buffer, NULL),
142
1.46k
        count, array->element_size, cmp);
143
1.46k
}
144
145
const void *array_bsearch_i(const struct array *array, const void *key,
146
                int (*cmp)(const void *, const void *))
147
0
{
148
0
  unsigned int count;
149
150
0
  count = array_count_i(array);
151
0
  return bsearch(key, array->buffer->data,
152
0
           count, array->element_size, cmp);
153
0
}
154
155
const void *array_lsearch_i(const struct array *array, const void *key,
156
          int (*cmp)(const void *, const void *))
157
0
{
158
0
  const void * const data = array->buffer->data;
159
0
  const size_t s = array->element_size;
160
0
  unsigned int idx;
161
162
0
  for (idx = 0; idx < array_count_i(array); idx++) {
163
0
    if (cmp(key, CONST_PTR_OFFSET(data, idx * s)) == 0) {
164
0
      return PTR_OFFSET(data, idx * s);
165
0
    }
166
0
  }
167
168
0
  return NULL;
169
0
}
170
171
const void *array_lsearch_ptr_i(const struct array *array, const void *key)
172
0
{
173
0
  i_assert(array->element_size == sizeof(key));
174
0
  const void *const *data = array->buffer->data;
175
0
  unsigned int i, count = array_count_i(array);
176
177
0
  for (i = 0; i < count; i++) {
178
0
    if (data[i] == key)
179
0
      return data[i];
180
0
  }
181
0
  return NULL;
182
0
}
183
184
bool array_lsearch_ptr_idx_i(const struct array *array, const void *key,
185
           unsigned int *idx_r)
186
1.46k
{
187
1.46k
  i_assert(array->element_size == sizeof(key));
188
1.46k
  const void *const *data = array->buffer->data;
189
1.46k
  unsigned int i, count = array_count_i(array);
190
191
1.46k
  for (i = 0; i < count; i++) {
192
1.46k
    if (data[i] == key) {
193
1.46k
      *idx_r = i;
194
1.46k
      return TRUE;
195
1.46k
    }
196
1.46k
  }
197
0
  return FALSE;
198
1.46k
}