ucx/cx/list.h

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

mercurial