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