| 48 * a stack buffer when swapped. |
48 * a stack buffer when swapped. |
| 49 */ |
49 */ |
| 50 CX_EXPORT extern const unsigned cx_array_swap_sbo_size; |
50 CX_EXPORT extern const unsigned cx_array_swap_sbo_size; |
| 51 |
51 |
| 52 /** |
52 /** |
| 53 * Declares variables for an array that can be used with the convenience macros. |
53 * Declares a typed array with size and capacity. |
| 54 * |
54 * |
| 55 * @par Examples |
55 * @param type the type of the elements |
| 56 * @code |
|
| 57 * // integer array with at most 255 elements |
|
| 58 * CX_ARRAY_DECLARE_SIZED(int, myarray, uint8_t) |
|
| 59 * |
|
| 60 * // array of MyObject* pointers where size and capacity are stored as unsigned int |
|
| 61 * CX_ARRAY_DECLARE_SIZED(MyObject*, objects, unsigned int) |
|
| 62 * |
|
| 63 * // initializing code |
|
| 64 * cx_array_initialize(myarray, 16); // reserve space for 16 |
|
| 65 * cx_array_initialize(objects, 100); // reserve space for 100 |
|
| 66 * @endcode |
|
| 67 * |
|
| 68 * @param type the type of the data |
|
| 69 * @param name the name of the array |
56 * @param name the name of the array |
| 70 * @param size_type the type of the size (should be uint8_t, uint16_t, uint32_t, or size_t) |
57 */ |
| 71 * |
58 #define CX_ARRAY(type, name) \ |
| 72 * @see cx_array_initialize() |
59 struct { \ |
| 73 * @see cx_array_simple_add() |
60 type *data; \ |
| 74 * @see cx_array_simple_copy() |
61 size_t size; \ |
| 75 * @see cx_array_simple_add_sorted() |
62 size_t capacity; \ |
| 76 * @see cx_array_simple_insert_sorted() |
63 } name |
| 77 */ |
64 |
| 78 #define CX_ARRAY_DECLARE_SIZED(type, name, size_type) \ |
65 /** |
| 79 type * name; \ |
66 * Internal structure for arrays. |
| 80 /** Array size. */ size_type name##_size; \ |
67 * |
| 81 /** Array capacity. */ size_type name##_capacity |
68 * A generalization of array structures declared with CX_ARRAY(). |
| 82 |
69 */ |
| 83 /** |
70 typedef struct cx_array_s { |
| 84 * Declares variables for an array that can be used with the convenience macros. |
71 /** The array data. */ |
| 85 * |
72 void *data; |
| 86 * The size and capacity variables will have type @c size_t. |
73 /** The number of elements. */ |
| 87 * Use #CX_ARRAY_DECLARE_SIZED() to specify a different type. |
74 size_t size; |
| 88 * |
75 /** The maximum number of elements. */ |
| 89 * @par Examples |
76 size_t capacity; |
| 90 * @code |
77 } CxArray; |
| 91 * // int array |
78 |
| 92 * CX_ARRAY_DECLARE(int, myarray) |
79 /** |
| 93 * |
80 * Initializes an array by allocating memory. |
| 94 * // initializing code |
81 * |
| 95 * cx_array_initialize(myarray, 32); // reserve space for 32 |
82 * Internal function - do not use manually. |
| 96 * @endcode |
83 * |
| 97 * |
84 * @param allocator the allocator for the array |
| 98 * @param type the type of the data |
85 * @param array a pointer to the array structure |
| 99 * @param name the name of the array |
86 * @param elem_size size of one element |
| 100 * |
87 * @param capacity the initial maximum number of elements |
| 101 * @see cx_array_initialize() |
88 * @retval zero allocation was successful |
| 102 * @see cx_array_simple_add() |
89 * @retval non-zero allocation failed |
| 103 * @see cx_array_simple_copy() |
90 */ |
| 104 * @see cx_array_simple_add_sorted() |
91 cx_attr_nonnull |
| 105 * @see cx_array_simple_insert_sorted() |
92 CX_EXPORT int cx_array_init_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity); |
| 106 */ |
93 |
| 107 #define CX_ARRAY_DECLARE(type, name) CX_ARRAY_DECLARE_SIZED(type, name, size_t) |
94 /** |
| 108 |
95 * Initializes an array by allocating memory. |
| 109 /** |
96 * |
| 110 * Initializes an array with the given capacity. |
97 * The size is set to zero. |
| 111 * |
98 * |
| 112 * The type of the capacity depends on the type used during declaration. |
99 * @attention If the array was already initialized, this will leak memory. |
| 113 * |
100 * Use cx_array_reserve() to change the capacity of an initialized array. |
| 114 * @par Examples |
101 * |
| 115 * @code |
102 * @param allocator (@c CxAllocator*) the allocator for the array |
| 116 * CX_ARRAY_DECLARE_SIZED(int, arr1, uint8_t) |
103 * @param array the name of the array |
| 117 * CX_ARRAY_DECLARE(int, arr2) // size and capacity are implicitly size_t |
104 * @param capacity (@c size_t) the initial maximum number of elements |
| 118 * |
105 * @retval zero allocation was successful |
| 119 * // initializing code |
106 * @retval non-zero allocation failed |
| 120 * cx_array_initialize(arr1, 500); // error: maximum for uint8_t is 255 |
107 */ |
| 121 * cx_array_initialize(arr2, 500); // OK |
108 #define cx_array_init_a(allocator, array, capacity) cx_array_init_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity) |
| 122 * @endcode |
109 |
| 123 * |
110 /** |
| 124 * |
111 * Initializes an array by allocating memory. |
| 125 * The memory for the array is allocated with the cxDefaultAllocator. |
112 * |
| 126 * |
113 * The size is set to zero. |
| 127 * @param array the name of the array |
114 * |
| 128 * @param capacity the initial capacity |
115 * @attention If the array was already initialized, this will leak memory. |
| 129 * @see cx_array_initialize_a() |
116 * |
| 130 * @see CX_ARRAY_DECLARE_SIZED() |
117 * @param array the name of the array |
| 131 * @see CX_ARRAY_DECLARE() |
118 * @param capacity (@c size_t) the initial maximum number of elements |
| 132 */ |
119 * @retval zero allocation was successful |
| 133 #define cx_array_initialize(array, capacity) \ |
120 * @retval non-zero allocation failed |
| 134 array##_capacity = capacity; \ |
121 */ |
| 135 array##_size = 0; \ |
122 #define cx_array_init(array, capacity) cx_array_init_a(cxDefaultAllocator, array, capacity) |
| 136 array = cxMallocDefault(sizeof(array[0]) * capacity) |
123 |
| 137 |
124 /** |
| 138 /** |
125 * Initializes an array with fixed size memory. |
| 139 * Initializes an array with the given capacity using the specified allocator. |
126 * |
| 140 * |
127 * Internal function - do not use manually. |
| 141 * @par Example |
128 * |
| 142 * @code |
129 * @param array a pointer to the array structure |
| 143 * CX_ARRAY_DECLARE(int, myarray) |
130 * @param data the fixed size array |
| 144 * |
131 * @param capacity the capacity of the fixed size array |
| 145 * |
132 * @param size the number of initialized elements in the fixed size array |
| 146 * const CxAllocator *al = // ... |
133 */ |
| 147 * cx_array_initialize_a(al, myarray, 128); |
134 cx_attr_nonnull |
| 148 * // ... |
135 CX_EXPORT void cx_array_init_fixed_(CxArray *array, const void *data, size_t capacity, size_t size); |
| 149 * cxFree(al, myarray); // remember to free with the same allocator |
136 |
| 150 * @endcode |
137 /** |
| 151 * |
138 * Initializes an array with fixed size memory. |
| 152 * @param allocator (@c CxAllocator*) the allocator |
139 * |
| 153 * @param array the name of the array |
140 * This is useful, for example, when you want to work with memory on the stack |
| 154 * @param capacity the initial capacity |
141 * and only want to move to the heap when the stack memory is not enough. |
| 155 * @see cx_array_initialize() |
142 * |
| 156 * @see CX_ARRAY_DECLARE_SIZED() |
143 * With the @p num_initialized argument you can specify how many elements in the |
| 157 * @see CX_ARRAY_DECLARE() |
144 * fixed size array are already correctly initialized, which determines the |
| 158 */ |
145 * initial size of the array. |
| 159 #define cx_array_initialize_a(allocator, array, capacity) \ |
146 * |
| 160 array##_capacity = capacity; \ |
147 * The capacity is determined automatically by the compiler. |
| 161 array##_size = 0; \ |
148 * |
| 162 array = cxMalloc(allocator, sizeof(array[0]) * capacity) |
149 * @attention When you add elements to an array that was initialized with fixed |
| 163 |
150 * size memory, you MUST check the capacity before adding the element and invoke |
| 164 /** |
151 * cx_array_copy_to_new() when you intend to exceed the capacity. |
| 165 * Defines a reallocation mechanism for arrays. |
152 * |
| 166 * You can create your own, use cx_array_reallocator(), or |
153 * @attention When you pass a pointer to an array that does not have a fixed |
| 167 * use the #cx_array_default_reallocator. |
154 * size, the behavior is unspecified. |
| 168 */ |
155 * |
| 169 struct cx_array_reallocator_s { |
156 * @param array the name of the array to initialize |
| 170 /** |
157 * @param fixed_size_array (@c void*) the fixed size array |
| 171 * Reallocates space for the given array. |
158 * @param num_initialized (@c size_t) the number of already initialized elements in the fixed size array |
| 172 * |
159 * @see cx_array_copy_to_new() |
| 173 * Implementations are not required to free the original array. |
160 */ |
| 174 * This allows reallocation of static or stack memory by allocating heap memory |
161 #define cx_array_init_fixed(array, fixed_size_array, num_initialized) \ |
| 175 * and copying the array contents; namely when @c stack_ptr in this struct |
162 cx_array_init_fixed_((CxArray*)&(array), fixed_size_array, cx_nmemb(fixed_size_array), num_initialized) |
| 176 * is not @c NULL and @p array equals @c stack_ptr. |
163 |
| 177 * |
164 /** |
| 178 * @param array the array to reallocate |
165 * Changes the capacity of an array. |
| 179 * @param old_capacity the old number of elements |
166 * |
| 180 * @param new_capacity the new number of elements |
167 * Internal function - do not use. |
| 181 * @param elem_size the size of each element |
168 * |
| 182 * @param alloc a reference to this allocator |
169 * @param allocator the allocator |
| 183 * @return a pointer to the reallocated memory or @c NULL on failure |
170 * @param array a pointer to the array structure |
| 184 */ |
171 * @param elem_size the size of one element |
| 185 void *(*realloc)( void *array, size_t old_capacity, size_t new_capacity, |
172 * @param capacity the new capacity |
| 186 size_t elem_size, struct cx_array_reallocator_s *alloc); |
173 * @retval zero allocation was successful |
| 187 |
174 * @retval non-zero allocation failed |
| 188 /** |
175 */ |
| 189 * The allocator that shall be used for the reallocations. |
176 cx_attr_nonnull |
| 190 */ |
177 CX_EXPORT int cx_array_reserve_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity); |
| 191 const CxAllocator *allocator; |
178 |
| 192 /** |
179 /** |
| 193 * Optional pointer to stack memory |
180 * Changes the capacity of an array. |
| 194 * if the array is originally located on the stack. |
181 * |
| 195 */ |
182 * If required, the size is reduced to fit into the new capacity. |
| 196 const void *stack_ptr; |
183 * |
| 197 }; |
184 * @param allocator (@c CxAllocator*) the allocator for the array |
| 198 |
185 * @param array the name of the array |
| 199 /** |
186 * @param capacity (@c size_t) the new maximum number of elements |
| 200 * Typedef for the array reallocator struct. |
187 * @retval zero allocation was successful |
| 201 */ |
188 * @retval non-zero allocation failed |
| 202 typedef struct cx_array_reallocator_s CxArrayReallocator; |
189 */ |
| 203 |
190 #define cx_array_reserve_a(allocator, array, capacity) \ |
| 204 /** |
191 cx_array_reserve_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity) |
| 205 * A default array reallocator that is based on the cxDefaultAllocator. |
192 |
| 206 */ |
193 /** |
| 207 CX_EXPORT extern CxArrayReallocator *cx_array_default_reallocator; |
194 * Changes the capacity of an array. |
| 208 |
195 * |
| 209 /** |
196 * If required, the size is reduced to fit into the new capacity. |
| 210 * Creates a new array reallocator. |
197 * |
| 211 * |
198 * @param array the name of the array |
| 212 * When @p allocator is @c NULL, the cxDefaultAllocator will be used. |
199 * @param capacity (@c size_t) the new maximum number of elements |
| 213 * |
200 * @retval zero allocation was successful |
| 214 * When @p stack_ptr is not @c NULL, the reallocator is supposed to be used |
201 * @retval non-zero allocation failed |
| 215 * @em only for the specific array initially located at @p stack_ptr. |
202 */ |
| 216 * When reallocation is needed, the reallocator checks if the array is |
203 #define cx_array_reserve(array, capacity) \ |
| 217 * still located at @p stack_ptr and copies the contents to the heap. |
204 cx_array_reserve_a(cxDefaultAllocator, array, capacity) |
| 218 * |
205 |
| 219 * @note Invoking this function with both arguments being @c NULL will return a |
206 /** |
| 220 * reallocator that behaves like #cx_array_default_reallocator. |
207 * Copies the array to a new memory region. |
| 221 * |
208 * |
| 222 * @param allocator the allocator this reallocator shall be based on |
209 * Internal function - do not use. |
| 223 * @param stack_ptr the address of the array when the array is initially located |
210 * |
| 224 * on the stack or shall not reallocate in place |
211 * @param allocator the allocator for new new memory |
| 225 * @return an array reallocator |
212 * @param array a pointer to the array structure |
| 226 */ |
213 * @param elem_size the size of one element |
| 227 CX_EXPORT CxArrayReallocator cx_array_reallocator( |
214 * @param capacity the new capacity |
| 228 const struct cx_allocator_s *allocator, const void *stack_ptr); |
215 * @retval zero allocation was successful |
| 229 |
216 * @retval non-zero allocation failed |
| 230 /** |
217 */ |
| 231 * Reserves memory for additional elements. |
218 cx_attr_nonnull |
| 232 * |
219 CX_EXPORT int cx_array_copy_to_new_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity); |
| 233 * This function checks if the @p capacity of the array is sufficient to hold |
220 |
| 234 * at least @p size plus @p elem_count elements. If not, a reallocation is |
221 /** |
| 235 * performed with the specified @p reallocator. |
222 * Copies the array to a new memory region. |
| 236 * You can create your own reallocator by hand, use #cx_array_default_reallocator, |
223 * |
| 237 * or use the convenience function cx_array_reallocator() to create a custom reallocator. |
224 * This is useful when you have initialized the array with a fixed size memory |
| 238 * |
225 * using cx_array_init_fixed(), and now you want to increase the capacity. |
| 239 * This function can be useful to replace subsequent calls to cx_array_copy() |
226 * |
| 240 * with one single cx_array_reserve() and then - after guaranteeing a |
227 * @attention When the original memory does not belong to stack memory, and |
| 241 * sufficient capacity - use simple memmove() or memcpy(). |
228 * you do not have another reference to this memory, it will leak. |
| 242 * |
229 * |
| 243 * The @p width in bytes refers to the size and capacity. |
230 * @param allocator (@c CxAllocator*) the allocator for the new memory |
| 244 * Both must have the same width. |
231 * @param array the name of the array |
| 245 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit |
232 * @param capacity (@c size_t) the new maximum number of elements |
| 246 * architecture. If set to zero, the native word width is used. |
233 * @retval zero allocation was successful |
| 247 * |
234 * @retval non-zero allocation failed |
| 248 * @note This function will reserve the minimum required capacity to hold |
235 * @see cx_array_init_fixed() |
| 249 * the additional elements and does not perform an overallocation. |
236 */ |
| 250 * |
237 #define cx_array_copy_to_new_a(allocator, array, capacity) \ |
| 251 * @param array a pointer to the target array |
238 cx_array_copy_to_new_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity) |
| 252 * @param size a pointer to the size of the array |
239 |
| 253 * @param capacity a pointer to the capacity of the array |
240 /** |
| 254 * @param width the width in bytes for the @p size and @p capacity or zero for default |
241 * Copies the array to a new memory region. |
| 255 * @param elem_size the size of one element |
242 * |
| 256 * @param elem_count the number of expected additional elements |
243 * This is useful when you have initialized the array with a fixed size memory |
| 257 * @param reallocator the array reallocator to use |
244 * using cx_array_init_fixed(), and now you want to increase the capacity. |
| 258 * (@c NULL defaults to #cx_array_default_reallocator) |
245 * |
| 259 * @retval zero success |
246 * @attention When the original memory does not belong to stack memory, and |
| 260 * @retval non-zero failure |
247 * you do not have another reference to this memory, it will leak. |
| 261 * @see cx_array_reallocator() |
248 * |
| 262 */ |
249 * @param array the name of the array |
| 263 cx_attr_nonnull_arg(1, 2, 3) |
250 * @param capacity (@c size_t) the new maximum number of elements |
| 264 CX_EXPORT int cx_array_reserve(void **array, void *size, void *capacity, |
251 * @retval zero allocation was successful |
| 265 unsigned width, size_t elem_size, size_t elem_count, |
252 * @retval non-zero allocation failed |
| 266 CxArrayReallocator *reallocator); |
253 * @see cx_array_init_fixed() |
| 267 |
254 */ |
| 268 /** |
255 #define cx_array_copy_to_new(array, capacity) \ |
| 269 * Copies elements from one array to another. |
256 cx_array_copy_to_new_a(cxDefaultAllocator, array, capacity) |
| 270 * |
257 |
| 271 * The elements are copied to the @p target array at the specified @p index, |
258 /** |
| 272 * overwriting possible elements. The @p index does not need to be in range of |
259 * Inserts data into an array. |
| 273 * the current array @p size. If the new index plus the number of elements added |
260 * |
| 274 * extends the array's size, the remaining @p capacity is used. |
261 * Internal function - do not use. |
| 275 * |
262 * |
| 276 * If the @p capacity is also insufficient to hold the new data, a reallocation |
263 * @param allocator the allocator to use for a possible reallocation |
| 277 * attempt is made with the specified @p reallocator. |
264 * @param array a pointer to the array structure |
| 278 * You can create your own reallocator by hand, use #cx_array_default_reallocator, |
265 * @param elem_size the size of one element |
| 279 * or use the convenience function cx_array_reallocator() to create a custom reallocator. |
266 * @param index the index where to insert the @p other data |
| 280 * |
267 * @param other a pointer to an array of data that shall be inserted |
| 281 * The @p width in bytes refers to the size and capacity. |
268 * @param n the number of elements that shall be inserted |
| 282 * Both must have the same width. |
269 * @retval zero success |
| 283 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit |
270 * @retval non-zero a re-allocation was necessary but failed |
| 284 * architecture. If set to zero, the native word width is used. |
271 */ |
| 285 * |
272 cx_attr_nonnull_arg(1, 2) |
| 286 * @note When this function does reallocate the array, it may allocate more |
273 CX_EXPORT int cx_array_insert_(const CxAllocator *allocator, CxArray *array, |
| 287 * space than required to avoid further allocations in the near future. |
274 size_t elem_size, size_t index, const void *other, size_t n); |
| 288 * |
275 |
| 289 * @param target a pointer to the target array |
276 /** |
| 290 * @param size a pointer to the size of the target array |
277 * Appends an element to an array. |
| 291 * @param capacity a pointer to the capacity of the target array |
278 * |
| 292 * @param width the width in bytes for the @p size and @p capacity or zero for default |
279 * When the capacity is not enough to hold the new element, a re-allocation is attempted. |
| 293 * @param index the index where the copied elements shall be placed |
280 * |
| 294 * @param src the source array |
281 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation |
| 295 * @param elem_size the size of one element |
282 * @param array the name of the array where the element shall be added |
| 296 * @param elem_count the number of elements to copy |
283 * @param element (@c void*) a pointer to the element that shall be added |
| 297 * @param reallocator the array reallocator to use |
284 * @retval zero success |
| 298 * (@c NULL defaults to #cx_array_default_reallocator) |
285 * @retval non-zero a re-allocation was necessary but failed |
| 299 * @retval zero success |
286 */ |
| 300 * @retval non-zero failure |
287 #define cx_array_add_a(allocator, array, element) \ |
| 301 * @see cx_array_reallocator() |
288 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, element, 1) |
| 302 * @see cx_array_reserve() |
289 |
| 303 */ |
290 /** |
| 304 cx_attr_nonnull_arg(1, 2, 3, 6) |
291 * Appends an element to an array. |
| 305 CX_EXPORT int cx_array_copy(void **target, void *size, void *capacity, unsigned width, |
292 * |
| 306 size_t index, const void *src, size_t elem_size, size_t elem_count, |
293 * When the capacity is not enough to hold the new element, a re-allocation is attempted. |
| 307 CxArrayReallocator *reallocator); |
294 * |
| 308 |
295 * @param array the name of the array where the element shall be added |
| 309 /** |
296 * @param element (@c void*) a pointer to the element that shall be added |
| 310 * Convenience macro that uses cx_array_copy() with a default layout and |
297 * @retval zero success |
| 311 * the specified reallocator. |
298 * @retval non-zero a re-allocation was necessary but failed |
| 312 * |
299 */ |
| 313 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
300 #define cx_array_add(array, element) \ |
| 314 * @param array the name of the array (NOT a pointer or alias to the array) |
301 cx_array_add_a(cxDefaultAllocator, array, element) |
| 315 * @param index (@c size_t) the index where the copied elements shall be placed |
302 |
| 316 * @param src (@c void*) the source array |
303 /** |
| 317 * @param count (@c size_t) the number of elements to copy |
304 * Inserts an element into an array. |
| 318 * @retval zero success |
305 * |
| 319 * @retval non-zero failure |
306 * When the capacity is not enough to hold the new element, a re-allocation is attempted. |
| 320 * @see CX_ARRAY_DECLARE() |
307 * |
| 321 * @see cx_array_simple_copy() |
308 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation |
| 322 */ |
309 * @param array the name of the array where the element shall be inserted |
| 323 #define cx_array_simple_copy_a(reallocator, array, index, src, count) \ |
310 * @param index (@c size_t) the index where to insert the @p element |
| 324 cx_array_copy((void**)&(array), &(array##_size), &(array##_capacity), \ |
311 * @param element (@c void*) a pointer to the element that shall be inserted |
| 325 sizeof(array##_size), index, src, sizeof((array)[0]), count, \ |
312 * @retval zero success |
| 326 reallocator) |
313 * @retval non-zero a re-allocation was necessary but failed |
| 327 |
314 */ |
| 328 /** |
315 #define cx_array_insert_a(allocator, array, index, element) \ |
| 329 * Convenience macro that uses cx_array_copy() with a default layout and |
316 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, element, 1) |
| 330 * the default reallocator. |
317 |
| 331 * |
318 /** |
| 332 * @param array the name of the array (NOT a pointer or alias to the array) |
319 * Inserts an element into an array. |
| 333 * @param index (@c size_t) the index where the copied elements shall be placed |
320 * |
| 334 * @param src (@c void*) the source array |
321 * When the capacity is not enough to hold the new element, a re-allocation is attempted. |
| 335 * @param count (@c size_t) the number of elements to copy |
322 * |
| 336 * @retval zero success |
323 * @param array the name of the array where the element shall be inserted |
| 337 * @retval non-zero failure |
324 * @param index (@c size_t) the index where to insert the @p element |
| 338 * @see CX_ARRAY_DECLARE() |
325 * @param element (@c void*) a pointer to the element that shall be inserted |
| 339 * @see cx_array_simple_copy_a() |
326 * @retval zero success |
| 340 */ |
327 * @retval non-zero a re-allocation was necessary but failed |
| 341 #define cx_array_simple_copy(array, index, src, count) \ |
328 */ |
| 342 cx_array_simple_copy_a(NULL, array, index, src, count) |
329 #define cx_array_insert(array, index, element) \ |
| 343 |
330 cx_array_insert_a(cxDefaultAllocator, array, index, element) |
| 344 /** |
331 |
| 345 * Convenience macro that uses cx_array_reserve() with a default layout and |
332 /** |
| 346 * the specified reallocator. |
333 * Inserts data into an array. |
| 347 * |
334 * |
| 348 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
335 * When the capacity is not enough to hold the new elements, a re-allocation is attempted. |
| 349 * @param array the name of the array (NOT a pointer or alias to the array) |
336 * |
| 350 * @param count (@c size_t) the number of expected @em additional elements |
337 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation |
| 351 * @retval zero success |
338 * @param array the name of the array where the elements shall be inserted |
| 352 * @retval non-zero failure |
339 * @param index (@c size_t) the index where to insert the @p other data |
| 353 * @see CX_ARRAY_DECLARE() |
340 * @param other (@c void*) a pointer to an array of data that shall be inserted |
| 354 * @see cx_array_simple_reserve() |
341 * @param n (@c size_t) the number of elements that shall be inserted |
| 355 */ |
342 * @retval zero success |
| 356 #define cx_array_simple_reserve_a(reallocator, array, count) \ |
343 * @retval non-zero a re-allocation was necessary but failed |
| 357 cx_array_reserve((void**)&(array), &(array##_size), &(array##_capacity), \ |
344 */ |
| 358 sizeof(array##_size), sizeof((array)[0]), count, \ |
345 #define cx_array_insert_array_a(allocator, array, index, other, n) \ |
| 359 reallocator) |
346 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, other, n) |
| 360 |
347 |
| 361 /** |
348 /** |
| 362 * Convenience macro that uses cx_array_reserve() with a default layout and |
349 * Inserts data into an array. |
| 363 * the default reallocator. |
350 * |
| 364 * |
351 * When the capacity is not enough to hold the new elements, a re-allocation is attempted. |
| 365 * @param array the name of the array (NOT a pointer or alias to the array) |
352 * |
| 366 * @param count (@c size_t) the number of expected additional elements |
353 * @param array the name of the array where the elements shall be inserted |
| 367 * @retval zero success |
354 * @param index (@c size_t) the index where to insert the @p other data |
| 368 * @retval non-zero failure |
355 * @param other (@c void*) a pointer to an array of data that shall be inserted |
| 369 * @see CX_ARRAY_DECLARE() |
356 * @param n (@c size_t) the number of elements that shall be inserted |
| 370 * @see cx_array_simple_reserve_a() |
357 * @retval zero success |
| 371 */ |
358 * @retval non-zero a re-allocation was necessary but failed |
| 372 #define cx_array_simple_reserve(array, count) \ |
359 */ |
| 373 cx_array_simple_reserve_a(NULL, array, count) |
360 #define cx_array_insert_array(array, index, other, n) \ |
| 374 |
361 cx_array_insert_array_a(cxDefaultAllocator, array, index, other, n) |
| 375 /** |
362 |
| 376 * Adds an element to an array with the possibility of allocating more space. |
363 /** |
| 377 * |
364 * Appends data to an array. |
| 378 * The element @p elem is added to the end of the @p target array which contains |
365 * |
| 379 * @p size elements, already. The @p capacity must point to a variable denoting |
366 * When the capacity is not enough to hold the new elements, a re-allocation is attempted. |
| 380 * the current maximum number of elements the array can hold. |
367 * |
| 381 * |
368 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation |
| 382 * If the capacity is insufficient to hold the new element, an attempt to |
369 * @param array the name of the array where the elements shall be added |
| 383 * increase the @p capacity is made and the new capacity is written back. |
370 * @param other (@c void*) a pointer to an array of data that shall be added |
| 384 * |
371 * @param n (@c size_t) the number of elements that shall be added |
| 385 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. |
372 * @retval zero success |
| 386 * It is important, however, that @p size and @p capacity are pointers to |
373 * @retval non-zero a re-allocation was necessary but failed |
| 387 * variables of the same type. |
374 */ |
| 388 * |
375 #define cx_array_add_array_a(allocator, array, other, n) \ |
| 389 * @param target (@c void**) a pointer to the target array |
376 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, other, n) |
| 390 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array |
377 |
| 391 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array |
378 /** |
| 392 * @param elem_size (@c size_t) the size of one element |
379 * Appends data to an array. |
| 393 * @param elem (@c void*) a pointer to the element to add |
380 * |
| 394 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
381 * When the capacity is not enough to hold the new elements, a re-allocation is attempted. |
| 395 * @retval zero success |
382 * |
| 396 * @retval non-zero failure |
383 * @param array the name of the array where the elements shall be added |
| 397 */ |
384 * @param other (@c void*) a pointer to an array of data that shall be added |
| 398 #define cx_array_add(target, size, capacity, elem_size, elem, reallocator) \ |
385 * @param n (@c size_t) the number of elements that shall be added |
| 399 cx_array_copy((void**)(target), size, capacity, sizeof(*(size)), \ |
386 * @retval zero success |
| 400 *(size), elem, elem_size, 1, reallocator) |
387 * @retval non-zero a re-allocation was necessary but failed |
| 401 |
388 */ |
| 402 /** |
389 #define cx_array_add_array(array, other, n) \ |
| 403 * Convenience macro that uses cx_array_add() with a default layout and |
390 cx_array_add_array_a(cxDefaultAllocator, array, other, n) |
| 404 * the specified reallocator. |
391 |
| 405 * |
392 /** |
| 406 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
393 * Inserts sorted data into a sorted array. |
| 407 * @param array the name of the array (NOT a pointer or alias to the array) |
394 * |
| 408 * @param elem the element to add (NOT a pointer, address is automatically taken) |
395 * Internal function - do not use. |
| 409 * @retval zero success |
396 * |
| 410 * @retval non-zero failure |
397 * @param allocator the allocator to use for a possible reallocation |
| 411 * @see CX_ARRAY_DECLARE() |
398 * @param array a pointer to the array structure |
| 412 * @see cx_array_simple_add() |
399 * @param elem_size the size of one element |
| 413 */ |
400 * @param cmp_func |
| 414 #define cx_array_simple_add_a(reallocator, array, elem) \ |
401 * @param sorted_data a pointer to an array of data that shall be inserted |
| 415 cx_array_simple_copy_a(reallocator, array, array##_size, &(elem), 1) |
402 * @param n the number of elements that shall be inserted |
| 416 |
403 * @param allow_duplicates @c false if duplicates shall be skipped during insertion |
| 417 /** |
404 * @retval zero success |
| 418 * Convenience macro that uses cx_array_add() with a default layout and |
405 * @retval non-zero a re-allocation was necessary but failed |
| 419 * the default reallocator. |
406 */ |
| 420 * |
407 cx_attr_nonnull |
| 421 * @param array the name of the array (NOT a pointer or alias to the array) |
408 CX_EXPORT int cx_array_insert_sorted_(const CxAllocator *allocator, CxArray *array, |
| 422 * @param elem the element to add (NOT a pointer, address is automatically taken) |
409 size_t elem_size, cx_compare_func cmp_func, const void *sorted_data, size_t n, |
| 423 * @retval zero success |
410 bool allow_duplicates); |
| 424 * @retval non-zero failure |
|
| 425 * @see CX_ARRAY_DECLARE() |
|
| 426 * @see cx_array_simple_add_a() |
|
| 427 */ |
|
| 428 #define cx_array_simple_add(array, elem) \ |
|
| 429 cx_array_simple_add_a(cx_array_default_reallocator, array, elem) |
|
| 430 |
|
| 431 /** |
|
| 432 * Inserts a sorted array into another sorted array. |
|
| 433 * |
|
| 434 * If either the target or the source array is not already sorted with respect |
|
| 435 * to the specified @p cmp_func, the behavior is undefined. |
|
| 436 * |
|
| 437 * If the capacity is insufficient to hold the new data, a reallocation |
|
| 438 * attempt is made. |
|
| 439 * You can create your own reallocator by hand, use #cx_array_default_reallocator, |
|
| 440 * or use the convenience function cx_array_reallocator() to create a custom reallocator. |
|
| 441 * |
|
| 442 * @param target a pointer to the target array |
|
| 443 * @param size a pointer to the size of the target array |
|
| 444 * @param capacity a pointer to the capacity of the target array |
|
| 445 * @param cmp_func the compare function for the elements |
|
| 446 * @param src the source array |
|
| 447 * @param elem_size the size of one element |
|
| 448 * @param elem_count the number of elements to insert |
|
| 449 * @param reallocator the array reallocator to use |
|
| 450 * (@c NULL defaults to #cx_array_default_reallocator) |
|
| 451 * @retval zero success |
|
| 452 * @retval non-zero failure |
|
| 453 */ |
|
| 454 cx_attr_nonnull_arg(1, 2, 3, 5) |
|
| 455 CX_EXPORT int cx_array_insert_sorted(void **target, size_t *size, size_t *capacity, |
|
| 456 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, |
|
| 457 CxArrayReallocator *reallocator); |
|
| 458 |
411 |
| 459 /** |
412 /** |
| 460 * Inserts an element into a sorted array. |
413 * Inserts an element into a sorted array. |
| 461 * |
414 * |
| 462 * If the target array is not already sorted with respect |
415 * When the capacity is not enough to hold the new element, a re-allocation is attempted. |
| 463 * to the specified @p cmp_func, the behavior is undefined. |
416 * |
| 464 * |
417 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined. |
| 465 * If the capacity is not enough to hold the new data, a reallocation |
418 * |
| 466 * attempt is made. |
419 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation |
| 467 * |
420 * @param array the name of the array where the elements shall be inserted |
| 468 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. |
421 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order |
| 469 * It is important, however, that @p size and @p capacity are pointers to |
422 * @param element (@c void*) a pointer to element that shall be inserted |
| 470 * variables of the same type. |
423 * @retval zero success |
| 471 * |
424 * @retval non-zero a re-allocation was necessary but failed |
| 472 * @param target (@c void**) a pointer to the target array |
425 */ |
| 473 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array |
426 #define cx_array_insert_sorted_a(allocator, array, cmp_func, element) \ |
| 474 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array |
427 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, element, 1, true) |
| 475 * @param elem_size (@c size_t) the size of one element |
428 |
| 476 * @param elem (@c void*) a pointer to the element to add |
429 /** |
| 477 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
430 * Inserts an element into a sorted array. |
| 478 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
431 * |
| 479 * @retval zero success |
432 * When the capacity is not enough to hold the new element, a re-allocation is attempted. |
| 480 * @retval non-zero failure |
433 * |
| 481 */ |
434 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined. |
| 482 #define cx_array_add_sorted(target, size, capacity, elem_size, elem, cmp_func, reallocator) \ |
435 * |
| 483 cx_array_insert_sorted((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator) |
436 * @param array the name of the array where the elements shall be inserted |
| 484 |
437 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order |
| 485 /** |
438 * @param element (@c void*) a pointer to element that shall be inserted |
| 486 * Convenience macro for cx_array_add_sorted() with a default |
439 * @retval zero success |
| 487 * layout and the specified reallocator. |
440 * @retval non-zero a re-allocation was necessary but failed |
| 488 * |
441 */ |
| 489 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
442 #define cx_array_insert_sorted(array, cmp_func, element) \ |
| 490 * @param array the name of the array (NOT a pointer or alias to the array) |
443 cx_array_insert_sorted_a(cxDefaultAllocator, array, cmp_func, element) |
| 491 * @param elem the element to add (NOT a pointer, address is automatically taken) |
444 |
| 492 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
445 /** |
| 493 * @retval zero success |
446 * Inserts sorted data into a sorted array. |
| 494 * @retval non-zero failure |
447 * |
| 495 * @see CX_ARRAY_DECLARE() |
448 * When the capacity is not enough to hold the new elements, a re-allocation is attempted. |
| 496 * @see cx_array_simple_add_sorted() |
449 * |
| 497 */ |
450 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined. |
| 498 #define cx_array_simple_add_sorted_a(reallocator, array, elem, cmp_func) \ |
451 * |
| 499 cx_array_add_sorted(&array, &(array##_size), &(array##_capacity), \ |
452 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation |
| 500 sizeof((array)[0]), &(elem), cmp_func, reallocator) |
453 * @param array the name of the array where the elements shall be inserted |
| 501 |
454 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order |
| 502 /** |
455 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted |
| 503 * Convenience macro for cx_array_add_sorted() with a default |
456 * @param n (@c size_t) the number of elements that shall be inserted |
| 504 * layout and the default reallocator. |
457 * @retval zero success |
| 505 * |
458 * @retval non-zero a re-allocation was necessary but failed |
| 506 * @param array the name of the array (NOT a pointer or alias to the array) |
459 */ |
| 507 * @param elem the element to add (NOT a pointer, address is automatically taken) |
460 #define cx_array_insert_sorted_array_a(allocator, array, cmp_func, sorted_data, n) \ |
| 508 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
461 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, sorted_data, n, true) |
| 509 * @retval zero success |
462 |
| 510 * @retval non-zero failure |
463 /** |
| 511 * @see CX_ARRAY_DECLARE() |
464 * Inserts sorted data into a sorted array. |
| 512 * @see cx_array_simple_add_sorted_a() |
465 * |
| 513 */ |
466 * When the capacity is not enough to hold the new elements, a re-allocation is attempted. |
| 514 #define cx_array_simple_add_sorted(array, elem, cmp_func) \ |
467 * |
| 515 cx_array_simple_add_sorted_a(NULL, array, elem, cmp_func) |
468 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined. |
| 516 |
469 * |
| 517 /** |
470 * @param array the name of the array where the elements shall be inserted |
| 518 * Convenience macro for cx_array_insert_sorted() with a default |
471 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order |
| 519 * layout and the specified reallocator. |
472 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted |
| 520 * |
473 * @param n (@c size_t) the number of elements that shall be inserted |
| 521 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
474 * @retval zero success |
| 522 * @param array the name of the array (NOT a pointer or alias to the array) |
475 * @retval non-zero a re-allocation was necessary but failed |
| 523 * @param src (@c void*) pointer to the source array |
476 */ |
| 524 * @param n (@c size_t) number of elements in the source array |
477 #define cx_array_insert_sorted_array(array, cmp_func, sorted_data, n) \ |
| 525 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
478 cx_array_insert_sorted_array_a(cxDefaultAllocator, array, cmp_func, sorted_data, n) |
| 526 * @retval zero success |
479 |
| 527 * @retval non-zero failure |
480 /** |
| 528 * @see CX_ARRAY_DECLARE() |
481 * Inserts an element into a sorted array if it is not already contained. |
| 529 * @see cx_array_simple_insert_sorted() |
482 * |
| 530 */ |
483 * When the capacity is not enough to hold the new element, a re-allocation is attempted. |
| 531 #define cx_array_simple_insert_sorted_a(reallocator, array, src, n, cmp_func) \ |
484 * |
| 532 cx_array_insert_sorted((void**)(&array), &(array##_size), &(array##_capacity), \ |
485 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined. |
| 533 cmp_func, src, sizeof((array)[0]), n, reallocator) |
486 * |
| 534 |
487 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation |
| 535 /** |
488 * @param array the name of the array where the elements shall be inserted |
| 536 * Convenience macro for cx_array_insert_sorted() with a default |
489 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order |
| 537 * layout and the default reallocator. |
490 * @param element (@c void*) a pointer to element that shall be inserted |
| 538 * |
491 * @retval zero success |
| 539 * @param array the name of the array (NOT a pointer or alias to the array) |
492 * @retval non-zero a re-allocation was necessary but failed |
| 540 * @param src (@c void*) pointer to the source array |
493 */ |
| 541 * @param n (@c size_t) number of elements in the source array |
494 #define cx_array_insert_unique_a(allocator, array, cmp_func, element) \ |
| 542 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
495 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, element, 1, false) |
| 543 * @retval zero success |
496 |
| 544 * @retval non-zero failure |
497 /** |
| 545 * @see CX_ARRAY_DECLARE() |
498 * Inserts an element into a sorted array if it is not already contained. |
| 546 * @see cx_array_simple_insert_sorted_a() |
499 * |
| 547 */ |
500 * When the capacity is not enough to hold the new element, a re-allocation is attempted. |
| 548 #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \ |
501 * |
| 549 cx_array_simple_insert_sorted_a(NULL, array, src, n, cmp_func) |
502 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined. |
| 550 |
503 * |
| 551 |
504 * @param array the name of the array where the elements shall be inserted |
| 552 /** |
505 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order |
| 553 * Inserts a sorted array into another sorted array, avoiding duplicates. |
506 * @param element (@c void*) a pointer to element that shall be inserted |
| 554 * |
507 * @retval zero success |
| 555 * If either the target or the source array is not already sorted with respect |
508 * @retval non-zero a re-allocation was necessary but failed |
| 556 * to the specified @p cmp_func, the behavior is undefined. |
509 */ |
| 557 * |
510 #define cx_array_insert_unique(array, cmp_func, element) \ |
| 558 * If the capacity is insufficient to hold the new data, a reallocation |
511 cx_array_insert_unique_a(cxDefaultAllocator, array, cmp_func, element) |
| 559 * attempt is made. |
512 |
| 560 * You can create your own reallocator by hand, use #cx_array_default_reallocator, |
513 /** |
| 561 * or use the convenience function cx_array_reallocator() to create a custom reallocator. |
514 * Inserts sorted data into a sorted array, skipping duplicates. |
| 562 * |
515 * |
| 563 * @param target a pointer to the target array |
516 * When the capacity is not enough to hold the new elements, a re-allocation is attempted. |
| 564 * @param size a pointer to the size of the target array |
517 * |
| 565 * @param capacity a pointer to the capacity of the target array |
518 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined. |
| 566 * @param cmp_func the compare function for the elements |
519 * |
| 567 * @param src the source array |
520 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation |
| 568 * @param elem_size the size of one element |
521 * @param array the name of the array where the elements shall be inserted |
| 569 * @param elem_count the number of elements to insert |
522 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order |
| 570 * @param reallocator the array reallocator to use |
523 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted |
| 571 * (@c NULL defaults to #cx_array_default_reallocator) |
524 * @param n (@c size_t) the number of elements that shall be inserted |
| 572 * @retval zero success |
525 * @retval zero success |
| 573 * @retval non-zero failure |
526 * @retval non-zero a re-allocation was necessary but failed |
| 574 */ |
527 */ |
| 575 cx_attr_nonnull_arg(1, 2, 3, 5) |
528 #define cx_array_insert_unique_array_a(allocator, array, cmp_func, sorted_data, n) \ |
| 576 CX_EXPORT int cx_array_insert_unique(void **target, size_t *size, size_t *capacity, |
529 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, sorted_data, n, false) |
| 577 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, |
530 |
| 578 CxArrayReallocator *reallocator); |
531 /** |
| 579 |
532 * Inserts sorted data into a sorted array, skipping duplicates. |
| 580 /** |
533 * |
| 581 * Inserts an element into a sorted array if it does not exist. |
534 * When the capacity is not enough to hold the new elements, a re-allocation is attempted. |
| 582 * |
535 * |
| 583 * If the target array is not already sorted with respect |
536 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined. |
| 584 * to the specified @p cmp_func, the behavior is undefined. |
537 * |
| 585 * |
538 * @param array the name of the array where the elements shall be inserted |
| 586 * If the capacity is insufficient to hold the new data, a reallocation |
539 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order |
| 587 * attempt is made. |
540 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted |
| 588 * |
541 * @param n (@c size_t) the number of elements that shall be inserted |
| 589 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. |
542 * @retval zero success |
| 590 * It is important, however, that @p size and @p capacity are pointers to |
543 * @retval non-zero a re-allocation was necessary but failed |
| 591 * variables of the same type. |
544 */ |
| 592 * |
545 #define cx_array_insert_unique_array(array, cmp_func, sorted_data, n) \ |
| 593 * @param target (@c void**) a pointer to the target array |
546 cx_array_insert_unique_array_a(cxDefaultAllocator, array, cmp_func, sorted_data, n) |
| 594 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array |
547 |
| 595 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array |
548 /** |
| 596 * @param elem_size (@c size_t) the size of one element |
549 * Creates an iterator over the elements of an array. |
| 597 * @param elem (@c void*) a pointer to the element to add |
550 * |
| 598 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
551 * Internal function - do not use. |
| 599 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
552 * |
| 600 * @retval zero success (also when the element was already present) |
553 * @param array a pointer to the array structure |
| 601 * @retval non-zero failure |
554 * @param elem_size the size of one element |
| 602 */ |
555 * @return an iterator over the elements |
| 603 #define cx_array_add_unique(target, size, capacity, elem_size, elem, cmp_func, reallocator) \ |
556 */ |
| 604 cx_array_insert_unique((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator) |
557 cx_attr_nodiscard cx_attr_nonnull |
| 605 |
558 CX_EXPORT CxIterator cx_array_iterator_(CxArray *array, size_t elem_size); |
| 606 /** |
559 |
| 607 * Convenience macro for cx_array_add_unique() with a default |
560 /** |
| 608 * layout and the specified reallocator. |
561 * Creates an iterator over the elements of an array. |
| 609 * |
562 * |
| 610 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
563 * The iterator will yield pointers to the elements. |
| 611 * @param array the name of the array (NOT a pointer or alias to the array) |
564 * |
| 612 * @param elem the element to add (NOT a pointer, address is automatically taken) |
565 * @param array the name of the array |
| 613 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
566 * @return an iterator over the elements |
| 614 * @retval zero success |
567 * @see cx_array_iterator_ptr() |
| 615 * @retval non-zero failure |
568 */ |
| 616 * @see CX_ARRAY_DECLARE() |
569 #define cx_array_iterator(array) \ |
| 617 * @see cx_array_simple_add_unique() |
570 cx_array_iterator_((CxArray*)&(array), sizeof((array).data[0])) |
| 618 */ |
571 |
| 619 #define cx_array_simple_add_unique_a(reallocator, array, elem, cmp_func) \ |
572 /** |
| 620 cx_array_add_unique(&array, &(array##_size), &(array##_capacity), \ |
573 * Creates an iterator over the elements of an array containing pointers. |
| 621 sizeof((array)[0]), &(elem), cmp_func, reallocator) |
574 * |
| 622 |
575 * Internal function - do not use. |
| 623 /** |
576 * |
| 624 * Convenience macro for cx_array_add_unique() with a default |
577 * @param array the name of the array |
| 625 * layout and the default reallocator. |
578 * @return an iterator over the elements |
| 626 * |
579 */ |
| 627 * @param array the name of the array (NOT a pointer or alias to the array) |
580 cx_attr_nodiscard cx_attr_nonnull |
| 628 * @param elem the element to add (NOT a pointer, address is automatically taken) |
581 CX_EXPORT CxIterator cx_array_iterator_ptr_(CxArray *array); |
| 629 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
582 |
| 630 * @retval zero success |
583 /** |
| 631 * @retval non-zero failure |
584 * Creates an iterator over the elements of an array containing pointers. |
| 632 * @see CX_ARRAY_DECLARE() |
585 * |
| 633 * @see cx_array_simple_add_unique_a() |
586 * The iterator will yield the elements themselves, which are supposed to |
| 634 */ |
587 * be pointers. |
| 635 #define cx_array_simple_add_unique(array, elem, cmp_func) \ |
588 * |
| 636 cx_array_simple_add_unique_a(NULL, array, elem, cmp_func) |
589 * @param array the name of the array |
| 637 |
590 * @return an iterator over the elements |
| 638 /** |
591 * @see cx_array_iterator() |
| 639 * Convenience macro for cx_array_insert_unique() with a default |
592 */ |
| 640 * layout and the specified reallocator. |
593 #define cx_array_iterator_ptr(array) \ |
| 641 * |
594 cx_array_iterator_ptr_((CxArray*)&(array)) |
| 642 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
595 |
| 643 * @param array the name of the array (NOT a pointer or alias to the array) |
596 /** |
| 644 * @param src (@c void*) pointer to the source array |
597 * Deallocates an array. |
| 645 * @param n (@c size_t) number of elements in the source array |
598 * |
| 646 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
599 * Internal function - do not use. |
| 647 * @retval zero success |
600 * |
| 648 * @retval non-zero failure |
601 * @param allocator (@c CxAllocator*) the allocator which was used to allocate the array |
| 649 * @see CX_ARRAY_DECLARE() |
602 * @param array a pointer to the array structure |
| 650 * @see cx_array_simple_insert_unique() |
603 */ |
| 651 */ |
604 cx_attr_nonnull |
| 652 #define cx_array_simple_insert_unique_a(reallocator, array, src, n, cmp_func) \ |
605 CX_EXPORT void cx_array_free_(const CxAllocator *allocator, CxArray *array); |
| 653 cx_array_insert_unique((void**)(&array), &(array##_size), &(array##_capacity), \ |
606 |
| 654 cmp_func, src, sizeof((array)[0]), n, reallocator) |
607 /** |
| 655 |
608 * Deallocates an array. |
| 656 /** |
609 * |
| 657 * Convenience macro for cx_array_insert_unique() with a default |
610 * The structure is reset to zero and can be re-initialized with |
| 658 * layout and the default reallocator. |
611 * cx_array_inita(). |
| 659 * |
612 * |
| 660 * @param array the name of the array (NOT a pointer or alias to the array) |
613 * @param array the name of the array |
| 661 * @param src (@c void*) pointer to the source array |
614 */ |
| 662 * @param n (@c size_t) number of elements in the source array |
615 #define cx_array_free(array) cx_array_free_(cxDefaultAllocator, (CxArray*)&(array)) |
| 663 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
616 |
| 664 * @retval zero success |
617 /** |
| 665 * @retval non-zero failure |
618 * Deallocates an array. |
| 666 * @see CX_ARRAY_DECLARE() |
619 * |
| 667 * @see cx_array_simple_insert_unique_a() |
620 * The structure is reset to zero and can be re-initialized with |
| 668 */ |
621 * cx_array_init_a(). |
| 669 #define cx_array_simple_insert_unique(array, src, n, cmp_func) \ |
622 * |
| 670 cx_array_simple_insert_unique_a(NULL, array, src, n, cmp_func) |
623 * @param allocator (@c CxAllocator*) the allocator which was used to allocate the array |
| |
624 * @param array the name of the array |
| |
625 */ |
| |
626 #define cx_array_free_a(allocator, array) cx_array_free_(allocator, (CxArray*)&(array)) |
| |
627 |
| 671 |
628 |
| 672 /** |
629 /** |
| 673 * Searches the largest lower bound in a sorted array. |
630 * Searches the largest lower bound in a sorted array. |
| 674 * |
631 * |
| 675 * In other words, this function returns the index of the largest element |
632 * In other words, this function returns the index of the largest element |