ucx/cx/list.h

changeset 22
112b85020dc9
parent 21
5ea41679e15d
equal deleted inserted replaced
21:5ea41679e15d 22:112b85020dc9
78 */ 78 */
79 void (*deallocate)(struct cx_list_s *list); 79 void (*deallocate)(struct cx_list_s *list);
80 80
81 /** 81 /**
82 * Member function for inserting a single element. 82 * Member function for inserting a single element.
83 * The data pointer may be @c NULL in which case the function shall only allocate memory. 83 * The data pointer may be @c NULL, in which case the function shall only allocate memory.
84 * Returns a pointer to the data of the inserted element. 84 * Returns a pointer to the allocated memory or @c NULL if allocation fails.
85 */ 85 */
86 void *(*insert_element)( 86 void *(*insert_element)(struct cx_list_s *list, size_t index, const void *data);
87 struct cx_list_s *list,
88 size_t index,
89 const void *data
90 );
91 87
92 /** 88 /**
93 * Member function for inserting multiple elements. 89 * Member function for inserting multiple elements.
94 * 90 *
91 * The data pointer may be @c NULL, in which case the function shall only allocate memory.
92 * Returns the number of successfully inserted or allocated elements.
93 *
95 * @see cx_list_default_insert_array() 94 * @see cx_list_default_insert_array()
96 */ 95 */
97 size_t (*insert_array)( 96 size_t (*insert_array)(struct cx_list_s *list, size_t index, const void *data, size_t n);
98 struct cx_list_s *list,
99 size_t index,
100 const void *data,
101 size_t n
102 );
103 97
104 /** 98 /**
105 * Member function for inserting sorted elements into a sorted list. 99 * Member function for inserting sorted elements into a sorted list.
100 * Returns the number of successfully inserted elements.
106 * 101 *
107 * @see cx_list_default_insert_sorted() 102 * @see cx_list_default_insert_sorted()
108 */ 103 */
109 size_t (*insert_sorted)( 104 size_t (*insert_sorted)(struct cx_list_s *list, const void *sorted_data, size_t n);
110 struct cx_list_s *list, 105
111 const void *sorted_data, 106 /**
112 size_t n 107 * Member function for inserting multiple elements if they do not exist.
113 ); 108 * Implementations shall return the number of successfully processed elements
109 * (including those which were not added because they are already contained).
110 * @see cx_list_default_insert_unique()
111 */
112 size_t (*insert_unique)(struct cx_list_s *list, const void *sorted_data, size_t n);
114 113
115 /** 114 /**
116 * Member function for inserting an element relative to an iterator position. 115 * Member function for inserting an element relative to an iterator position.
117 */ 116 */
118 int (*insert_iter)( 117 int (*insert_iter)(struct cx_iterator_s *iter, const void *elem, int prepend);
119 struct cx_iterator_s *iter,
120 const void *elem,
121 int prepend
122 );
123 118
124 /** 119 /**
125 * Member function for removing elements. 120 * Member function for removing elements.
126 * 121 *
127 * Implementations SHALL check if @p targetbuf is set and copy the elements 122 * Implementations SHALL check if @p targetbuf is set and copy the elements
129 * When @p targetbuf is not set, the destructors SHALL be invoked. 124 * When @p targetbuf is not set, the destructors SHALL be invoked.
130 * 125 *
131 * The function SHALL return the actual number of elements removed, which 126 * The function SHALL return the actual number of elements removed, which
132 * might be lower than @p num when going out of bounds. 127 * might be lower than @p num when going out of bounds.
133 */ 128 */
134 size_t (*remove)( 129 size_t (*remove)(struct cx_list_s *list, size_t index, size_t num, void *targetbuf);
135 struct cx_list_s *list,
136 size_t index,
137 size_t num,
138 void *targetbuf
139 );
140 130
141 /** 131 /**
142 * Member function for removing all elements. 132 * Member function for removing all elements.
143 */ 133 */
144 void (*clear)(struct cx_list_s *list); 134 void (*clear)(struct cx_list_s *list);
146 /** 136 /**
147 * Member function for swapping two elements. 137 * Member function for swapping two elements.
148 * 138 *
149 * @see cx_list_default_swap() 139 * @see cx_list_default_swap()
150 */ 140 */
151 int (*swap)( 141 int (*swap)(struct cx_list_s *list, size_t i, size_t j);
152 struct cx_list_s *list,
153 size_t i,
154 size_t j
155 );
156 142
157 /** 143 /**
158 * Member function for element lookup. 144 * Member function for element lookup.
159 */ 145 */
160 void *(*at)( 146 void *(*at)(const struct cx_list_s *list, size_t index);
161 const struct cx_list_s *list,
162 size_t index
163 );
164 147
165 /** 148 /**
166 * Member function for finding and optionally removing an element. 149 * Member function for finding and optionally removing an element.
167 */ 150 */
168 size_t (*find_remove)( 151 size_t (*find_remove)(struct cx_list_s *list, const void *elem, bool remove);
169 struct cx_list_s *list,
170 const void *elem,
171 bool remove
172 );
173 152
174 /** 153 /**
175 * Member function for sorting the list. 154 * Member function for sorting the list.
176 * 155 *
177 * @see cx_list_default_sort() 156 * @see cx_list_default_sort()
179 void (*sort)(struct cx_list_s *list); 158 void (*sort)(struct cx_list_s *list);
180 159
181 /** 160 /**
182 * Optional member function for comparing this list 161 * Optional member function for comparing this list
183 * to another list of the same type. 162 * to another list of the same type.
184 * If set to @c NULL, comparison won't be optimized. 163 * If set to @c NULL, the comparison won't be optimized.
185 */ 164 */
186 cx_attr_nonnull 165 int (*compare)(const struct cx_list_s *list, const struct cx_list_s *other);
187 int (*compare)(
188 const struct cx_list_s *list,
189 const struct cx_list_s *other
190 );
191 166
192 /** 167 /**
193 * Member function for reversing the order of the items. 168 * Member function for reversing the order of the items.
194 */ 169 */
195 void (*reverse)(struct cx_list_s *list); 170 void (*reverse)(struct cx_list_s *list);
196 171
197 /** 172 /**
173 * Optional member function for changing the capacity.
174 * If the list does not support overallocation, this can be set to @c NULL.
175 */
176 int (*change_capacity)(struct cx_list_s *list, size_t new_capacity);
177
178 /**
198 * Member function for returning an iterator pointing to the specified index. 179 * Member function for returning an iterator pointing to the specified index.
199 */ 180 */
200 struct cx_iterator_s (*iterator)( 181 struct cx_iterator_s (*iterator)(const struct cx_list_s *list, size_t index, bool backward);
201 const struct cx_list_s *list,
202 size_t index,
203 bool backward
204 );
205 }; 182 };
206 183
207 /** 184 /**
208 * Common type for all list implementations. 185 * Common type for all list implementations.
209 */ 186 */
212 /** 189 /**
213 * A shared instance of an empty list. 190 * A shared instance of an empty list.
214 * 191 *
215 * Writing to that list is not allowed. 192 * Writing to that list is not allowed.
216 * 193 *
217 * You can use this is a placeholder for initializing CxList pointers 194 * You can use this as a placeholder for initializing CxList pointers
218 * for which you do not want to reserve memory right from the beginning. 195 * for which you do not want to reserve memory right from the beginning.
219 */ 196 */
220 cx_attr_export 197 CX_EXPORT extern CxList *const cxEmptyList;
221 extern CxList *const cxEmptyList;
222 198
223 /** 199 /**
224 * Default implementation of an array insert. 200 * Default implementation of an array insert.
225 * 201 *
226 * This function uses the element insert function for each element of the array. 202 * This function uses the element insert function for each element of the array.
233 * @param data a pointer to the array of data to insert 209 * @param data a pointer to the array of data to insert
234 * @param n the number of elements to insert 210 * @param n the number of elements to insert
235 * @return the number of elements actually inserted 211 * @return the number of elements actually inserted
236 */ 212 */
237 cx_attr_nonnull 213 cx_attr_nonnull
238 cx_attr_export 214 CX_EXPORT size_t cx_list_default_insert_array(struct cx_list_s *list,
239 size_t cx_list_default_insert_array( 215 size_t index, const void *data, size_t n);
240 struct cx_list_s *list,
241 size_t index,
242 const void *data,
243 size_t n
244 );
245 216
246 /** 217 /**
247 * Default implementation of a sorted insert. 218 * Default implementation of a sorted insert.
248 * 219 *
249 * This function uses the array insert function to insert consecutive groups 220 * This function uses the array insert function to insert consecutive groups
258 * @param sorted_data a pointer to the array of pre-sorted data to insert 229 * @param sorted_data a pointer to the array of pre-sorted data to insert
259 * @param n the number of elements to insert 230 * @param n the number of elements to insert
260 * @return the number of elements actually inserted 231 * @return the number of elements actually inserted
261 */ 232 */
262 cx_attr_nonnull 233 cx_attr_nonnull
263 cx_attr_export 234 CX_EXPORT size_t cx_list_default_insert_sorted(struct cx_list_s *list,
264 size_t cx_list_default_insert_sorted( 235 const void *sorted_data, size_t n);
265 struct cx_list_s *list, 236
266 const void *sorted_data, 237 /**
267 size_t n 238 * Default implementation of an array insert where only elements are inserted when they don't exist in the list.
268 ); 239 *
240 * This function is similar to cx_list_default_insert_sorted(), except it skips elements that are already in the list.
241 *
242 * @note The return value of this function denotes the number of elements from the @p sorted_data that are definitely
243 * contained in the list after completing the call. It is @em not the number of elements that were newly inserted.
244 * That means, when no error occurred, the return value should be @p n.
245 *
246 * Use this in your own list class if you do not want to implement an optimized version for your list.
247 *
248 * @param list the list
249 * @param sorted_data a pointer to the array of pre-sorted data to insert
250 * @param n the number of elements to insert
251 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call
252 */
253 cx_attr_nonnull
254 CX_EXPORT size_t cx_list_default_insert_unique(struct cx_list_s *list,
255 const void *sorted_data, size_t n);
269 256
270 /** 257 /**
271 * Default unoptimized sort implementation. 258 * Default unoptimized sort implementation.
272 * 259 *
273 * This function will copy all data to an array, sort the array with standard 260 * This function will copy all data to an array, sort the array with standard
277 * version for your list. 264 * version for your list.
278 * 265 *
279 * @param list the list that shall be sorted 266 * @param list the list that shall be sorted
280 */ 267 */
281 cx_attr_nonnull 268 cx_attr_nonnull
282 cx_attr_export 269 CX_EXPORT void cx_list_default_sort(struct cx_list_s *list);
283 void cx_list_default_sort(struct cx_list_s *list);
284 270
285 /** 271 /**
286 * Default unoptimized swap implementation. 272 * Default unoptimized swap implementation.
287 * 273 *
288 * Use this in your own list class if you do not want to implement an optimized 274 * Use this in your own list class if you do not want to implement an optimized
294 * @retval zero success 280 * @retval zero success
295 * @retval non-zero when indices are out of bounds or memory 281 * @retval non-zero when indices are out of bounds or memory
296 * allocation for the temporary buffer fails 282 * allocation for the temporary buffer fails
297 */ 283 */
298 cx_attr_nonnull 284 cx_attr_nonnull
299 cx_attr_export 285 CX_EXPORT int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j);
300 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j);
301 286
302 /** 287 /**
303 * Initializes a list struct. 288 * Initializes a list struct.
304 * 289 *
305 * Only use this function if you are creating your own list implementation. 290 * Only use this function if you are creating your own list implementation.
306 * The purpose of this function is to be called in the initialization code 291 * The purpose of this function is to be called in the initialization code
307 * of your list, to set certain members correctly. 292 * of your list to set certain members correctly.
308 * 293 *
309 * This is particularly important when you want your list to support 294 * This is particularly important when you want your list to support
310 * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list 295 * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list
311 * class accordingly and make sure that you can implement your list as if 296 * class accordingly and make sure that you can implement your list as if
312 * it was only storing objects and the wrapper will automatically enable 297 * it was only storing objects, and the wrapper will automatically enable
313 * the feature of storing pointers. 298 * the feature of storing pointers.
314 * 299 *
315 * @par Example 300 * @par Example
316 * 301 *
317 * @code 302 * @code
342 * @param allocator the allocator for the elements 327 * @param allocator the allocator for the elements
343 * @param comparator a compare function for the elements 328 * @param comparator a compare function for the elements
344 * @param elem_size the size of one element 329 * @param elem_size the size of one element
345 */ 330 */
346 cx_attr_nonnull_arg(1, 2, 3) 331 cx_attr_nonnull_arg(1, 2, 3)
347 cx_attr_export 332 CX_EXPORT void cx_list_init(struct cx_list_s *list,
348 void cx_list_init( 333 struct cx_list_class_s *cl, const struct cx_allocator_s *allocator,
349 struct cx_list_s *list, 334 cx_compare_func comparator, size_t elem_size);
350 struct cx_list_class_s *cl,
351 const struct cx_allocator_s *allocator,
352 cx_compare_func comparator,
353 size_t elem_size
354 );
355 335
356 /** 336 /**
357 * Returns the number of elements currently stored in the list. 337 * Returns the number of elements currently stored in the list.
358 * 338 *
359 * @param list the list 339 * @param list the list
360 * @return the number of currently stored elements 340 * @return the number of currently stored elements
361 */ 341 */
362 cx_attr_nonnull 342 cx_attr_nonnull
363 static inline size_t cxListSize(const CxList *list) { 343 CX_EXPORT size_t cxListSize(const CxList *list);
364 return list->collection.size;
365 }
366 344
367 /** 345 /**
368 * Adds an item to the end of the list. 346 * Adds an item to the end of the list.
369 * 347 *
370 * @param list the list 348 * @param list the list
373 * @retval non-zero memory allocation failure 351 * @retval non-zero memory allocation failure
374 * @see cxListAddArray() 352 * @see cxListAddArray()
375 * @see cxListEmplace() 353 * @see cxListEmplace()
376 */ 354 */
377 cx_attr_nonnull 355 cx_attr_nonnull
378 static inline int cxListAdd( 356 CX_EXPORT int cxListAdd(CxList *list, const void *elem);
379 CxList *list,
380 const void *elem
381 ) {
382 list->collection.sorted = false;
383 return list->cl->insert_element(list, list->collection.size, elem) == NULL;
384 }
385 357
386 /** 358 /**
387 * Adds multiple items to the end of the list. 359 * Adds multiple items to the end of the list.
388 * 360 *
389 * This method is more efficient than invoking cxListAdd() multiple times. 361 * This method is more efficient than invoking cxListAdd() multiple times.
390 * 362 *
391 * If there is not enough memory to add all elements, the returned value is 363 * If there is not enough memory to add all elements, the returned value is
392 * less than @p n. 364 * less than @p n.
393 * 365 *
394 * If this list is storing pointers instead of objects @p array is expected to 366 * If this list is storing pointers instead of objects, @p array is expected to
395 * be an array of pointers. 367 * be an array of pointers.
396 * 368 *
397 * @param list the list 369 * @param list the list
398 * @param array a pointer to the elements to add 370 * @param array a pointer to the elements to add
399 * @param n the number of elements to add 371 * @param n the number of elements to add
400 * @return the number of added elements 372 * @return the number of added elements
401 */ 373 * @see cxListEmplaceArray()
402 cx_attr_nonnull 374 */
403 static inline size_t cxListAddArray( 375 cx_attr_nonnull
404 CxList *list, 376 CX_EXPORT size_t cxListAddArray(CxList *list, const void *array, size_t n);
405 const void *array,
406 size_t n
407 ) {
408 list->collection.sorted = false;
409 return list->cl->insert_array(list, list->collection.size, array, n);
410 }
411 377
412 /** 378 /**
413 * Inserts an item at the specified index. 379 * Inserts an item at the specified index.
414 * 380 *
415 * If @p index equals the list @c size, this is effectively cxListAdd(). 381 * If the @p index equals the list @c size, this is effectively cxListAdd().
416 * 382 *
417 * @param list the list 383 * @param list the list
418 * @param index the index the element shall have 384 * @param index the index the element shall have
419 * @param elem a pointer to the element to add 385 * @param elem a pointer to the element to add
420 * @retval zero success 386 * @retval zero success
422 * @see cxListInsertAfter() 388 * @see cxListInsertAfter()
423 * @see cxListInsertBefore() 389 * @see cxListInsertBefore()
424 * @see cxListEmplaceAt() 390 * @see cxListEmplaceAt()
425 */ 391 */
426 cx_attr_nonnull 392 cx_attr_nonnull
427 static inline int cxListInsert( 393 CX_EXPORT int cxListInsert(CxList *list, size_t index, const void *elem);
428 CxList *list,
429 size_t index,
430 const void *elem
431 ) {
432 list->collection.sorted = false;
433 return list->cl->insert_element(list, index, elem) == NULL;
434 }
435 394
436 /** 395 /**
437 * Allocates memory for an element at the specified index and returns a pointer to that memory. 396 * Allocates memory for an element at the specified index and returns a pointer to that memory.
438 * 397 *
439 * @remark When the list is storing pointers, this will return a @c void**. 398 * @remark When the list is storing pointers, this will return a @c void**.
440 * 399 *
441 * @param list the list 400 * @param list the list
442 * @param index the index where to emplace the element 401 * @param index the index where to emplace the element
443 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds 402 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds
444 * @see cxListEmplace() 403 * @see cxListEmplace()
404 * @see cxListEmplaceArrayAt()
445 * @see cxListInsert() 405 * @see cxListInsert()
446 */ 406 */
447 cx_attr_nonnull 407 cx_attr_nonnull
448 static inline void *cxListEmplaceAt(CxList *list, size_t index) { 408 CX_EXPORT void *cxListEmplaceAt(CxList *list, size_t index);
449 list->collection.sorted = false;
450 return list->cl->insert_element(list, index, NULL);
451 }
452
453 409
454 /** 410 /**
455 * Allocates memory for an element at the end of the list and returns a pointer to that memory. 411 * Allocates memory for an element at the end of the list and returns a pointer to that memory.
456 * 412 *
457 * @remark When the list is storing pointers, this will return a @c void**. 413 * @remark When the list is storing pointers, this will return a @c void**.
460 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds 416 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds
461 * @see cxListEmplaceAt() 417 * @see cxListEmplaceAt()
462 * @see cxListAdd() 418 * @see cxListAdd()
463 */ 419 */
464 cx_attr_nonnull 420 cx_attr_nonnull
465 static inline void *cxListEmplace(CxList *list) { 421 CX_EXPORT void *cxListEmplace(CxList *list);
466 list->collection.sorted = false; 422
467 return list->cl->insert_element(list, list->collection.size, NULL); 423 /**
468 } 424 * Allocates memory for multiple elements and returns an iterator.
425 *
426 * The iterator will only iterate over the successfully allocated elements.
427 * The @c elem_count attribute is set to that number, and the @c index attribute
428 * will range from zero to @c elem_count minus one.
429 *
430 * @remark When the list is storing pointers, the iterator will iterate over
431 * the @c void** elements.
432 *
433 * @param list the list
434 * @param index the index where to insert the new data
435 * @param n the number of elements for which to allocate the memory
436 * @return an iterator, iterating over the new memory
437 * @see cxListEmplaceAt()
438 * @see cxListInsertArray()
439 */
440 cx_attr_nonnull
441 CX_EXPORT CxIterator cxListEmplaceArrayAt(CxList *list, size_t index, size_t n);
442
443 /**
444 * Allocates memory for multiple elements and returns an iterator.
445 *
446 * The iterator will only iterate over the successfully allocated elements.
447 * The @c elem_count attribute is set to that number, and the @c index attribute
448 * will range from zero to @c elem_count minus one.
449 *
450 * @remark When the list is storing pointers, the iterator will iterate over
451 * the @c void** elements.
452 *
453 * @param list the list
454 * @param n the number of elements for which to allocate the memory
455 * @return an iterator, iterating over the new memory
456 * @see cxListEmplace()
457 * @see cxListAddArray()
458 */
459 cx_attr_nonnull
460 CX_EXPORT CxIterator cxListEmplaceArray(CxList *list, size_t n);
469 461
470 /** 462 /**
471 * Inserts an item into a sorted list. 463 * Inserts an item into a sorted list.
472 * 464 *
473 * If the list is not sorted already, the behavior is undefined. 465 * If the list is not sorted already, the behavior is undefined.
476 * @param elem a pointer to the element to add 468 * @param elem a pointer to the element to add
477 * @retval zero success 469 * @retval zero success
478 * @retval non-zero memory allocation failure 470 * @retval non-zero memory allocation failure
479 */ 471 */
480 cx_attr_nonnull 472 cx_attr_nonnull
481 static inline int cxListInsertSorted( 473 CX_EXPORT int cxListInsertSorted(CxList *list, const void *elem);
482 CxList *list, 474
483 const void *elem 475 /**
484 ) { 476 * Inserts an item into a list if it does not exist.
485 list->collection.sorted = true; // guaranteed by definition 477 *
486 const void *data = list->collection.store_pointer ? &elem : elem; 478 * If the list is not sorted already, this function will check all elements
487 return list->cl->insert_sorted(list, data, 1) == 0; 479 * and append the new element when it was not found.
488 } 480 * It is strongly recommended to use this function only on sorted lists, where
481 * the element, if it is not contained, is inserted at the correct position.
482 *
483 * @param list the list
484 * @param elem a pointer to the element to add
485 * @retval zero success (also when the element was already in the list)
486 * @retval non-zero memory allocation failure
487 */
488 cx_attr_nonnull
489 CX_EXPORT int cxListInsertUnique(CxList *list, const void *elem);
489 490
490 /** 491 /**
491 * Inserts multiple items to the list at the specified index. 492 * Inserts multiple items to the list at the specified index.
492 * If @p index equals the list size, this is effectively cxListAddArray(). 493 * If the @p index equals the list size, this is effectively cxListAddArray().
493 * 494 *
494 * This method is usually more efficient than invoking cxListInsert() 495 * This method is usually more efficient than invoking cxListInsert()
495 * multiple times. 496 * multiple times.
496 * 497 *
497 * If there is not enough memory to add all elements, the returned value is 498 * If there is not enough memory to add all elements, the returned value is
498 * less than @p n. 499 * less than @p n.
499 * 500 *
500 * If this list is storing pointers instead of objects @p array is expected to 501 * If this list is storing pointers instead of objects, @p array is expected to
501 * be an array of pointers. 502 * be an array of pointers.
502 * 503 *
503 * @param list the list 504 * @param list the list
504 * @param index the index where to add the elements 505 * @param index the index where to add the elements
505 * @param array a pointer to the elements to add 506 * @param array a pointer to the elements to add
506 * @param n the number of elements to add 507 * @param n the number of elements to add
507 * @return the number of added elements 508 * @return the number of added elements
508 */ 509 * @see cxListEmplaceArrayAt()
509 cx_attr_nonnull 510 */
510 static inline size_t cxListInsertArray( 511 cx_attr_nonnull
511 CxList *list, 512 CX_EXPORT size_t cxListInsertArray(CxList *list, size_t index, const void *array, size_t n);
512 size_t index,
513 const void *array,
514 size_t n
515 ) {
516 list->collection.sorted = false;
517 return list->cl->insert_array(list, index, array, n);
518 }
519 513
520 /** 514 /**
521 * Inserts a sorted array into a sorted list. 515 * Inserts a sorted array into a sorted list.
522 * 516 *
523 * This method is usually more efficient than inserting each element separately, 517 * This method is usually more efficient than inserting each element separately
524 * because consecutive chunks of sorted data are inserted in one pass. 518 * because consecutive chunks of sorted data are inserted in one pass.
525 * 519 *
526 * If there is not enough memory to add all elements, the returned value is 520 * If there is not enough memory to add all elements, the returned value is
527 * less than @p n. 521 * less than @p n.
528 * 522 *
529 * If this list is storing pointers instead of objects @p array is expected to 523 * If this list is storing pointers instead of objects, @p array is expected to
530 * be an array of pointers. 524 * be an array of pointers.
531 * 525 *
532 * If the list is not sorted already, the behavior is undefined. 526 * If the list is not sorted already, the behavior is undefined.
533 * 527 *
534 * @param list the list 528 * @param list the list
535 * @param array a pointer to the elements to add 529 * @param array a pointer to the elements to add
536 * @param n the number of elements to add 530 * @param n the number of elements to add
537 * @return the number of added elements 531 * @return the number of added elements
538 */ 532 */
539 cx_attr_nonnull 533 cx_attr_nonnull
540 static inline size_t cxListInsertSortedArray( 534 CX_EXPORT size_t cxListInsertSortedArray(CxList *list, const void *array, size_t n);
541 CxList *list, 535
542 const void *array, 536 /**
543 size_t n 537 * Inserts an array into a list, skipping duplicates.
544 ) { 538 *
545 list->collection.sorted = true; // guaranteed by definition 539 * The @p list does not need to be sorted (in contrast to cxListInsertSortedArray()).
546 return list->cl->insert_sorted(list, array, n); 540 * But it is strongly recommended to use this function only on sorted lists,
547 } 541 * because otherwise it will fall back to an inefficient algorithm which inserts
542 * all elements one by one.
543 * If the @p list is not sorted, the @p array also does not need to be sorted.
544 * But when the @p list is sorted, the @p array must also be sorted.
545 *
546 * This method is usually more efficient than inserting each element separately
547 * because consecutive chunks of sorted data are inserted in one pass.
548 *
549 * If there is not enough memory to add all elements, the returned value is
550 * less than @p n.
551 *
552 * @note The return value of this function denotes the number of elements
553 * from the @p sorted_data that are definitely contained in the list after
554 * completing the call. It is @em not the number of elements that were newly
555 * inserted. That means, when no error occurred, the return value should
556 * be @p n.
557 *
558 * If this list is storing pointers instead of objects @p array is expected to
559 * be an array of pointers.
560 *
561 * @param list the list
562 * @param array a pointer to the elements to add
563 * @param n the number of elements to add
564 * @return the number of added elements
565 *
566 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call
567 */
568 cx_attr_nonnull
569 CX_EXPORT size_t cxListInsertUniqueArray(CxList *list, const void *array, size_t n);
548 570
549 /** 571 /**
550 * Inserts an element after the current location of the specified iterator. 572 * Inserts an element after the current location of the specified iterator.
551 * 573 *
552 * The used iterator remains operational, but all other active iterators should 574 * The used iterator remains operational, but all other active iterators should
561 * @retval non-zero memory allocation failure 583 * @retval non-zero memory allocation failure
562 * @see cxListInsert() 584 * @see cxListInsert()
563 * @see cxListInsertBefore() 585 * @see cxListInsertBefore()
564 */ 586 */
565 cx_attr_nonnull 587 cx_attr_nonnull
566 static inline int cxListInsertAfter( 588 CX_EXPORT int cxListInsertAfter(CxIterator *iter, const void *elem);
567 CxIterator *iter,
568 const void *elem
569 ) {
570 CxList* list = (CxList*)iter->src_handle.m;
571 list->collection.sorted = false;
572 return list->cl->insert_iter(iter, elem, 0);
573 }
574 589
575 /** 590 /**
576 * Inserts an element before the current location of the specified iterator. 591 * Inserts an element before the current location of the specified iterator.
577 * 592 *
578 * The used iterator remains operational, but all other active iterators should 593 * The used iterator remains operational, but all other active iterators should
587 * @retval non-zero memory allocation failure 602 * @retval non-zero memory allocation failure
588 * @see cxListInsert() 603 * @see cxListInsert()
589 * @see cxListInsertAfter() 604 * @see cxListInsertAfter()
590 */ 605 */
591 cx_attr_nonnull 606 cx_attr_nonnull
592 static inline int cxListInsertBefore( 607 CX_EXPORT int cxListInsertBefore(CxIterator *iter, const void *elem);
593 CxIterator *iter,
594 const void *elem
595 ) {
596 CxList* list = (CxList*)iter->src_handle.m;
597 list->collection.sorted = false;
598 return list->cl->insert_iter(iter, elem, 1);
599 }
600 608
601 /** 609 /**
602 * Removes the element at the specified index. 610 * Removes the element at the specified index.
603 * 611 *
604 * If an element destructor function is specified, it is called before 612 * If an element destructor function is specified, it is called before
608 * @param index the index of the element 616 * @param index the index of the element
609 * @retval zero success 617 * @retval zero success
610 * @retval non-zero index out of bounds 618 * @retval non-zero index out of bounds
611 */ 619 */
612 cx_attr_nonnull 620 cx_attr_nonnull
613 static inline int cxListRemove( 621 CX_EXPORT int cxListRemove(CxList *list, size_t index);
614 CxList *list,
615 size_t index
616 ) {
617 return list->cl->remove(list, index, 1, NULL) == 0;
618 }
619 622
620 /** 623 /**
621 * Removes and returns the element at the specified index. 624 * Removes and returns the element at the specified index.
622 * 625 *
623 * No destructor is called, and instead the element is copied to the 626 * No destructor is called, and instead the element is copied to the
628 * @param index the index of the element 631 * @param index the index of the element
629 * @param targetbuf a buffer where to copy the element 632 * @param targetbuf a buffer where to copy the element
630 * @retval zero success 633 * @retval zero success
631 * @retval non-zero index out of bounds 634 * @retval non-zero index out of bounds
632 */ 635 */
633 cx_attr_nonnull 636 cx_attr_nonnull cx_attr_access_w(3)
634 cx_attr_access_w(3) 637 CX_EXPORT int cxListRemoveAndGet(CxList *list, size_t index, void *targetbuf);
635 static inline int cxListRemoveAndGet(
636 CxList *list,
637 size_t index,
638 void *targetbuf
639 ) {
640 return list->cl->remove(list, index, 1, targetbuf) == 0;
641 }
642 638
643 /** 639 /**
644 * Removes and returns the first element of the list. 640 * Removes and returns the first element of the list.
645 * 641 *
646 * No destructor is called, and instead the element is copied to the 642 * No destructor is called, and instead the element is copied to the
648 * If the list is storing pointers, only the pointer is copied to @p targetbuf. 644 * If the list is storing pointers, only the pointer is copied to @p targetbuf.
649 * 645 *
650 * @param list the list 646 * @param list the list
651 * @param targetbuf a buffer where to copy the element 647 * @param targetbuf a buffer where to copy the element
652 * @retval zero success 648 * @retval zero success
653 * @retval non-zero list is empty 649 * @retval non-zero the list is empty
654 * @see cxListPopFront() 650 * @see cxListPopFront()
655 * @see cxListRemoveAndGetLast() 651 * @see cxListRemoveAndGetLast()
656 */ 652 */
657 cx_attr_nonnull 653 cx_attr_nonnull cx_attr_access_w(2)
658 cx_attr_access_w(2) 654 CX_EXPORT int cxListRemoveAndGetFirst(CxList *list, void *targetbuf);
659 static inline int cxListRemoveAndGetFirst(
660 CxList *list,
661 void *targetbuf
662 ) {
663 return list->cl->remove(list, 0, 1, targetbuf) == 0;
664 }
665 655
666 /** 656 /**
667 * Removes and returns the first element of the list. 657 * Removes and returns the first element of the list.
668 * 658 *
669 * Alias for cxListRemoveAndGetFirst(). 659 * Alias for cxListRemoveAndGetFirst().
673 * If the list is storing pointers, only the pointer is copied to @p targetbuf. 663 * If the list is storing pointers, only the pointer is copied to @p targetbuf.
674 * 664 *
675 * @param list (@c CxList*) the list 665 * @param list (@c CxList*) the list
676 * @param targetbuf (@c void*) a buffer where to copy the element 666 * @param targetbuf (@c void*) a buffer where to copy the element
677 * @retval zero success 667 * @retval zero success
678 * @retval non-zero list is empty 668 * @retval non-zero the list is empty
679 * @see cxListRemoveAndGetFirst() 669 * @see cxListRemoveAndGetFirst()
680 * @see cxListPop() 670 * @see cxListPop()
681 */ 671 */
682 #define cxListPopFront(list, targetbuf) cxListRemoveAndGetFirst((list), (targetbuf)) 672 #define cxListPopFront(list, targetbuf) cxListRemoveAndGetFirst((list), (targetbuf))
683 673
690 * If the list is storing pointers, only the pointer is copied to @p targetbuf. 680 * If the list is storing pointers, only the pointer is copied to @p targetbuf.
691 * 681 *
692 * @param list the list 682 * @param list the list
693 * @param targetbuf a buffer where to copy the element 683 * @param targetbuf a buffer where to copy the element
694 * @retval zero success 684 * @retval zero success
695 * @retval non-zero list is empty 685 * @retval non-zero the list is empty
696 */ 686 */
697 cx_attr_nonnull 687 cx_attr_nonnull cx_attr_access_w(2)
698 cx_attr_access_w(2) 688 CX_EXPORT int cxListRemoveAndGetLast(CxList *list, void *targetbuf);
699 static inline int cxListRemoveAndGetLast(
700 CxList *list,
701 void *targetbuf
702 ) {
703 // note: index may wrap - member function will catch that
704 return list->cl->remove(list, list->collection.size - 1, 1, targetbuf) == 0;
705 }
706 689
707 /** 690 /**
708 * Removes and returns the last element of the list. 691 * Removes and returns the last element of the list.
709 * 692 *
710 * Alias for cxListRemoveAndGetLast(). 693 * Alias for cxListRemoveAndGetLast().
714 * If the list is storing pointers, only the pointer is copied to @p targetbuf. 697 * If the list is storing pointers, only the pointer is copied to @p targetbuf.
715 * 698 *
716 * @param list (@c CxList*) the list 699 * @param list (@c CxList*) the list
717 * @param targetbuf (@c void*) a buffer where to copy the element 700 * @param targetbuf (@c void*) a buffer where to copy the element
718 * @retval zero success 701 * @retval zero success
719 * @retval non-zero list is empty 702 * @retval non-zero the list is empty
720 * @see cxListRemoveAndGetLast() 703 * @see cxListRemoveAndGetLast()
721 * @see cxListPopFront() 704 * @see cxListPopFront()
722 */ 705 */
723 #define cxListPop(list, targetbuf) cxListRemoveAndGetLast((list), (targetbuf)) 706 #define cxListPop(list, targetbuf) cxListRemoveAndGetLast((list), (targetbuf))
724 707
736 * @param index the index of the element 719 * @param index the index of the element
737 * @param num the number of elements to remove 720 * @param num the number of elements to remove
738 * @return the actual number of removed elements 721 * @return the actual number of removed elements
739 */ 722 */
740 cx_attr_nonnull 723 cx_attr_nonnull
741 static inline size_t cxListRemoveArray( 724 CX_EXPORT size_t cxListRemoveArray(CxList *list, size_t index, size_t num);
742 CxList *list,
743 size_t index,
744 size_t num
745 ) {
746 return list->cl->remove(list, index, num, NULL);
747 }
748 725
749 /** 726 /**
750 * Removes and returns multiple elements starting at the specified index. 727 * Removes and returns multiple elements starting at the specified index.
751 * 728 *
752 * No destructor is called, and instead the elements are copied to the 729 * No destructor is called, and instead the elements are copied to the
757 * @param index the index of the element 734 * @param index the index of the element
758 * @param num the number of elements to remove 735 * @param num the number of elements to remove
759 * @param targetbuf a buffer where to copy the elements 736 * @param targetbuf a buffer where to copy the elements
760 * @return the actual number of removed elements 737 * @return the actual number of removed elements
761 */ 738 */
762 cx_attr_nonnull 739 cx_attr_nonnull cx_attr_access_w(4)
763 cx_attr_access_w(4) 740 CX_EXPORT size_t cxListRemoveArrayAndGet(CxList *list, size_t index, size_t num, void *targetbuf);
764 static inline size_t cxListRemoveArrayAndGet(
765 CxList *list,
766 size_t index,
767 size_t num,
768 void *targetbuf
769 ) {
770 return list->cl->remove(list, index, num, targetbuf);
771 }
772 741
773 /** 742 /**
774 * Removes all elements from this list. 743 * Removes all elements from this list.
775 * 744 *
776 * If element destructor functions are specified, they are called for each 745 * If element destructor functions are specified, they are called for each
777 * element before removing them. 746 * element before removing them.
778 * 747 *
779 * @param list the list 748 * @param list the list
780 */ 749 */
781 cx_attr_nonnull 750 cx_attr_nonnull
782 static inline void cxListClear(CxList *list) { 751 CX_EXPORT void cxListClear(CxList *list);
783 list->collection.sorted = true; // empty lists are always sorted
784 list->cl->clear(list);
785 }
786 752
787 /** 753 /**
788 * Swaps two items in the list. 754 * Swaps two items in the list.
789 * 755 *
790 * Implementations should only allocate temporary memory for the swap if 756 * Implementations should only allocate temporary memory for the swap if
796 * @retval zero success 762 * @retval zero success
797 * @retval non-zero one of the indices is out of bounds, 763 * @retval non-zero one of the indices is out of bounds,
798 * or the swap needed extra memory, but allocation failed 764 * or the swap needed extra memory, but allocation failed
799 */ 765 */
800 cx_attr_nonnull 766 cx_attr_nonnull
801 static inline int cxListSwap( 767 CX_EXPORT int cxListSwap(CxList *list, size_t i, size_t j);
802 CxList *list,
803 size_t i,
804 size_t j
805 ) {
806 list->collection.sorted = false;
807 return list->cl->swap(list, i, j);
808 }
809 768
810 /** 769 /**
811 * Returns a pointer to the element at the specified index. 770 * Returns a pointer to the element at the specified index.
812 * 771 *
813 * If the list is storing pointers, returns the pointer stored at the specified index. 772 * If the list is storing pointers, returns the pointer stored at the specified index.
815 * @param list the list 774 * @param list the list
816 * @param index the index of the element 775 * @param index the index of the element
817 * @return a pointer to the element or @c NULL if the index is out of bounds 776 * @return a pointer to the element or @c NULL if the index is out of bounds
818 */ 777 */
819 cx_attr_nonnull 778 cx_attr_nonnull
820 static inline void *cxListAt( 779 CX_EXPORT void *cxListAt(const CxList *list, size_t index);
821 const CxList *list,
822 size_t index
823 ) {
824 return list->cl->at(list, index);
825 }
826 780
827 /** 781 /**
828 * Returns a pointer to the first element. 782 * Returns a pointer to the first element.
829 * 783 *
830 * If the list is storing pointers, returns the first pointer stored in the list. 784 * If the list is storing pointers, returns the first pointer stored in the list.
831 * 785 *
832 * @param list the list 786 * @param list the list
833 * @return a pointer to the first element or @c NULL if the list is empty 787 * @return a pointer to the first element or @c NULL if the list is empty
834 */ 788 */
835 cx_attr_nonnull 789 cx_attr_nonnull
836 static inline void *cxListFirst(const CxList *list) { 790 CX_EXPORT void *cxListFirst(const CxList *list);
837 return list->cl->at(list, 0);
838 }
839 791
840 /** 792 /**
841 * Returns a pointer to the last element. 793 * Returns a pointer to the last element.
842 * 794 *
843 * If the list is storing pointers, returns the last pointer stored in the list. 795 * If the list is storing pointers, returns the last pointer stored in the list.
844 * 796 *
845 * @param list the list 797 * @param list the list
846 * @return a pointer to the last element or @c NULL if the list is empty 798 * @return a pointer to the last element or @c NULL if the list is empty
847 */ 799 */
848 cx_attr_nonnull 800 cx_attr_nonnull
849 static inline void *cxListLast(const CxList *list) { 801 CX_EXPORT void *cxListLast(const CxList *list);
850 return list->cl->at(list, list->collection.size - 1); 802
851 } 803 /**
852 804 * Sets the element at the specified index in the list.
853 /** 805 *
854 * Sets the element at the specified index in the list 806 * This overwrites the element in-place without calling any destructor
807 * on the overwritten element.
855 * 808 *
856 * @param list the list to set the element in 809 * @param list the list to set the element in
857 * @param index the index to set the element at 810 * @param index the index to set the element at
858 * @param elem element to set 811 * @param elem element to set
859 * @retval zero on success 812 * @retval zero on success
860 * @retval non-zero when index is out of bounds 813 * @retval non-zero when index is out of bounds
861 */ 814 */
862 cx_attr_nonnull 815 cx_attr_nonnull
863 cx_attr_export 816 CX_EXPORT int cxListSet(CxList *list, size_t index, const void *elem);
864 int cxListSet(
865 CxList *list,
866 size_t index,
867 const void *elem
868 );
869 817
870 /** 818 /**
871 * Returns an iterator pointing to the item at the specified index. 819 * Returns an iterator pointing to the item at the specified index.
872 * 820 *
873 * The returned iterator is position-aware. 821 * The returned iterator is position-aware.
874 * 822 *
875 * If the index is out of range, a past-the-end iterator will be returned. 823 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned.
876 * 824 *
877 * @param list the list 825 * @param list the list
878 * @param index the index where the iterator shall point at 826 * @param index the index where the iterator shall point at
879 * @return a new iterator 827 * @return a new iterator
880 */ 828 */
881 cx_attr_nonnull
882 cx_attr_nodiscard 829 cx_attr_nodiscard
883 static inline CxIterator cxListIteratorAt( 830 CX_EXPORT CxIterator cxListIteratorAt(const CxList *list, size_t index);
884 const CxList *list,
885 size_t index
886 ) {
887 return list->cl->iterator(list, index, false);
888 }
889 831
890 /** 832 /**
891 * Returns a backwards iterator pointing to the item at the specified index. 833 * Returns a backwards iterator pointing to the item at the specified index.
892 * 834 *
893 * The returned iterator is position-aware. 835 * The returned iterator is position-aware.
894 * 836 *
895 * If the index is out of range, a past-the-end iterator will be returned. 837 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned.
896 * 838 *
897 * @param list the list 839 * @param list the list
898 * @param index the index where the iterator shall point at 840 * @param index the index where the iterator shall point at
899 * @return a new iterator 841 * @return a new iterator
900 */ 842 */
901 cx_attr_nonnull
902 cx_attr_nodiscard 843 cx_attr_nodiscard
903 static inline CxIterator cxListBackwardsIteratorAt( 844 CX_EXPORT CxIterator cxListBackwardsIteratorAt(const CxList *list, size_t index);
904 const CxList *list, 845
905 size_t index 846 /**
906 ) { 847 * Returns an iterator pointing to the first item of the list.
907 return list->cl->iterator(list, index, true);
908 }
909
910 /**
911 * Returns a mutating iterator pointing to the item at the specified index.
912 * 848 *
913 * The returned iterator is position-aware. 849 * The returned iterator is position-aware.
914 * 850 *
915 * If the index is out of range, a past-the-end iterator will be returned. 851 * If the list is empty or @c NULL, a past-the-end iterator will be returned.
916 * 852 *
917 * @param list the list 853 * @param list the list
918 * @param index the index where the iterator shall point at
919 * @return a new iterator 854 * @return a new iterator
920 */ 855 */
921 cx_attr_nonnull
922 cx_attr_nodiscard 856 cx_attr_nodiscard
923 cx_attr_export 857 CX_EXPORT CxIterator cxListIterator(const CxList *list);
924 CxIterator cxListMutIteratorAt( 858
925 CxList *list, 859 /**
926 size_t index 860 * Returns a backwards iterator pointing to the last item of the list.
927 );
928
929 /**
930 * Returns a mutating backwards iterator pointing to the item at the
931 * specified index.
932 * 861 *
933 * The returned iterator is position-aware. 862 * The returned iterator is position-aware.
934 * 863 *
935 * If the index is out of range, a past-the-end iterator will be returned. 864 * If the list is empty or @c NULL, a past-the-end iterator will be returned.
936 * 865 *
937 * @param list the list 866 * @param list the list
938 * @param index the index where the iterator shall point at
939 * @return a new iterator 867 * @return a new iterator
940 */ 868 */
941 cx_attr_nonnull
942 cx_attr_nodiscard 869 cx_attr_nodiscard
943 cx_attr_export 870 CX_EXPORT CxIterator cxListBackwardsIterator(const CxList *list);
944 CxIterator cxListMutBackwardsIteratorAt(
945 CxList *list,
946 size_t index
947 );
948
949 /**
950 * Returns an iterator pointing to the first item of the list.
951 *
952 * The returned iterator is position-aware.
953 *
954 * If the list is empty or @c NULL, a past-the-end iterator will be returned.
955 *
956 * @param list the list
957 * @return a new iterator
958 */
959 cx_attr_nodiscard
960 static inline CxIterator cxListIterator(const CxList *list) {
961 if (list == NULL) list = cxEmptyList;
962 return list->cl->iterator(list, 0, false);
963 }
964
965 /**
966 * Returns a mutating iterator pointing to the first item of the list.
967 *
968 * The returned iterator is position-aware.
969 *
970 * If the list is empty or @c NULL, a past-the-end iterator will be returned.
971 *
972 * @param list the list
973 * @return a new iterator
974 */
975 cx_attr_nodiscard
976 static inline CxIterator cxListMutIterator(CxList *list) {
977 if (list == NULL) list = cxEmptyList;
978 return cxListMutIteratorAt(list, 0);
979 }
980
981
982 /**
983 * Returns a backwards iterator pointing to the last item of the list.
984 *
985 * The returned iterator is position-aware.
986 *
987 * If the list is empty or @c NULL, a past-the-end iterator will be returned.
988 *
989 * @param list the list
990 * @return a new iterator
991 */
992 cx_attr_nodiscard
993 static inline CxIterator cxListBackwardsIterator(const CxList *list) {
994 if (list == NULL) list = cxEmptyList;
995 return list->cl->iterator(list, list->collection.size - 1, true);
996 }
997
998 /**
999 * Returns a mutating backwards iterator pointing to the last item of the list.
1000 *
1001 * The returned iterator is position-aware.
1002 *
1003 * If the list is empty or @c NULL, a past-the-end iterator will be returned.
1004 *
1005 * @param list the list
1006 * @return a new iterator
1007 */
1008 cx_attr_nodiscard
1009 static inline CxIterator cxListMutBackwardsIterator(CxList *list) {
1010 if (list == NULL) list = cxEmptyList;
1011 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1);
1012 }
1013 871
1014 /** 872 /**
1015 * Returns the index of the first element that equals @p elem. 873 * Returns the index of the first element that equals @p elem.
1016 * 874 *
1017 * Determining equality is performed by the list's comparator function. 875 * Determining equality is performed by the list's comparator function.
1020 * @param elem the element to find 878 * @param elem the element to find
1021 * @return the index of the element or the size of the list when the element is not found 879 * @return the index of the element or the size of the list when the element is not found
1022 * @see cxListIndexValid() 880 * @see cxListIndexValid()
1023 * @see cxListContains() 881 * @see cxListContains()
1024 */ 882 */
1025 cx_attr_nonnull 883 cx_attr_nonnull cx_attr_nodiscard
1026 cx_attr_nodiscard 884 CX_EXPORT size_t cxListFind(const CxList *list, const void *elem);
1027 static inline size_t cxListFind( 885
1028 const CxList *list, 886 /**
1029 const void *elem 887 * Checks if the list contains the specified element.
1030 ) {
1031 return list->cl->find_remove((CxList*)list, elem, false);
1032 }
1033
1034 /**
1035 * Checks, if the list contains the specified element.
1036 * 888 *
1037 * The elements are compared with the list's comparator function. 889 * The elements are compared with the list's comparator function.
1038 * 890 *
1039 * @param list the list 891 * @param list the list
1040 * @param elem the element to find 892 * @param elem the element to find
1041 * @retval true if the element is contained 893 * @retval true if the element is contained
1042 * @retval false if the element is not contained 894 * @retval false if the element is not contained
1043 * @see cxListFind() 895 * @see cxListFind()
1044 */ 896 */
1045 cx_attr_nonnull 897 cx_attr_nonnull cx_attr_nodiscard
1046 cx_attr_nodiscard 898 CX_EXPORT bool cxListContains(const CxList* list, const void* elem);
1047 static inline bool cxListContains(
1048 const CxList* list,
1049 const void* elem
1050 ) {
1051 return list->cl->find_remove((CxList*)list, elem, false) < list->collection.size;
1052 }
1053 899
1054 /** 900 /**
1055 * Checks if the specified index is within bounds. 901 * Checks if the specified index is within bounds.
1056 * 902 *
1057 * @param list the list 903 * @param list the list
1058 * @param index the index 904 * @param index the index
1059 * @retval true if the index is within bounds 905 * @retval true if the index is within bounds
1060 * @retval false if the index is out of bounds 906 * @retval false if the index is out of bounds
1061 */ 907 */
1062 cx_attr_nonnull 908 cx_attr_nonnull cx_attr_nodiscard
1063 cx_attr_nodiscard 909 CX_EXPORT bool cxListIndexValid(const CxList *list, size_t index);
1064 static inline bool cxListIndexValid(const CxList *list, size_t index) {
1065 return index < list->collection.size;
1066 }
1067 910
1068 /** 911 /**
1069 * Removes and returns the index of the first element that equals @p elem. 912 * Removes and returns the index of the first element that equals @p elem.
1070 * 913 *
1071 * Determining equality is performed by the list's comparator function. 914 * Determining equality is performed by the list's comparator function.
1075 * @return the index of the now removed element or the list size 918 * @return the index of the now removed element or the list size
1076 * when the element is not found or could not be removed 919 * when the element is not found or could not be removed
1077 * @see cxListIndexValid() 920 * @see cxListIndexValid()
1078 */ 921 */
1079 cx_attr_nonnull 922 cx_attr_nonnull
1080 static inline size_t cxListFindRemove( 923 CX_EXPORT size_t cxListFindRemove(CxList *list, const void *elem);
1081 CxList *list,
1082 const void *elem
1083 ) {
1084 return list->cl->find_remove(list, elem, true);
1085 }
1086 924
1087 /** 925 /**
1088 * Sorts the list. 926 * Sorts the list.
1089 * 927 *
1090 * @remark The underlying sort algorithm is implementation defined. 928 * @remark The underlying sort algorithm is implementation defined.
1091 * 929 *
1092 * @param list the list 930 * @param list the list
1093 */ 931 */
1094 cx_attr_nonnull 932 cx_attr_nonnull
1095 static inline void cxListSort(CxList *list) { 933 CX_EXPORT void cxListSort(CxList *list);
1096 if (list->collection.sorted) return;
1097 list->cl->sort(list);
1098 list->collection.sorted = true;
1099 }
1100 934
1101 /** 935 /**
1102 * Reverses the order of the items. 936 * Reverses the order of the items.
1103 * 937 *
1104 * @param list the list 938 * @param list the list
1105 */ 939 */
1106 cx_attr_nonnull 940 cx_attr_nonnull
1107 static inline void cxListReverse(CxList *list) { 941 CX_EXPORT void cxListReverse(CxList *list);
1108 // still sorted, but not according to the cmp_func
1109 list->collection.sorted = false;
1110 list->cl->reverse(list);
1111 }
1112 942
1113 /** 943 /**
1114 * Compares a list to another list of the same type. 944 * Compares a list to another list of the same type.
1115 * 945 *
1116 * First, the list sizes are compared. 946 * First, the list sizes are compared.
1117 * If they match, the lists are compared element-wise. 947 * If they match, the lists are compared element-wise.
1118 * 948 *
1119 * @param list the list 949 * @param list the list
1120 * @param other the list to compare to 950 * @param other the list to compare to
1121 * @retval zero both lists are equal element wise 951 * @retval zero both lists are equal element wise
1122 * @retval negative the first list is smaller 952 * @retval negative the first list is smaller,
1123 * or the first non-equal element in the first list is smaller 953 * or the first non-equal element in the first list is smaller
1124 * @retval positive the first list is larger 954 * @retval positive the first list is larger
1125 * or the first non-equal element in the first list is larger 955 * or the first non-equal element in the first list is larger
1126 */ 956 */
1127 cx_attr_nonnull 957 cx_attr_nonnull cx_attr_nodiscard
1128 cx_attr_nodiscard 958 CX_EXPORT int cxListCompare(const CxList *list, const CxList *other);
1129 cx_attr_export
1130 int cxListCompare(
1131 const CxList *list,
1132 const CxList *other
1133 );
1134 959
1135 /** 960 /**
1136 * Deallocates the memory of the specified list structure. 961 * Deallocates the memory of the specified list structure.
1137 * 962 *
1138 * Also calls the content destructor functions for each element, if specified. 963 * Also calls the content destructor functions for each element, if specified.
1139 * 964 *
1140 * @param list the list which shall be freed 965 * @param list the list that shall be freed
1141 */ 966 */
1142 cx_attr_export 967 CX_EXPORT void cxListFree(CxList *list);
1143 void cxListFree(CxList *list); 968
1144 969
970 /**
971 * Performs a deep clone of one list into another.
972 *
973 * If the destination list already contains elements, the cloned elements
974 * are appended to that list.
975 *
976 * @attention If the cloned elements need to be destroyed by a destructor
977 * function, you must make sure that the destination list also uses this
978 * destructor function.
979 *
980 * @param dst the destination list
981 * @param src the source list
982 * @param clone_func the clone function for the elements
983 * @param clone_allocator the allocator that is passed to the clone function
984 * @param data optional additional data that is passed to the clone function
985 * @retval zero when all elements were successfully cloned
986 * @retval non-zero when an allocation error occurred
987 * @see cxListCloneSimple()
988 */
989 cx_attr_nonnull_arg(1, 2, 3)
990 CX_EXPORT int cxListClone(CxList *dst, const CxList *src,
991 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
992
993 /**
994 * Clones elements from a list only if they are not present in another list.
995 *
996 * If the @p minuend does not contain duplicates, this is equivalent to adding
997 * the set difference to the destination list.
998 *
999 * This function is optimized for the case when both the @p minuend and the
1000 * @p subtrahend are sorted.
1001 *
1002 * @param dst the destination list
1003 * @param minuend the list to subtract elements from
1004 * @param subtrahend the elements that shall be subtracted
1005 * @param clone_func the clone function for the elements
1006 * @param clone_allocator the allocator that is passed to the clone function
1007 * @param data optional additional data that is passed to the clone function
1008 * @retval zero when the elements were successfully cloned
1009 * @retval non-zero when an allocation error occurred
1010 * @see cxListDifferenceSimple()
1011 */
1012 cx_attr_nonnull_arg(1, 2, 3, 4)
1013 CX_EXPORT int cxListDifference(CxList *dst,
1014 const CxList *minuend, const CxList *subtrahend,
1015 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
1016
1017 /**
1018 * Clones elements from a list only if they are also present in another list.
1019 *
1020 * This function is optimized for the case when both the @p src and the
1021 * @p other list are sorted.
1022 *
1023 * If the destination list already contains elements, the intersection is appended
1024 * to that list.
1025 *
1026 * @param dst the destination list
1027 * @param src the list to clone the elements from
1028 * @param other the list to check the elements for existence
1029 * @param clone_func the clone function for the elements
1030 * @param clone_allocator the allocator that is passed to the clone function
1031 * @param data optional additional data that is passed to the clone function
1032 * @retval zero when the elements were successfully cloned
1033 * @retval non-zero when an allocation error occurred
1034 * @see cxListIntersectionSimple()
1035 */
1036 cx_attr_nonnull_arg(1, 2, 3, 4)
1037 CX_EXPORT int cxListIntersection(CxList *dst, const CxList *src, const CxList *other,
1038 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
1039
1040 /**
1041 * Performs a deep clone of one list into another, skipping duplicates.
1042 *
1043 * This function is optimized for the case when both the @p src and the
1044 * @p other list are sorted.
1045 * In that case, the union will also be sorted.
1046 *
1047 * If the destination list already contains elements, the union is appended
1048 * to that list. In that case the destination is not necessarily sorted.
1049 *
1050 * @param dst the destination list
1051 * @param src the primary source list
1052 * @param other the other list, where elements are only cloned from
1053 * when they are not in @p src
1054 * @param clone_func the clone function for the elements
1055 * @param clone_allocator the allocator that is passed to the clone function
1056 * @param data optional additional data that is passed to the clone function
1057 * @retval zero when the elements were successfully cloned
1058 * @retval non-zero when an allocation error occurred
1059 * @see cxListUnionSimple()
1060 */
1061 cx_attr_nonnull_arg(1, 2, 3, 4)
1062 CX_EXPORT int cxListUnion(CxList *dst, const CxList *src, const CxList *other,
1063 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
1064
1065 /**
1066 * Performs a shallow clone of one list into another.
1067 *
1068 * This function uses the default allocator, if needed, and performs
1069 * shallow clones with @c memcpy().
1070 *
1071 * If the destination list already contains elements, the cloned elements
1072 * are appended to that list.
1073 *
1074 * @attention If the cloned elements need to be destroyed by a destructor
1075 * function, you must make sure that the destination list also uses this
1076 * destructor function.
1077 *
1078 * @param dst the destination list
1079 * @param src the source list
1080 * @retval zero when all elements were successfully cloned
1081 * @retval non-zero when an allocation error occurred
1082 * @see cxListClone()
1083 */
1084 cx_attr_nonnull
1085 CX_EXPORT int cxListCloneSimple(CxList *dst, const CxList *src);
1086
1087 /**
1088 * Clones elements from a list only if they are not present in another list.
1089 *
1090 * This function uses the default allocator, if needed, and performs
1091 * shallow clones with @c memcpy().
1092 *
1093 * If the @p minuend does not contain duplicates, this is equivalent to adding
1094 * the set difference to the destination list.
1095 *
1096 * This function is optimized for the case when both the @p minuend and the
1097 * @p subtrahend are sorted.
1098 *
1099 * @param dst the destination list
1100 * @param minuend the list to subtract elements from
1101 * @param subtrahend the elements that shall be subtracted
1102 * @retval zero when the elements were successfully cloned
1103 * @retval non-zero when an allocation error occurred
1104 * @see cxListDifference()
1105 */
1106 cx_attr_nonnull
1107 CX_EXPORT int cxListDifferenceSimple(CxList *dst,
1108 const CxList *minuend, const CxList *subtrahend);
1109
1110 /**
1111 * Clones elements from a list only if they are also present in another list.
1112 *
1113 * This function uses the default allocator, if needed, and performs
1114 * shallow clones with @c memcpy().
1115 *
1116 * This function is optimized for the case when both the @p src and the
1117 * @p other list are sorted.
1118 *
1119 * If the destination list already contains elements, the intersection is appended
1120 * to that list.
1121 *
1122 * @param dst the destination list
1123 * @param src the list to clone the elements from
1124 * @param other the list to check the elements for existence
1125 * @retval zero when the elements were successfully cloned
1126 * @retval non-zero when an allocation error occurred
1127 * @see cxListIntersection()
1128 */
1129 cx_attr_nonnull
1130 CX_EXPORT int cxListIntersectionSimple(CxList *dst, const CxList *src, const CxList *other);
1131
1132 /**
1133 * Performs a deep clone of one list into another, skipping duplicates.
1134 *
1135 * This function uses the default allocator, if needed, and performs
1136 * shallow clones with @c memcpy().
1137 *
1138 * This function is optimized for the case when both the @p src and the
1139 * @p other list are sorted.
1140 * In that case, the union will also be sorted.
1141 *
1142 * If the destination list already contains elements, the union is appended
1143 * to that list. In that case the destination is not necessarily sorted.
1144 *
1145 * @param dst the destination list
1146 * @param src the primary source list
1147 * @param other the other list, where elements are only cloned from
1148 * when they are not in @p src
1149 * @retval zero when the elements were successfully cloned
1150 * @retval non-zero when an allocation error occurred
1151 * @see cxListUnion()
1152 */
1153 cx_attr_nonnull
1154 CX_EXPORT int cxListUnionSimple(CxList *dst, const CxList *src, const CxList *other);
1155
1156 /**
1157 * Asks the list to reserve enough memory for a given total number of elements.
1158 *
1159 * List implementations are free to choose if reserving memory upfront makes
1160 * sense.
1161 * For example, array-based implementations usually do support reserving memory
1162 * for additional elements while linked lists usually don't.
1163 *
1164 * @note When the requested capacity is smaller than the current size,
1165 * this function returns zero without performing any action.
1166 *
1167 * @param list the list
1168 * @param capacity the expected total number of elements
1169 * @retval zero on success or when overallocation is not supported
1170 * @retval non-zero when an allocation error occurred
1171 * @see cxListShrink()
1172 */
1173 cx_attr_nonnull
1174 CX_EXPORT int cxListReserve(CxList *list, size_t capacity);
1175
1176 /**
1177 * Advises the list to free any overallocated memory.
1178 *
1179 * Lists that do not support overallocation simply return zero.
1180 *
1181 * This function usually returns zero, except for very special and custom
1182 * list and/or allocator implementations where freeing memory can fail.
1183 *
1184 * @param list the list
1185 * @return usually zero
1186 */
1187 cx_attr_nonnull
1188 CX_EXPORT int cxListShrink(CxList *list);
1145 1189
1146 #ifdef __cplusplus 1190 #ifdef __cplusplus
1147 } // extern "C" 1191 } // extern "C"
1148 #endif 1192 #endif
1149 1193

mercurial