maildir: If we notice an unexpectedly inserted file, retry the sync to fix it.
Without this doveadm force-resync would just ignore the inserted files.
4 /* Array is a buffer accessible using fixed size elements. As long as the
5 compiler provides typeof() function, the array provides type safety. If
6 a wrong type is tried to be added to the array, or if the array's contents
7 are tried to be used using a wrong type, the compiler will give a warning.
12 ARRAY_DEFINE(bars, struct bar);
16 i_array_init(&foo->bars, 10);
18 struct bar *bar = array_idx(&foo->bars, 5);
19 struct baz *baz = array_idx(&foo->bars, 5); // compiler warning
21 If you want to pass an array as a parameter to a function, you'll need to
22 create a type for the array using ARRAY_DEFINE_TYPE() and use the type in
23 the parameter using ARRAY_TYPE().
27 ARRAY_DEFINE_TYPE(foo, struct foo);
28 void do_foo(ARRAY_TYPE(foo) *bars) {
29 struct foo *foo = array_idx(bars, 0);
32 #include "array-decl.h"
35 #define p_array_init(array, pool, init_count) \
36 array_create(array, pool, sizeof(**(array)->v), init_count)
37 #define i_array_init(array, init_count) \
38 p_array_init(array, default_pool, init_count)
39 #define t_array_init(array, init_count) \
40 p_array_init(array, pool_datastack_create(), init_count)
43 # define ARRAY_TYPE_CAST_CONST(array) \
45 # define ARRAY_TYPE_CAST_MODIFIABLE(array) \
46 (typeof(*(array)->v_modifiable))
47 # define ARRAY_TYPE_CHECK(array, data) \
48 COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \
49 **(array)->v_modifiable, *data)
51 # define ARRAY_TYPE_CAST_CONST(array)
52 # define ARRAY_TYPE_CAST_MODIFIABLE(array)
53 # define ARRAY_TYPE_CHECK(array, data) 0
56 /* usage: struct foo *foo; array_foreach(foo_arr, foo) { .. } */
57 #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L)
58 # define array_foreach(array, elem) \
59 for (const void *elem ## __foreach_end = \
60 (const char *)(elem = *(array)->v) + (array)->arr.buffer->used; \
61 elem != elem ## __foreach_end; (elem)++)
62 # define array_foreach_modifiable(array, elem) \
63 for (const void *elem ## _end = \
64 (const char *)(elem = ARRAY_TYPE_CAST_MODIFIABLE(array) \
65 buffer_get_modifiable_data((array)->arr.buffer, NULL)) + \
66 (array)->arr.buffer->used; \
67 elem != elem ## _end; elem++)
69 # define array_foreach(array, elem) \
70 for (elem = *(array)->v; \
71 elem != CONST_PTR_OFFSET(*(array)->v, (array)->arr.buffer->used); \
73 # define array_foreach_modifiable(array, elem) \
74 for (elem = ARRAY_TYPE_CAST_MODIFIABLE(array) \
75 buffer_get_modifiable_data((array)->arr.buffer, NULL); \
76 elem != CONST_PTR_OFFSET(*(array)->v, (array)->arr.buffer->used); \
80 #define array_foreach_idx(array, elem) \
81 ((elem) - (array)->v[0])
84 array_create_from_buffer_i(struct array *array, buffer_t *buffer,
87 array->buffer = buffer;
88 array->element_size = element_size;
90 #define array_create_from_buffer(array, buffer, element_size) \
91 array_create_from_buffer_i(&(array)->arr, buffer, element_size)
94 array_create_i(struct array *array, pool_t pool,
95 size_t element_size, unsigned int init_count)
99 buffer = buffer_create_dynamic(pool, init_count * element_size);
100 array_create_from_buffer_i(array, buffer, element_size);
102 #define array_create(array, pool, element_size, init_count) \
103 array_create_i(&(array)->arr, pool, element_size, init_count)
106 array_free_i(struct array *array)
108 buffer_free(&array->buffer);
110 #define array_free(array) \
111 array_free_i(&(array)->arr)
114 array_is_created_i(const struct array *array)
116 return array->buffer != NULL;
118 #define array_is_created(array) \
119 array_is_created_i(&(array)->arr)
121 static inline pool_t ATTR_PURE
122 array_get_pool_i(struct array *array)
124 return buffer_get_pool(array->buffer);
126 #define array_get_pool(array) \
127 array_get_pool_i(&(array)->arr)
130 array_clear_i(struct array *array)
132 buffer_set_used_size(array->buffer, 0);
134 #define array_clear(array) \
135 array_clear_i(&(array)->arr)
137 static inline unsigned int ATTR_PURE
138 array_count_i(const struct array *array)
140 return array->buffer->used / array->element_size;
142 #define array_count(array) \
143 array_count_i(&(array)->arr)
146 array_append_i(struct array *array, const void *data, unsigned int count)
148 buffer_append(array->buffer, data, count * array->element_size);
151 #define array_append(array, data, count) \
152 array_append_i(&(array)->arr + ARRAY_TYPE_CHECK(array, data), \
156 array_append_array_i(struct array *dest_array, const struct array *src_array)
158 i_assert(dest_array->element_size == src_array->element_size);
159 buffer_append_buf(dest_array->buffer, src_array->buffer, 0, (size_t)-1);
161 #define array_append_array(dest_array, src_array) \
162 array_append_array_i(&(dest_array)->arr, &(src_array)->arr)
165 array_insert_i(struct array *array, unsigned int idx,
166 const void *data, unsigned int count)
168 buffer_insert(array->buffer, idx * array->element_size,
169 data, count * array->element_size);
172 #define array_insert(array, idx, data, count) \
173 array_insert_i(&(array)->arr + ARRAY_TYPE_CHECK(array, data), \
177 array_delete_i(struct array *array, unsigned int idx, unsigned int count)
179 buffer_delete(array->buffer, idx * array->element_size,
180 count * array->element_size);
182 #define array_delete(array, idx, count) \
183 array_delete_i(&(array)->arr, idx, count)
185 static inline const void *
186 array_get_i(const struct array *array, unsigned int *count_r)
188 *count_r = array_count_i(array);
189 return array->buffer->data;
191 #define array_get(array, count) \
192 ARRAY_TYPE_CAST_CONST(array)array_get_i(&(array)->arr, count)
194 static inline const void * ATTR_PURE
195 array_idx_i(const struct array *array, unsigned int idx)
197 i_assert(idx * array->element_size < array->buffer->used);
198 return CONST_PTR_OFFSET(array->buffer->data, idx * array->element_size);
200 #define array_idx(array, idx) \
201 ARRAY_TYPE_CAST_CONST(array)array_idx_i(&(array)->arr, idx)
204 array_get_modifiable_i(struct array *array, unsigned int *count_r)
206 *count_r = array_count_i(array);
207 return buffer_get_modifiable_data(array->buffer, NULL);
209 #define array_get_modifiable(array, count) \
210 ARRAY_TYPE_CAST_MODIFIABLE(array) \
211 array_get_modifiable_i(&(array)->arr, count)
213 void *array_idx_modifiable_i(struct array *array, unsigned int idx);
214 #define array_idx_modifiable(array, idx) \
215 ARRAY_TYPE_CAST_MODIFIABLE(array) \
216 array_idx_modifiable_i(&(array)->arr, idx)
218 void array_idx_set_i(struct array *array, unsigned int idx, const void *data);
219 #define array_idx_set(array, idx, data) \
220 array_idx_set_i(&(array)->arr + ARRAY_TYPE_CHECK(array, data), \
223 void array_idx_clear_i(struct array *array, unsigned int idx);
224 #define array_idx_clear(array, idx) \
225 array_idx_clear_i(&(array)->arr, idx)
228 array_append_space_i(struct array *array)
232 data = buffer_append_space_unsafe(array->buffer, array->element_size);
233 memset(data, 0, array->element_size);
236 #define array_append_space(array) \
237 ARRAY_TYPE_CAST_MODIFIABLE(array)array_append_space_i(&(array)->arr)
239 void *array_insert_space_i(struct array *array, unsigned int idx);
240 #define array_insert_space(array, idx) \
241 ARRAY_TYPE_CAST_MODIFIABLE(array) \
242 array_insert_space_i(&(array)->arr, idx)
245 array_copy(struct array *dest, unsigned int dest_idx,
246 const struct array *src, unsigned int src_idx, unsigned int count)
248 i_assert(dest->element_size == src->element_size);
250 buffer_copy(dest->buffer, dest_idx * dest->element_size,
251 src->buffer, src_idx * src->element_size,
252 count * dest->element_size);
255 bool array_cmp_i(const struct array *array1,
256 const struct array *array2) ATTR_PURE;
257 #define array_cmp(array1, array2) \
258 array_cmp_i(&(array1)->arr, &(array2)->arr)
260 void array_reverse_i(struct array *array);
261 #define array_reverse(array) \
262 array_reverse_i(&(array)->arr)
264 void array_sort_i(struct array *array, int (*cmp)(const void *, const void *));
265 #ifdef CONTEXT_TYPE_SAFETY
266 #define array_sort(array, cmp) \
267 ({(void)(1 ? 0 : cmp(ARRAY_TYPE_CAST_CONST(array)NULL, \
268 ARRAY_TYPE_CAST_CONST(array)NULL)); \
269 array_sort_i(&(array)->arr, \
270 (int (*)(const void *, const void *))cmp); })
272 #define array_sort(array, cmp) \
273 array_sort_i(&(array)->arr, (int (*)(const void *, const void *))cmp)
276 void *array_bsearch_i(struct array *array, const void *key,
277 int (*cmp)(const void *, const void *));
278 #ifdef CONTEXT_TYPE_SAFETY
279 #define array_bsearch(array, key, cmp) \
280 ARRAY_TYPE_CAST_MODIFIABLE(array) \
281 ({(void)(1 ? 0 : cmp(key, ARRAY_TYPE_CAST_CONST(array)NULL)); \
282 array_bsearch_i(&(array)->arr, (const void *)key, \
283 (int (*)(const void *, const void *))cmp); })
285 #define array_bsearch(array, key, cmp) \
286 array_bsearch_i(&(array)->arr, (const void *)key, \
287 (int (*)(const void *, const void *))cmp)