| 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 allocated memory or @c NULL if allocation fails. |
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 |
| 257 * @param sorted_data a pointer to the array of pre-sorted data to insert |
223 * @param sorted_data a pointer to the array of pre-sorted data to insert |
| 258 * @param n the number of elements to insert |
224 * @param n the number of elements to insert |
| 259 * @return the number of elements actually inserted |
225 * @return the number of elements actually inserted |
| 260 */ |
226 */ |
| 261 cx_attr_nonnull |
227 cx_attr_nonnull |
| 262 cx_attr_export |
228 CX_EXPORT size_t cx_list_default_insert_sorted(struct cx_list_s *list, |
| 263 size_t cx_list_default_insert_sorted( |
229 const void *sorted_data, size_t n); |
| 264 struct cx_list_s *list, |
230 |
| 265 const void *sorted_data, |
231 /** |
| 266 size_t n |
232 * Default implementation of an array insert where only elements are inserted when they don't exist in the list. |
| 267 ); |
233 * |
| |
234 * This function is similar to cx_list_default_insert_sorted(), except it skips elements that are already in the list. |
| |
235 * |
| |
236 * @note The return value of this function denotes the number of elements from the @p sorted_data that are definitely |
| |
237 * contained in the list after completing the call. It is @em not the number of elements that were newly inserted. |
| |
238 * That means, when no error occurred, the return value should be @p n. |
| |
239 * |
| |
240 * Use this in your own list class if you do not want to implement an optimized version for your list. |
| |
241 * |
| |
242 * @param list the list |
| |
243 * @param sorted_data a pointer to the array of pre-sorted data to insert |
| |
244 * @param n the number of elements to insert |
| |
245 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call |
| |
246 */ |
| |
247 cx_attr_nonnull |
| |
248 CX_EXPORT size_t cx_list_default_insert_unique(struct cx_list_s *list, |
| |
249 const void *sorted_data, size_t n); |
| 268 |
250 |
| 269 /** |
251 /** |
| 270 * Default unoptimized sort implementation. |
252 * Default unoptimized sort implementation. |
| 271 * |
253 * |
| 272 * This function will copy all data to an array, sort the array with standard |
254 * This function will copy all data to an array, sort the array with standard |
| 293 * @retval zero success |
274 * @retval zero success |
| 294 * @retval non-zero when indices are out of bounds or memory |
275 * @retval non-zero when indices are out of bounds or memory |
| 295 * allocation for the temporary buffer fails |
276 * allocation for the temporary buffer fails |
| 296 */ |
277 */ |
| 297 cx_attr_nonnull |
278 cx_attr_nonnull |
| 298 cx_attr_export |
279 CX_EXPORT int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j); |
| 299 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j); |
|
| 300 |
280 |
| 301 /** |
281 /** |
| 302 * Initializes a list struct. |
282 * Initializes a list struct. |
| 303 * |
283 * |
| 304 * Only use this function if you are creating your own list implementation. |
284 * Only use this function if you are creating your own list implementation. |
| 305 * The purpose of this function is to be called in the initialization code |
285 * The purpose of this function is to be called in the initialization code |
| 306 * of your list, to set certain members correctly. |
286 * of your list to set certain members correctly. |
| 307 * |
287 * |
| 308 * This is particularly important when you want your list to support |
288 * This is particularly important when you want your list to support |
| 309 * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list |
289 * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list |
| 310 * class accordingly and make sure that you can implement your list as if |
290 * class accordingly and make sure that you can implement your list as if |
| 311 * it was only storing objects and the wrapper will automatically enable |
291 * it was only storing objects, and the wrapper will automatically enable |
| 312 * the feature of storing pointers. |
292 * the feature of storing pointers. |
| 313 * |
293 * |
| 314 * @par Example |
294 * @par Example |
| 315 * |
295 * |
| 316 * @code |
296 * @code |
| 341 * @param allocator the allocator for the elements |
321 * @param allocator the allocator for the elements |
| 342 * @param comparator a compare function for the elements |
322 * @param comparator a compare function for the elements |
| 343 * @param elem_size the size of one element |
323 * @param elem_size the size of one element |
| 344 */ |
324 */ |
| 345 cx_attr_nonnull_arg(1, 2, 3) |
325 cx_attr_nonnull_arg(1, 2, 3) |
| 346 cx_attr_export |
326 CX_EXPORT void cx_list_init(struct cx_list_s *list, |
| 347 void cx_list_init( |
327 struct cx_list_class_s *cl, const struct cx_allocator_s *allocator, |
| 348 struct cx_list_s *list, |
328 cx_compare_func comparator, size_t elem_size); |
| 349 struct cx_list_class_s *cl, |
|
| 350 const struct cx_allocator_s *allocator, |
|
| 351 cx_compare_func comparator, |
|
| 352 size_t elem_size |
|
| 353 ); |
|
| 354 |
329 |
| 355 /** |
330 /** |
| 356 * Returns the number of elements currently stored in the list. |
331 * Returns the number of elements currently stored in the list. |
| 357 * |
332 * |
| 358 * @param list the list |
333 * @param list the list |
| 359 * @return the number of currently stored elements |
334 * @return the number of currently stored elements |
| 360 */ |
335 */ |
| 361 cx_attr_nonnull |
336 cx_attr_nonnull |
| 362 static inline size_t cxListSize(const CxList *list) { |
337 CX_EXPORT size_t cxListSize(const CxList *list); |
| 363 return list->collection.size; |
|
| 364 } |
|
| 365 |
338 |
| 366 /** |
339 /** |
| 367 * Adds an item to the end of the list. |
340 * Adds an item to the end of the list. |
| 368 * |
341 * |
| 369 * @param list the list |
342 * @param list the list |
| 372 * @retval non-zero memory allocation failure |
345 * @retval non-zero memory allocation failure |
| 373 * @see cxListAddArray() |
346 * @see cxListAddArray() |
| 374 * @see cxListEmplace() |
347 * @see cxListEmplace() |
| 375 */ |
348 */ |
| 376 cx_attr_nonnull |
349 cx_attr_nonnull |
| 377 static inline int cxListAdd( |
350 CX_EXPORT int cxListAdd(CxList *list, const void *elem); |
| 378 CxList *list, |
|
| 379 const void *elem |
|
| 380 ) { |
|
| 381 list->collection.sorted = false; |
|
| 382 return list->cl->insert_element(list, list->collection.size, elem) == NULL; |
|
| 383 } |
|
| 384 |
351 |
| 385 /** |
352 /** |
| 386 * Adds multiple items to the end of the list. |
353 * Adds multiple items to the end of the list. |
| 387 * |
354 * |
| 388 * This method is more efficient than invoking cxListAdd() multiple times. |
355 * This method is more efficient than invoking cxListAdd() multiple times. |
| 389 * |
356 * |
| 390 * If there is not enough memory to add all elements, the returned value is |
357 * If there is not enough memory to add all elements, the returned value is |
| 391 * less than @p n. |
358 * less than @p n. |
| 392 * |
359 * |
| 393 * If this list is storing pointers instead of objects @p array is expected to |
360 * If this list is storing pointers instead of objects, @p array is expected to |
| 394 * be an array of pointers. |
361 * be an array of pointers. |
| 395 * |
362 * |
| 396 * @param list the list |
363 * @param list the list |
| 397 * @param array a pointer to the elements to add |
364 * @param array a pointer to the elements to add |
| 398 * @param n the number of elements to add |
365 * @param n the number of elements to add |
| 399 * @return the number of added elements |
366 * @return the number of added elements |
| 400 */ |
367 * @see cxListEmplaceArray() |
| 401 cx_attr_nonnull |
368 */ |
| 402 static inline size_t cxListAddArray( |
369 cx_attr_nonnull |
| 403 CxList *list, |
370 CX_EXPORT size_t cxListAddArray(CxList *list, const void *array, size_t n); |
| 404 const void *array, |
|
| 405 size_t n |
|
| 406 ) { |
|
| 407 list->collection.sorted = false; |
|
| 408 return list->cl->insert_array(list, list->collection.size, array, n); |
|
| 409 } |
|
| 410 |
371 |
| 411 /** |
372 /** |
| 412 * Inserts an item at the specified index. |
373 * Inserts an item at the specified index. |
| 413 * |
374 * |
| 414 * If @p index equals the list @c size, this is effectively cxListAdd(). |
375 * If the @p index equals the list @c size, this is effectively cxListAdd(). |
| 415 * |
376 * |
| 416 * @param list the list |
377 * @param list the list |
| 417 * @param index the index the element shall have |
378 * @param index the index the element shall have |
| 418 * @param elem a pointer to the element to add |
379 * @param elem a pointer to the element to add |
| 419 * @retval zero success |
380 * @retval zero success |
| 421 * @see cxListInsertAfter() |
382 * @see cxListInsertAfter() |
| 422 * @see cxListInsertBefore() |
383 * @see cxListInsertBefore() |
| 423 * @see cxListEmplaceAt() |
384 * @see cxListEmplaceAt() |
| 424 */ |
385 */ |
| 425 cx_attr_nonnull |
386 cx_attr_nonnull |
| 426 static inline int cxListInsert( |
387 CX_EXPORT int cxListInsert(CxList *list, size_t index, const void *elem); |
| 427 CxList *list, |
|
| 428 size_t index, |
|
| 429 const void *elem |
|
| 430 ) { |
|
| 431 list->collection.sorted = false; |
|
| 432 return list->cl->insert_element(list, index, elem) == NULL; |
|
| 433 } |
|
| 434 |
388 |
| 435 /** |
389 /** |
| 436 * Allocates memory for an element at the specified index and returns a pointer to that memory. |
390 * Allocates memory for an element at the specified index and returns a pointer to that memory. |
| 437 * |
391 * |
| 438 * @remark When the list is storing pointers, this will return a @c void**. |
392 * @remark When the list is storing pointers, this will return a @c void**. |
| 439 * |
393 * |
| 440 * @param list the list |
394 * @param list the list |
| 441 * @param index the index where to emplace the element |
395 * @param index the index where to emplace the element |
| 442 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
396 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
| 443 * @see cxListEmplace() |
397 * @see cxListEmplace() |
| |
398 * @see cxListEmplaceArrayAt() |
| 444 * @see cxListInsert() |
399 * @see cxListInsert() |
| 445 */ |
400 */ |
| 446 cx_attr_nonnull |
401 cx_attr_nonnull |
| 447 static inline void *cxListEmplaceAt(CxList *list, size_t index) { |
402 CX_EXPORT void *cxListEmplaceAt(CxList *list, size_t index); |
| 448 list->collection.sorted = false; |
|
| 449 return list->cl->insert_element(list, index, NULL); |
|
| 450 } |
|
| 451 |
|
| 452 |
403 |
| 453 /** |
404 /** |
| 454 * Allocates memory for an element at the end of the list and returns a pointer to that memory. |
405 * Allocates memory for an element at the end of the list and returns a pointer to that memory. |
| 455 * |
406 * |
| 456 * @remark When the list is storing pointers, this will return a @c void**. |
407 * @remark When the list is storing pointers, this will return a @c void**. |
| 459 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
410 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
| 460 * @see cxListEmplaceAt() |
411 * @see cxListEmplaceAt() |
| 461 * @see cxListAdd() |
412 * @see cxListAdd() |
| 462 */ |
413 */ |
| 463 cx_attr_nonnull |
414 cx_attr_nonnull |
| 464 static inline void *cxListEmplace(CxList *list) { |
415 CX_EXPORT void *cxListEmplace(CxList *list); |
| 465 list->collection.sorted = false; |
416 |
| 466 return list->cl->insert_element(list, list->collection.size, NULL); |
417 /** |
| 467 } |
418 * Allocates memory for multiple elements and returns an iterator. |
| |
419 * |
| |
420 * The iterator will only iterate over the successfully allocated elements. |
| |
421 * The @c elem_count attribute is set to that number, and the @c index attribute |
| |
422 * will range from zero to @c elem_count minus one. |
| |
423 * |
| |
424 * @remark When the list is storing pointers, the iterator will iterate over |
| |
425 * the @c void** elements. |
| |
426 * |
| |
427 * @param list the list |
| |
428 * @param index the index where to insert the new data |
| |
429 * @param n the number of elements for which to allocate the memory |
| |
430 * @return an iterator, iterating over the new memory |
| |
431 * @see cxListEmplaceAt() |
| |
432 * @see cxListInsertArray() |
| |
433 */ |
| |
434 cx_attr_nonnull |
| |
435 CX_EXPORT CxIterator cxListEmplaceArrayAt(CxList *list, size_t index, size_t n); |
| |
436 |
| |
437 /** |
| |
438 * Allocates memory for multiple elements and returns an iterator. |
| |
439 * |
| |
440 * The iterator will only iterate over the successfully allocated elements. |
| |
441 * The @c elem_count attribute is set to that number, and the @c index attribute |
| |
442 * will range from zero to @c elem_count minus one. |
| |
443 * |
| |
444 * @remark When the list is storing pointers, the iterator will iterate over |
| |
445 * the @c void** elements. |
| |
446 * |
| |
447 * @param list the list |
| |
448 * @param n the number of elements for which to allocate the memory |
| |
449 * @return an iterator, iterating over the new memory |
| |
450 * @see cxListEmplace() |
| |
451 * @see cxListAddArray() |
| |
452 */ |
| |
453 cx_attr_nonnull |
| |
454 CX_EXPORT CxIterator cxListEmplaceArray(CxList *list, size_t n); |
| 468 |
455 |
| 469 /** |
456 /** |
| 470 * Inserts an item into a sorted list. |
457 * Inserts an item into a sorted list. |
| 471 * |
458 * |
| 472 * If the list is not sorted already, the behavior is undefined. |
459 * If the list is not sorted already, the behavior is undefined. |
| 475 * @param elem a pointer to the element to add |
462 * @param elem a pointer to the element to add |
| 476 * @retval zero success |
463 * @retval zero success |
| 477 * @retval non-zero memory allocation failure |
464 * @retval non-zero memory allocation failure |
| 478 */ |
465 */ |
| 479 cx_attr_nonnull |
466 cx_attr_nonnull |
| 480 static inline int cxListInsertSorted( |
467 CX_EXPORT int cxListInsertSorted(CxList *list, const void *elem); |
| 481 CxList *list, |
468 |
| 482 const void *elem |
469 /** |
| 483 ) { |
470 * Inserts an item into a list if it does not exist. |
| 484 list->collection.sorted = true; // guaranteed by definition |
471 * |
| 485 const void *data = list->collection.store_pointer ? &elem : elem; |
472 * If the list is not sorted already, this function will check all elements |
| 486 return list->cl->insert_sorted(list, data, 1) == 0; |
473 * and append the new element when it was not found. |
| 487 } |
474 * It is strongly recommended to use this function only on sorted lists, where |
| |
475 * the element, if it is not contained, is inserted at the correct position. |
| |
476 * |
| |
477 * @param list the list |
| |
478 * @param elem a pointer to the element to add |
| |
479 * @retval zero success (also when the element was already in the list) |
| |
480 * @retval non-zero memory allocation failure |
| |
481 */ |
| |
482 cx_attr_nonnull |
| |
483 CX_EXPORT int cxListInsertUnique(CxList *list, const void *elem); |
| 488 |
484 |
| 489 /** |
485 /** |
| 490 * Inserts multiple items to the list at the specified index. |
486 * Inserts multiple items to the list at the specified index. |
| 491 * If @p index equals the list size, this is effectively cxListAddArray(). |
487 * If the @p index equals the list size, this is effectively cxListAddArray(). |
| 492 * |
488 * |
| 493 * This method is usually more efficient than invoking cxListInsert() |
489 * This method is usually more efficient than invoking cxListInsert() |
| 494 * multiple times. |
490 * multiple times. |
| 495 * |
491 * |
| 496 * If there is not enough memory to add all elements, the returned value is |
492 * If there is not enough memory to add all elements, the returned value is |
| 497 * less than @p n. |
493 * less than @p n. |
| 498 * |
494 * |
| 499 * If this list is storing pointers instead of objects @p array is expected to |
495 * If this list is storing pointers instead of objects, @p array is expected to |
| 500 * be an array of pointers. |
496 * be an array of pointers. |
| 501 * |
497 * |
| 502 * @param list the list |
498 * @param list the list |
| 503 * @param index the index where to add the elements |
499 * @param index the index where to add the elements |
| 504 * @param array a pointer to the elements to add |
500 * @param array a pointer to the elements to add |
| 505 * @param n the number of elements to add |
501 * @param n the number of elements to add |
| 506 * @return the number of added elements |
502 * @return the number of added elements |
| 507 */ |
503 * @see cxListEmplaceArrayAt() |
| 508 cx_attr_nonnull |
504 */ |
| 509 static inline size_t cxListInsertArray( |
505 cx_attr_nonnull |
| 510 CxList *list, |
506 CX_EXPORT size_t cxListInsertArray(CxList *list, size_t index, const void *array, size_t n); |
| 511 size_t index, |
|
| 512 const void *array, |
|
| 513 size_t n |
|
| 514 ) { |
|
| 515 list->collection.sorted = false; |
|
| 516 return list->cl->insert_array(list, index, array, n); |
|
| 517 } |
|
| 518 |
507 |
| 519 /** |
508 /** |
| 520 * Inserts a sorted array into a sorted list. |
509 * Inserts a sorted array into a sorted list. |
| 521 * |
510 * |
| 522 * This method is usually more efficient than inserting each element separately, |
511 * This method is usually more efficient than inserting each element separately |
| 523 * because consecutive chunks of sorted data are inserted in one pass. |
512 * because consecutive chunks of sorted data are inserted in one pass. |
| 524 * |
513 * |
| 525 * If there is not enough memory to add all elements, the returned value is |
514 * If there is not enough memory to add all elements, the returned value is |
| 526 * less than @p n. |
515 * less than @p n. |
| 527 * |
516 * |
| 528 * If this list is storing pointers instead of objects @p array is expected to |
517 * If this list is storing pointers instead of objects, @p array is expected to |
| 529 * be an array of pointers. |
518 * be an array of pointers. |
| 530 * |
519 * |
| 531 * If the list is not sorted already, the behavior is undefined. |
520 * If the list is not sorted already, the behavior is undefined. |
| 532 * |
521 * |
| 533 * @param list the list |
522 * @param list the list |
| 534 * @param array a pointer to the elements to add |
523 * @param array a pointer to the elements to add |
| 535 * @param n the number of elements to add |
524 * @param n the number of elements to add |
| 536 * @return the number of added elements |
525 * @return the number of added elements |
| 537 */ |
526 */ |
| 538 cx_attr_nonnull |
527 cx_attr_nonnull |
| 539 static inline size_t cxListInsertSortedArray( |
528 CX_EXPORT size_t cxListInsertSortedArray(CxList *list, const void *array, size_t n); |
| 540 CxList *list, |
529 |
| 541 const void *array, |
530 /** |
| 542 size_t n |
531 * Inserts an array into a list, skipping duplicates. |
| 543 ) { |
532 * |
| 544 list->collection.sorted = true; // guaranteed by definition |
533 * The @p list does not need to be sorted (in contrast to cxListInsertSortedArray()). |
| 545 return list->cl->insert_sorted(list, array, n); |
534 * But it is strongly recommended to use this function only on sorted lists, |
| 546 } |
535 * because otherwise it will fall back to an inefficient algorithm which inserts |
| |
536 * all elements one by one. |
| |
537 * If the @p list is not sorted, the @p array also does not need to be sorted. |
| |
538 * But when the @p list is sorted, the @p array must also be sorted. |
| |
539 * |
| |
540 * This method is usually more efficient than inserting each element separately |
| |
541 * because consecutive chunks of sorted data are inserted in one pass. |
| |
542 * |
| |
543 * If there is not enough memory to add all elements, the returned value is |
| |
544 * less than @p n. |
| |
545 * |
| |
546 * @note The return value of this function denotes the number of elements |
| |
547 * from the @p sorted_data that are definitely contained in the list after |
| |
548 * completing the call. It is @em not the number of elements that were newly |
| |
549 * inserted. That means, when no error occurred, the return value should |
| |
550 * be @p n. |
| |
551 * |
| |
552 * If this list is storing pointers instead of objects @p array is expected to |
| |
553 * be an array of pointers. |
| |
554 * |
| |
555 * @param list the list |
| |
556 * @param array a pointer to the elements to add |
| |
557 * @param n the number of elements to add |
| |
558 * @return the number of added elements |
| |
559 * |
| |
560 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call |
| |
561 */ |
| |
562 cx_attr_nonnull |
| |
563 CX_EXPORT size_t cxListInsertUniqueArray(CxList *list, const void *array, size_t n); |
| 547 |
564 |
| 548 /** |
565 /** |
| 549 * Inserts an element after the current location of the specified iterator. |
566 * Inserts an element after the current location of the specified iterator. |
| 550 * |
567 * |
| 551 * The used iterator remains operational, but all other active iterators should |
568 * The used iterator remains operational, but all other active iterators should |
| 756 * @param index the index of the element |
728 * @param index the index of the element |
| 757 * @param num the number of elements to remove |
729 * @param num the number of elements to remove |
| 758 * @param targetbuf a buffer where to copy the elements |
730 * @param targetbuf a buffer where to copy the elements |
| 759 * @return the actual number of removed elements |
731 * @return the actual number of removed elements |
| 760 */ |
732 */ |
| 761 cx_attr_nonnull |
733 cx_attr_nonnull cx_attr_access_w(4) |
| 762 cx_attr_access_w(4) |
734 CX_EXPORT size_t cxListRemoveArrayAndGet(CxList *list, size_t index, size_t num, void *targetbuf); |
| 763 static inline size_t cxListRemoveArrayAndGet( |
|
| 764 CxList *list, |
|
| 765 size_t index, |
|
| 766 size_t num, |
|
| 767 void *targetbuf |
|
| 768 ) { |
|
| 769 return list->cl->remove(list, index, num, targetbuf); |
|
| 770 } |
|
| 771 |
735 |
| 772 /** |
736 /** |
| 773 * Removes all elements from this list. |
737 * Removes all elements from this list. |
| 774 * |
738 * |
| 775 * If element destructor functions are specified, they are called for each |
739 * If element destructor functions are specified, they are called for each |
| 776 * element before removing them. |
740 * element before removing them. |
| 777 * |
741 * |
| 778 * @param list the list |
742 * @param list the list |
| 779 */ |
743 */ |
| 780 cx_attr_nonnull |
744 cx_attr_nonnull |
| 781 static inline void cxListClear(CxList *list) { |
745 CX_EXPORT void cxListClear(CxList *list); |
| 782 list->collection.sorted = true; // empty lists are always sorted |
|
| 783 list->cl->clear(list); |
|
| 784 } |
|
| 785 |
746 |
| 786 /** |
747 /** |
| 787 * Swaps two items in the list. |
748 * Swaps two items in the list. |
| 788 * |
749 * |
| 789 * Implementations should only allocate temporary memory for the swap if |
750 * Implementations should only allocate temporary memory for the swap if |
| 814 * @param list the list |
768 * @param list the list |
| 815 * @param index the index of the element |
769 * @param index the index of the element |
| 816 * @return a pointer to the element or @c NULL if the index is out of bounds |
770 * @return a pointer to the element or @c NULL if the index is out of bounds |
| 817 */ |
771 */ |
| 818 cx_attr_nonnull |
772 cx_attr_nonnull |
| 819 static inline void *cxListAt( |
773 CX_EXPORT void *cxListAt(const CxList *list, size_t index); |
| 820 const CxList *list, |
|
| 821 size_t index |
|
| 822 ) { |
|
| 823 return list->cl->at(list, index); |
|
| 824 } |
|
| 825 |
774 |
| 826 /** |
775 /** |
| 827 * Returns a pointer to the first element. |
776 * Returns a pointer to the first element. |
| 828 * |
777 * |
| 829 * If the list is storing pointers, returns the first pointer stored in the list. |
778 * If the list is storing pointers, returns the first pointer stored in the list. |
| 830 * |
779 * |
| 831 * @param list the list |
780 * @param list the list |
| 832 * @return a pointer to the first element or @c NULL if the list is empty |
781 * @return a pointer to the first element or @c NULL if the list is empty |
| 833 */ |
782 */ |
| 834 cx_attr_nonnull |
783 cx_attr_nonnull |
| 835 static inline void *cxListFirst(const CxList *list) { |
784 CX_EXPORT void *cxListFirst(const CxList *list); |
| 836 return list->cl->at(list, 0); |
|
| 837 } |
|
| 838 |
785 |
| 839 /** |
786 /** |
| 840 * Returns a pointer to the last element. |
787 * Returns a pointer to the last element. |
| 841 * |
788 * |
| 842 * If the list is storing pointers, returns the last pointer stored in the list. |
789 * If the list is storing pointers, returns the last pointer stored in the list. |
| 843 * |
790 * |
| 844 * @param list the list |
791 * @param list the list |
| 845 * @return a pointer to the last element or @c NULL if the list is empty |
792 * @return a pointer to the last element or @c NULL if the list is empty |
| 846 */ |
793 */ |
| 847 cx_attr_nonnull |
794 cx_attr_nonnull |
| 848 static inline void *cxListLast(const CxList *list) { |
795 CX_EXPORT void *cxListLast(const CxList *list); |
| 849 return list->cl->at(list, list->collection.size - 1); |
796 |
| 850 } |
797 /** |
| 851 |
798 * Sets the element at the specified index in the list. |
| 852 /** |
799 * |
| 853 * Sets the element at the specified index in the list |
800 * This overwrites the element in-place without calling any destructor |
| |
801 * on the overwritten element. |
| 854 * |
802 * |
| 855 * @param list the list to set the element in |
803 * @param list the list to set the element in |
| 856 * @param index the index to set the element at |
804 * @param index the index to set the element at |
| 857 * @param elem element to set |
805 * @param elem element to set |
| 858 * @retval zero on success |
806 * @retval zero on success |
| 859 * @retval non-zero when index is out of bounds |
807 * @retval non-zero when index is out of bounds |
| 860 */ |
808 */ |
| 861 cx_attr_nonnull |
809 cx_attr_nonnull |
| 862 cx_attr_export |
810 CX_EXPORT int cxListSet(CxList *list, size_t index, const void *elem); |
| 863 int cxListSet( |
|
| 864 CxList *list, |
|
| 865 size_t index, |
|
| 866 const void *elem |
|
| 867 ); |
|
| 868 |
811 |
| 869 /** |
812 /** |
| 870 * Returns an iterator pointing to the item at the specified index. |
813 * Returns an iterator pointing to the item at the specified index. |
| 871 * |
814 * |
| 872 * The returned iterator is position-aware. |
815 * The returned iterator is position-aware. |
| 896 * @param list the list |
833 * @param list the list |
| 897 * @param index the index where the iterator shall point at |
834 * @param index the index where the iterator shall point at |
| 898 * @return a new iterator |
835 * @return a new iterator |
| 899 */ |
836 */ |
| 900 cx_attr_nodiscard |
837 cx_attr_nodiscard |
| 901 static inline CxIterator cxListBackwardsIteratorAt( |
838 CX_EXPORT CxIterator cxListBackwardsIteratorAt(const CxList *list, size_t index); |
| 902 const CxList *list, |
839 |
| 903 size_t index |
840 /** |
| 904 ) { |
841 * Returns an iterator pointing to the first item of the list. |
| 905 if (list == NULL) list = cxEmptyList; |
|
| 906 return list->cl->iterator(list, index, true); |
|
| 907 } |
|
| 908 |
|
| 909 /** |
|
| 910 * Returns a mutating iterator pointing to the item at the specified index. |
|
| 911 * |
842 * |
| 912 * The returned iterator is position-aware. |
843 * The returned iterator is position-aware. |
| 913 * |
844 * |
| 914 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
845 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 915 * |
846 * |
| 916 * @param list the list |
847 * @param list the list |
| 917 * @param index the index where the iterator shall point at |
|
| 918 * @return a new iterator |
848 * @return a new iterator |
| 919 */ |
849 */ |
| 920 cx_attr_nodiscard |
850 cx_attr_nodiscard |
| 921 cx_attr_export |
851 CX_EXPORT CxIterator cxListIterator(const CxList *list); |
| 922 CxIterator cxListMutIteratorAt( |
852 |
| 923 CxList *list, |
853 /** |
| 924 size_t index |
854 * Returns a backwards iterator pointing to the last item of the list. |
| 925 ); |
|
| 926 |
|
| 927 /** |
|
| 928 * Returns a mutating backwards iterator pointing to the item at the |
|
| 929 * specified index. |
|
| 930 * |
855 * |
| 931 * The returned iterator is position-aware. |
856 * The returned iterator is position-aware. |
| 932 * |
857 * |
| 933 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
858 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 934 * |
859 * |
| 935 * @param list the list |
860 * @param list the list |
| 936 * @param index the index where the iterator shall point at |
|
| 937 * @return a new iterator |
861 * @return a new iterator |
| 938 */ |
862 */ |
| 939 cx_attr_nodiscard |
863 cx_attr_nodiscard |
| 940 cx_attr_export |
864 CX_EXPORT CxIterator cxListBackwardsIterator(const CxList *list); |
| 941 CxIterator cxListMutBackwardsIteratorAt( |
|
| 942 CxList *list, |
|
| 943 size_t index |
|
| 944 ); |
|
| 945 |
|
| 946 /** |
|
| 947 * Returns an iterator pointing to the first item of the list. |
|
| 948 * |
|
| 949 * The returned iterator is position-aware. |
|
| 950 * |
|
| 951 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
|
| 952 * |
|
| 953 * @param list the list |
|
| 954 * @return a new iterator |
|
| 955 */ |
|
| 956 cx_attr_nodiscard |
|
| 957 static inline CxIterator cxListIterator(const CxList *list) { |
|
| 958 if (list == NULL) list = cxEmptyList; |
|
| 959 return list->cl->iterator(list, 0, false); |
|
| 960 } |
|
| 961 |
|
| 962 /** |
|
| 963 * Returns a mutating iterator pointing to the first item of the list. |
|
| 964 * |
|
| 965 * The returned iterator is position-aware. |
|
| 966 * |
|
| 967 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
|
| 968 * |
|
| 969 * @param list the list |
|
| 970 * @return a new iterator |
|
| 971 */ |
|
| 972 cx_attr_nodiscard |
|
| 973 static inline CxIterator cxListMutIterator(CxList *list) { |
|
| 974 if (list == NULL) list = cxEmptyList; |
|
| 975 return cxListMutIteratorAt(list, 0); |
|
| 976 } |
|
| 977 |
|
| 978 |
|
| 979 /** |
|
| 980 * Returns a backwards iterator pointing to the last item of the list. |
|
| 981 * |
|
| 982 * The returned iterator is position-aware. |
|
| 983 * |
|
| 984 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
|
| 985 * |
|
| 986 * @param list the list |
|
| 987 * @return a new iterator |
|
| 988 */ |
|
| 989 cx_attr_nodiscard |
|
| 990 static inline CxIterator cxListBackwardsIterator(const CxList *list) { |
|
| 991 if (list == NULL) list = cxEmptyList; |
|
| 992 return list->cl->iterator(list, list->collection.size - 1, true); |
|
| 993 } |
|
| 994 |
|
| 995 /** |
|
| 996 * Returns a mutating backwards iterator pointing to the last item of the list. |
|
| 997 * |
|
| 998 * The returned iterator is position-aware. |
|
| 999 * |
|
| 1000 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
|
| 1001 * |
|
| 1002 * @param list the list |
|
| 1003 * @return a new iterator |
|
| 1004 */ |
|
| 1005 cx_attr_nodiscard |
|
| 1006 static inline CxIterator cxListMutBackwardsIterator(CxList *list) { |
|
| 1007 if (list == NULL) list = cxEmptyList; |
|
| 1008 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1); |
|
| 1009 } |
|
| 1010 |
865 |
| 1011 /** |
866 /** |
| 1012 * Returns the index of the first element that equals @p elem. |
867 * Returns the index of the first element that equals @p elem. |
| 1013 * |
868 * |
| 1014 * Determining equality is performed by the list's comparator function. |
869 * Determining equality is performed by the list's comparator function. |
| 1017 * @param elem the element to find |
872 * @param elem the element to find |
| 1018 * @return the index of the element or the size of the list when the element is not found |
873 * @return the index of the element or the size of the list when the element is not found |
| 1019 * @see cxListIndexValid() |
874 * @see cxListIndexValid() |
| 1020 * @see cxListContains() |
875 * @see cxListContains() |
| 1021 */ |
876 */ |
| 1022 cx_attr_nonnull |
877 cx_attr_nonnull cx_attr_nodiscard |
| 1023 cx_attr_nodiscard |
878 CX_EXPORT size_t cxListFind(const CxList *list, const void *elem); |
| 1024 static inline size_t cxListFind( |
879 |
| 1025 const CxList *list, |
880 /** |
| 1026 const void *elem |
881 * Checks if the list contains the specified element. |
| 1027 ) { |
|
| 1028 return list->cl->find_remove((CxList*)list, elem, false); |
|
| 1029 } |
|
| 1030 |
|
| 1031 /** |
|
| 1032 * Checks, if the list contains the specified element. |
|
| 1033 * |
882 * |
| 1034 * The elements are compared with the list's comparator function. |
883 * The elements are compared with the list's comparator function. |
| 1035 * |
884 * |
| 1036 * @param list the list |
885 * @param list the list |
| 1037 * @param elem the element to find |
886 * @param elem the element to find |
| 1038 * @retval true if the element is contained |
887 * @retval true if the element is contained |
| 1039 * @retval false if the element is not contained |
888 * @retval false if the element is not contained |
| 1040 * @see cxListFind() |
889 * @see cxListFind() |
| 1041 */ |
890 */ |
| 1042 cx_attr_nonnull |
891 cx_attr_nonnull cx_attr_nodiscard |
| 1043 cx_attr_nodiscard |
892 CX_EXPORT bool cxListContains(const CxList* list, const void* elem); |
| 1044 static inline bool cxListContains( |
|
| 1045 const CxList* list, |
|
| 1046 const void* elem |
|
| 1047 ) { |
|
| 1048 return list->cl->find_remove((CxList*)list, elem, false) < list->collection.size; |
|
| 1049 } |
|
| 1050 |
893 |
| 1051 /** |
894 /** |
| 1052 * Checks if the specified index is within bounds. |
895 * Checks if the specified index is within bounds. |
| 1053 * |
896 * |
| 1054 * @param list the list |
897 * @param list the list |
| 1055 * @param index the index |
898 * @param index the index |
| 1056 * @retval true if the index is within bounds |
899 * @retval true if the index is within bounds |
| 1057 * @retval false if the index is out of bounds |
900 * @retval false if the index is out of bounds |
| 1058 */ |
901 */ |
| 1059 cx_attr_nonnull |
902 cx_attr_nonnull cx_attr_nodiscard |
| 1060 cx_attr_nodiscard |
903 CX_EXPORT bool cxListIndexValid(const CxList *list, size_t index); |
| 1061 static inline bool cxListIndexValid(const CxList *list, size_t index) { |
|
| 1062 return index < list->collection.size; |
|
| 1063 } |
|
| 1064 |
904 |
| 1065 /** |
905 /** |
| 1066 * Removes and returns the index of the first element that equals @p elem. |
906 * Removes and returns the index of the first element that equals @p elem. |
| 1067 * |
907 * |
| 1068 * Determining equality is performed by the list's comparator function. |
908 * Determining equality is performed by the list's comparator function. |
| 1072 * @return the index of the now removed element or the list size |
912 * @return the index of the now removed element or the list size |
| 1073 * when the element is not found or could not be removed |
913 * when the element is not found or could not be removed |
| 1074 * @see cxListIndexValid() |
914 * @see cxListIndexValid() |
| 1075 */ |
915 */ |
| 1076 cx_attr_nonnull |
916 cx_attr_nonnull |
| 1077 static inline size_t cxListFindRemove( |
917 CX_EXPORT size_t cxListFindRemove(CxList *list, const void *elem); |
| 1078 CxList *list, |
|
| 1079 const void *elem |
|
| 1080 ) { |
|
| 1081 return list->cl->find_remove(list, elem, true); |
|
| 1082 } |
|
| 1083 |
918 |
| 1084 /** |
919 /** |
| 1085 * Sorts the list. |
920 * Sorts the list. |
| 1086 * |
921 * |
| 1087 * @remark The underlying sort algorithm is implementation defined. |
922 * @remark The underlying sort algorithm is implementation defined. |
| 1088 * |
923 * |
| 1089 * @param list the list |
924 * @param list the list |
| 1090 */ |
925 */ |
| 1091 cx_attr_nonnull |
926 cx_attr_nonnull |
| 1092 static inline void cxListSort(CxList *list) { |
927 CX_EXPORT void cxListSort(CxList *list); |
| 1093 if (list->collection.sorted) return; |
|
| 1094 list->cl->sort(list); |
|
| 1095 list->collection.sorted = true; |
|
| 1096 } |
|
| 1097 |
928 |
| 1098 /** |
929 /** |
| 1099 * Reverses the order of the items. |
930 * Reverses the order of the items. |
| 1100 * |
931 * |
| 1101 * @param list the list |
932 * @param list the list |
| 1102 */ |
933 */ |
| 1103 cx_attr_nonnull |
934 cx_attr_nonnull |
| 1104 static inline void cxListReverse(CxList *list) { |
935 CX_EXPORT void cxListReverse(CxList *list); |
| 1105 // still sorted, but not according to the cmp_func |
|
| 1106 list->collection.sorted = false; |
|
| 1107 list->cl->reverse(list); |
|
| 1108 } |
|
| 1109 |
936 |
| 1110 /** |
937 /** |
| 1111 * Compares a list to another list of the same type. |
938 * Compares a list to another list of the same type. |
| 1112 * |
939 * |
| 1113 * First, the list sizes are compared. |
940 * First, the list sizes are compared. |
| 1114 * If they match, the lists are compared element-wise. |
941 * If they match, the lists are compared element-wise. |
| 1115 * |
942 * |
| 1116 * @param list the list |
943 * @param list the list |
| 1117 * @param other the list to compare to |
944 * @param other the list to compare to |
| 1118 * @retval zero both lists are equal element wise |
945 * @retval zero both lists are equal element wise |
| 1119 * @retval negative the first list is smaller |
946 * @retval negative the first list is smaller, |
| 1120 * or the first non-equal element in the first list is smaller |
947 * or the first non-equal element in the first list is smaller |
| 1121 * @retval positive the first list is larger |
948 * @retval positive the first list is larger |
| 1122 * or the first non-equal element in the first list is larger |
949 * or the first non-equal element in the first list is larger |
| 1123 */ |
950 */ |
| 1124 cx_attr_nonnull |
951 cx_attr_nonnull cx_attr_nodiscard |
| 1125 cx_attr_nodiscard |
952 CX_EXPORT int cxListCompare(const CxList *list, const CxList *other); |
| 1126 cx_attr_export |
|
| 1127 int cxListCompare( |
|
| 1128 const CxList *list, |
|
| 1129 const CxList *other |
|
| 1130 ); |
|
| 1131 |
953 |
| 1132 /** |
954 /** |
| 1133 * Deallocates the memory of the specified list structure. |
955 * Deallocates the memory of the specified list structure. |
| 1134 * |
956 * |
| 1135 * Also calls the content destructor functions for each element, if specified. |
957 * Also calls the content destructor functions for each element, if specified. |
| 1136 * |
958 * |
| 1137 * @param list the list which shall be freed |
959 * @param list the list that shall be freed |
| 1138 */ |
960 */ |
| 1139 cx_attr_export |
961 CX_EXPORT void cxListFree(CxList *list); |
| 1140 void cxListFree(CxList *list); |
962 |
| |
963 |
| |
964 /** |
| |
965 * Performs a deep clone of one list into another. |
| |
966 * |
| |
967 * If the destination list already contains elements, the cloned elements |
| |
968 * are appended to that list. |
| |
969 * |
| |
970 * @attention If the cloned elements need to be destroyed by a destructor |
| |
971 * function, you must make sure that the destination list also uses this |
| |
972 * destructor function. |
| |
973 * |
| |
974 * @param dst the destination list |
| |
975 * @param src the source list |
| |
976 * @param clone_func the clone function for the elements |
| |
977 * @param clone_allocator the allocator that is passed to the clone function |
| |
978 * @param data optional additional data that is passed to the clone function |
| |
979 * @retval zero when all elements were successfully cloned |
| |
980 * @retval non-zero when an allocation error occurred |
| |
981 * @see cxListUnion() |
| |
982 */ |
| |
983 cx_attr_nonnull_arg(1, 2, 3) |
| |
984 CX_EXPORT int cxListClone(CxList *dst, const CxList *src, |
| |
985 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); |
| |
986 |
| |
987 /** |
| |
988 * Clones elements from a list only if they are not present in another list. |
| |
989 * |
| |
990 * If the @p minuend does not contain duplicates, this is equivalent to adding |
| |
991 * the set difference to the destination list. |
| |
992 * |
| |
993 * This function is optimized for the case when both the @p minuend and the |
| |
994 * @p subtrahend are sorted. |
| |
995 * |
| |
996 * @param dst the destination list |
| |
997 * @param minuend the list to subtract elements from |
| |
998 * @param subtrahend the elements that shall be subtracted |
| |
999 * @param clone_func the clone function for the elements |
| |
1000 * @param clone_allocator the allocator that is passed to the clone function |
| |
1001 * @param data optional additional data that is passed to the clone function |
| |
1002 * @retval zero when the elements were successfully cloned |
| |
1003 * @retval non-zero when an allocation error occurred |
| |
1004 */ |
| |
1005 cx_attr_nonnull_arg(1, 2, 3, 4) |
| |
1006 CX_EXPORT int cxListDifference(CxList *dst, |
| |
1007 const CxList *minuend, const CxList *subtrahend, |
| |
1008 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); |
| |
1009 |
| |
1010 /** |
| |
1011 * Clones elements from a list only if they are also present in another list. |
| |
1012 * |
| |
1013 * This function is optimized for the case when both the @p src and the |
| |
1014 * @p other list are sorted. |
| |
1015 * |
| |
1016 * If the destination list already contains elements, the intersection is appended |
| |
1017 * to that list. |
| |
1018 * |
| |
1019 * @param dst the destination list |
| |
1020 * @param src the list to clone the elements from |
| |
1021 * @param other the list to check the elements for existence |
| |
1022 * @param clone_func the clone function for the elements |
| |
1023 * @param clone_allocator the allocator that is passed to the clone function |
| |
1024 * @param data optional additional data that is passed to the clone function |
| |
1025 * @retval zero when the elements were successfully cloned |
| |
1026 * @retval non-zero when an allocation error occurred |
| |
1027 */ |
| |
1028 cx_attr_nonnull_arg(1, 2, 3, 4) |
| |
1029 CX_EXPORT int cxListIntersection(CxList *dst, const CxList *src, const CxList *other, |
| |
1030 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); |
| |
1031 |
| |
1032 /** |
| |
1033 * Performs a deep clone of one list into another, skipping duplicates. |
| |
1034 * |
| |
1035 * This function is optimized for the case when both the @p src and the |
| |
1036 * @p other list are sorted. |
| |
1037 * In that case, the union will also be sorted. |
| |
1038 * |
| |
1039 * If the destination list already contains elements, the union is appended |
| |
1040 * to that list. In that case the destination is not necessarily sorted. |
| |
1041 * |
| |
1042 * @param dst the destination list |
| |
1043 * @param src the primary source list |
| |
1044 * @param other the other list, where elements are only cloned from |
| |
1045 * when they are not in @p src |
| |
1046 * @param clone_func the clone function for the elements |
| |
1047 * @param clone_allocator the allocator that is passed to the clone function |
| |
1048 * @param data optional additional data that is passed to the clone function |
| |
1049 * @retval zero when the elements were successfully cloned |
| |
1050 * @retval non-zero when an allocation error occurred |
| |
1051 * @see cxListClone() |
| |
1052 */ |
| |
1053 cx_attr_nonnull_arg(1, 2, 3, 4) |
| |
1054 CX_EXPORT int cxListUnion(CxList *dst, const CxList *src, const CxList *other, |
| |
1055 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); |
| 1141 |
1056 |
| 1142 |
1057 |
| 1143 #ifdef __cplusplus |
1058 #ifdef __cplusplus |
| 1144 } // extern "C" |
1059 } // extern "C" |
| 1145 #endif |
1060 #endif |