ucx/cx/list.h

changeset 102
64ded9f6a6c6
parent 101
7b3a3130be44
equal deleted inserted replaced
101:7b3a3130be44 102:64ded9f6a6c6
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 * Implementors SHOULD see to performant implementations for corner cases.
84 */ 83 */
85 int (*insert_element)( 84 int (*insert_element)(
86 struct cx_list_s *list, 85 struct cx_list_s *list,
87 size_t index, 86 size_t index,
88 const void *data 87 const void *data
89 ); 88 );
90 89
91 /** 90 /**
92 * Member function for inserting multiple elements. 91 * Member function for inserting multiple elements.
93 * Implementors SHOULD see to performant implementations for corner cases.
94 * 92 *
95 * @see cx_list_default_insert_array() 93 * @see cx_list_default_insert_array()
96 */ 94 */
97 size_t (*insert_array)( 95 size_t (*insert_array)(
98 struct cx_list_s *list, 96 struct cx_list_s *list,
163 ); 161 );
164 162
165 /** 163 /**
166 * Member function for finding and optionally removing an element. 164 * Member function for finding and optionally removing an element.
167 */ 165 */
168 ssize_t (*find_remove)( 166 size_t (*find_remove)(
169 struct cx_list_s *list, 167 struct cx_list_s *list,
170 const void *elem, 168 const void *elem,
171 bool remove 169 bool remove
172 ); 170 );
173 171
217 * @param data a pointer to the array of data to insert 215 * @param data a pointer to the array of data to insert
218 * @param n the number of elements to insert 216 * @param n the number of elements to insert
219 * @return the number of elements actually inserted 217 * @return the number of elements actually inserted
220 */ 218 */
221 cx_attr_nonnull 219 cx_attr_nonnull
220 cx_attr_export
222 size_t cx_list_default_insert_array( 221 size_t cx_list_default_insert_array(
223 struct cx_list_s *list, 222 struct cx_list_s *list,
224 size_t index, 223 size_t index,
225 const void *data, 224 const void *data,
226 size_t n 225 size_t n
241 * @param sorted_data a pointer to the array of pre-sorted data to insert 240 * @param sorted_data a pointer to the array of pre-sorted data to insert
242 * @param n the number of elements to insert 241 * @param n the number of elements to insert
243 * @return the number of elements actually inserted 242 * @return the number of elements actually inserted
244 */ 243 */
245 cx_attr_nonnull 244 cx_attr_nonnull
245 cx_attr_export
246 size_t cx_list_default_insert_sorted( 246 size_t cx_list_default_insert_sorted(
247 struct cx_list_s *list, 247 struct cx_list_s *list,
248 const void *sorted_data, 248 const void *sorted_data,
249 size_t n 249 size_t n
250 ); 250 );
259 * version for your list. 259 * version for your list.
260 * 260 *
261 * @param list the list that shall be sorted 261 * @param list the list that shall be sorted
262 */ 262 */
263 cx_attr_nonnull 263 cx_attr_nonnull
264 cx_attr_export
264 void cx_list_default_sort(struct cx_list_s *list); 265 void cx_list_default_sort(struct cx_list_s *list);
265 266
266 /** 267 /**
267 * Default unoptimized swap implementation. 268 * Default unoptimized swap implementation.
268 * 269 *
275 * @retval zero success 276 * @retval zero success
276 * @retval non-zero when indices are out of bounds or memory 277 * @retval non-zero when indices are out of bounds or memory
277 * allocation for the temporary buffer fails 278 * allocation for the temporary buffer fails
278 */ 279 */
279 cx_attr_nonnull 280 cx_attr_nonnull
281 cx_attr_export
280 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j); 282 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j);
281 283
282 /** 284 /**
285 * Initializes a list struct.
286 *
287 * Only use this function if you are creating your own list implementation.
288 * The purpose of this function is to be called in the initialization code
289 * of your list, to set certain members correctly.
290 *
291 * This is particularly important when you want your list to support
292 * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list
293 * class accordingly and make sure that you can implement your list as if
294 * it was only storing objects and the wrapper will automatically enable
295 * the feature of storing pointers.
296 *
297 * @par Example
298 *
299 * @code
300 * CxList *myCustomListCreate(
301 * const CxAllocator *allocator,
302 * cx_compare_func comparator,
303 * size_t elem_size
304 * ) {
305 * if (allocator == NULL) {
306 * allocator = cxDefaultAllocator;
307 * }
308 *
309 * MyCustomList *list = cxCalloc(allocator, 1, sizeof(MyCustomList));
310 * if (list == NULL) return NULL;
311 *
312 * // initialize
313 * cx_list_init((CxList*)list, &my_custom_list_class,
314 * allocator, comparator, elem_size);
315 *
316 * // ... some more custom stuff ...
317 *
318 * return (CxList *) list;
319 * }
320 * @endcode
321 *
322 * @param list the list to initialize
323 * @param cl the list class
324 * @param allocator the allocator for the elements
325 * @param comparator a compare function for the elements
326 * @param elem_size the size of one element
327 */
328 cx_attr_nonnull_arg(1, 2, 3)
329 cx_attr_export
330 void cx_list_init(
331 struct cx_list_s *list,
332 struct cx_list_class_s *cl,
333 const struct cx_allocator_s *allocator,
334 cx_compare_func comparator,
335 size_t elem_size
336 );
337
338 /**
283 * Common type for all list implementations. 339 * Common type for all list implementations.
284 */ 340 */
285 typedef struct cx_list_s CxList; 341 typedef struct cx_list_s CxList;
286
287 /**
288 * Advises the list to store copies of the objects (default mode of operation).
289 *
290 * Retrieving objects from this list will yield pointers to the copies stored
291 * within this list.
292 *
293 * @param list the list
294 * @see cxListStorePointers()
295 */
296 cx_attr_nonnull
297 void cxListStoreObjects(CxList *list);
298
299 /**
300 * Advises the list to only store pointers to the objects.
301 *
302 * Retrieving objects from this list will yield the original pointers stored.
303 *
304 * @note This function forcibly sets the element size to the size of a pointer.
305 * Invoking this function on a non-empty list that already stores copies of
306 * objects is undefined.
307 *
308 * @param list the list
309 * @see cxListStoreObjects()
310 */
311 cx_attr_nonnull
312 void cxListStorePointers(CxList *list);
313
314 /**
315 * Returns true, if this list is storing pointers instead of the actual data.
316 *
317 * @param list
318 * @return true, if this list is storing pointers
319 * @see cxListStorePointers()
320 */
321 cx_attr_nonnull
322 static inline bool cxListIsStoringPointers(const CxList *list) {
323 return list->collection.store_pointer;
324 }
325 342
326 /** 343 /**
327 * Returns the number of elements currently stored in the list. 344 * Returns the number of elements currently stored in the list.
328 * 345 *
329 * @param list the list 346 * @param list the list
346 cx_attr_nonnull 363 cx_attr_nonnull
347 static inline int cxListAdd( 364 static inline int cxListAdd(
348 CxList *list, 365 CxList *list,
349 const void *elem 366 const void *elem
350 ) { 367 ) {
368 list->collection.sorted = false;
351 return list->cl->insert_element(list, list->collection.size, elem); 369 return list->cl->insert_element(list, list->collection.size, elem);
352 } 370 }
353 371
354 /** 372 /**
355 * Adds multiple items to the end of the list. 373 * Adds multiple items to the end of the list.
371 static inline size_t cxListAddArray( 389 static inline size_t cxListAddArray(
372 CxList *list, 390 CxList *list,
373 const void *array, 391 const void *array,
374 size_t n 392 size_t n
375 ) { 393 ) {
394 list->collection.sorted = false;
376 return list->cl->insert_array(list, list->collection.size, array, n); 395 return list->cl->insert_array(list, list->collection.size, array, n);
377 } 396 }
378 397
379 /** 398 /**
380 * Inserts an item at the specified index. 399 * Inserts an item at the specified index.
393 static inline int cxListInsert( 412 static inline int cxListInsert(
394 CxList *list, 413 CxList *list,
395 size_t index, 414 size_t index,
396 const void *elem 415 const void *elem
397 ) { 416 ) {
417 list->collection.sorted = false;
398 return list->cl->insert_element(list, index, elem); 418 return list->cl->insert_element(list, index, elem);
399 } 419 }
400 420
401 /** 421 /**
402 * Inserts an item into a sorted list. 422 * Inserts an item into a sorted list.
423 *
424 * If the list is not sorted already, the behavior is undefined.
403 * 425 *
404 * @param list the list 426 * @param list the list
405 * @param elem a pointer to the element to add 427 * @param elem a pointer to the element to add
406 * @retval zero success 428 * @retval zero success
407 * @retval non-zero memory allocation failure 429 * @retval non-zero memory allocation failure
409 cx_attr_nonnull 431 cx_attr_nonnull
410 static inline int cxListInsertSorted( 432 static inline int cxListInsertSorted(
411 CxList *list, 433 CxList *list,
412 const void *elem 434 const void *elem
413 ) { 435 ) {
436 list->collection.sorted = true; // guaranteed by definition
414 const void *data = list->collection.store_pointer ? &elem : elem; 437 const void *data = list->collection.store_pointer ? &elem : elem;
415 return list->cl->insert_sorted(list, data, 1) == 0; 438 return list->cl->insert_sorted(list, data, 1) == 0;
416 } 439 }
417 440
418 /** 441 /**
439 CxList *list, 462 CxList *list,
440 size_t index, 463 size_t index,
441 const void *array, 464 const void *array,
442 size_t n 465 size_t n
443 ) { 466 ) {
467 list->collection.sorted = false;
444 return list->cl->insert_array(list, index, array, n); 468 return list->cl->insert_array(list, index, array, n);
445 } 469 }
446 470
447 /** 471 /**
448 * Inserts a sorted array into a sorted list. 472 * Inserts a sorted array into a sorted list.
453 * If there is not enough memory to add all elements, the returned value is 477 * If there is not enough memory to add all elements, the returned value is
454 * less than @p n. 478 * less than @p n.
455 * 479 *
456 * If this list is storing pointers instead of objects @p array is expected to 480 * If this list is storing pointers instead of objects @p array is expected to
457 * be an array of pointers. 481 * be an array of pointers.
482 *
483 * If the list is not sorted already, the behavior is undefined.
458 * 484 *
459 * @param list the list 485 * @param list the list
460 * @param array a pointer to the elements to add 486 * @param array a pointer to the elements to add
461 * @param n the number of elements to add 487 * @param n the number of elements to add
462 * @return the number of added elements 488 * @return the number of added elements
465 static inline size_t cxListInsertSortedArray( 491 static inline size_t cxListInsertSortedArray(
466 CxList *list, 492 CxList *list,
467 const void *array, 493 const void *array,
468 size_t n 494 size_t n
469 ) { 495 ) {
496 list->collection.sorted = true; // guaranteed by definition
470 return list->cl->insert_sorted(list, array, n); 497 return list->cl->insert_sorted(list, array, n);
471 } 498 }
472 499
473 /** 500 /**
474 * Inserts an element after the current location of the specified iterator. 501 * Inserts an element after the current location of the specified iterator.
489 cx_attr_nonnull 516 cx_attr_nonnull
490 static inline int cxListInsertAfter( 517 static inline int cxListInsertAfter(
491 CxIterator *iter, 518 CxIterator *iter,
492 const void *elem 519 const void *elem
493 ) { 520 ) {
494 return ((struct cx_list_s *) iter->src_handle.m)->cl->insert_iter(iter, elem, 0); 521 CxList* list = (CxList*)iter->src_handle.m;
522 list->collection.sorted = false;
523 return list->cl->insert_iter(iter, elem, 0);
495 } 524 }
496 525
497 /** 526 /**
498 * Inserts an element before the current location of the specified iterator. 527 * Inserts an element before the current location of the specified iterator.
499 * 528 *
513 cx_attr_nonnull 542 cx_attr_nonnull
514 static inline int cxListInsertBefore( 543 static inline int cxListInsertBefore(
515 CxIterator *iter, 544 CxIterator *iter,
516 const void *elem 545 const void *elem
517 ) { 546 ) {
518 return ((struct cx_list_s *) iter->src_handle.m)->cl->insert_iter(iter, elem, 1); 547 CxList* list = (CxList*)iter->src_handle.m;
548 list->collection.sorted = false;
549 return list->cl->insert_iter(iter, elem, 1);
519 } 550 }
520 551
521 /** 552 /**
522 * Removes the element at the specified index. 553 * Removes the element at the specified index.
523 * 554 *
614 * 645 *
615 * @param list the list 646 * @param list the list
616 */ 647 */
617 cx_attr_nonnull 648 cx_attr_nonnull
618 static inline void cxListClear(CxList *list) { 649 static inline void cxListClear(CxList *list) {
650 list->collection.sorted = true; // empty lists are always sorted
619 list->cl->clear(list); 651 list->cl->clear(list);
620 } 652 }
621 653
622 /** 654 /**
623 * Swaps two items in the list. 655 * Swaps two items in the list.
636 static inline int cxListSwap( 668 static inline int cxListSwap(
637 CxList *list, 669 CxList *list,
638 size_t i, 670 size_t i,
639 size_t j 671 size_t j
640 ) { 672 ) {
673 list->collection.sorted = false;
641 return list->cl->swap(list, i, j); 674 return list->cl->swap(list, i, j);
642 } 675 }
643 676
644 /** 677 /**
645 * Returns a pointer to the element at the specified index. 678 * Returns a pointer to the element at the specified index.
707 * @param index the index where the iterator shall point at 740 * @param index the index where the iterator shall point at
708 * @return a new iterator 741 * @return a new iterator
709 */ 742 */
710 cx_attr_nonnull 743 cx_attr_nonnull
711 cx_attr_nodiscard 744 cx_attr_nodiscard
745 cx_attr_export
712 CxIterator cxListMutIteratorAt( 746 CxIterator cxListMutIteratorAt(
713 CxList *list, 747 CxList *list,
714 size_t index 748 size_t index
715 ); 749 );
716 750
726 * @param index the index where the iterator shall point at 760 * @param index the index where the iterator shall point at
727 * @return a new iterator 761 * @return a new iterator
728 */ 762 */
729 cx_attr_nonnull 763 cx_attr_nonnull
730 cx_attr_nodiscard 764 cx_attr_nodiscard
765 cx_attr_export
731 CxIterator cxListMutBackwardsIteratorAt( 766 CxIterator cxListMutBackwardsIteratorAt(
732 CxList *list, 767 CxList *list,
733 size_t index 768 size_t index
734 ); 769 );
735 770
803 * 838 *
804 * Determining equality is performed by the list's comparator function. 839 * Determining equality is performed by the list's comparator function.
805 * 840 *
806 * @param list the list 841 * @param list the list
807 * @param elem the element to find 842 * @param elem the element to find
808 * @return the index of the element or a negative 843 * @return the index of the element or the size of the list when the element is not found
809 * value when the element is not found 844 * @see cxListIndexValid()
810 */ 845 */
811 cx_attr_nonnull 846 cx_attr_nonnull
812 cx_attr_nodiscard 847 cx_attr_nodiscard
813 static inline ssize_t cxListFind( 848 static inline size_t cxListFind(
814 const CxList *list, 849 const CxList *list,
815 const void *elem 850 const void *elem
816 ) { 851 ) {
817 return list->cl->find_remove((CxList*)list, elem, false); 852 return list->cl->find_remove((CxList*)list, elem, false);
818 } 853 }
819 854
820 /** 855 /**
856 * Checks if the specified index is within bounds.
857 *
858 * @param list the list
859 * @param index the index
860 * @retval true if the index is within bounds
861 * @retval false if the index is out of bounds
862 */
863 cx_attr_nonnull
864 cx_attr_nodiscard
865 static inline bool cxListIndexValid(const CxList *list, size_t index) {
866 return index < list->collection.size;
867 }
868
869 /**
821 * Removes and returns the index of the first element that equals @p elem. 870 * Removes and returns the index of the first element that equals @p elem.
822 * 871 *
823 * Determining equality is performed by the list's comparator function. 872 * Determining equality is performed by the list's comparator function.
824 * 873 *
825 * @param list the list 874 * @param list the list
826 * @param elem the element to find and remove 875 * @param elem the element to find and remove
827 * @return the index of the now removed element or a negative 876 * @return the index of the now removed element or the list size
828 * value when the element is not found or could not be removed 877 * when the element is not found or could not be removed
829 */ 878 * @see cxListIndexValid()
830 cx_attr_nonnull 879 */
831 static inline ssize_t cxListFindRemove( 880 cx_attr_nonnull
881 static inline size_t cxListFindRemove(
832 CxList *list, 882 CxList *list,
833 const void *elem 883 const void *elem
834 ) { 884 ) {
835 return list->cl->find_remove(list, elem, true); 885 return list->cl->find_remove(list, elem, true);
836 } 886 }
843 * @param list the list 893 * @param list the list
844 */ 894 */
845 cx_attr_nonnull 895 cx_attr_nonnull
846 static inline void cxListSort(CxList *list) { 896 static inline void cxListSort(CxList *list) {
847 list->cl->sort(list); 897 list->cl->sort(list);
898 list->collection.sorted = true;
848 } 899 }
849 900
850 /** 901 /**
851 * Reverses the order of the items. 902 * Reverses the order of the items.
852 * 903 *
853 * @param list the list 904 * @param list the list
854 */ 905 */
855 cx_attr_nonnull 906 cx_attr_nonnull
856 static inline void cxListReverse(CxList *list) { 907 static inline void cxListReverse(CxList *list) {
908 // still sorted, but not according to the cmp_func
909 list->collection.sorted = false;
857 list->cl->reverse(list); 910 list->cl->reverse(list);
858 } 911 }
859 912
860 /** 913 /**
861 * Compares a list to another list of the same type. 914 * Compares a list to another list of the same type.
871 * @retval positive the first list is larger 924 * @retval positive the first list is larger
872 * or the first non-equal element in the first list is larger 925 * or the first non-equal element in the first list is larger
873 */ 926 */
874 cx_attr_nonnull 927 cx_attr_nonnull
875 cx_attr_nodiscard 928 cx_attr_nodiscard
929 cx_attr_export
876 int cxListCompare( 930 int cxListCompare(
877 const CxList *list, 931 const CxList *list,
878 const CxList *other 932 const CxList *other
879 ); 933 );
880 934
883 * 937 *
884 * Also calls the content destructor functions for each element, if specified. 938 * Also calls the content destructor functions for each element, if specified.
885 * 939 *
886 * @param list the list which shall be freed 940 * @param list the list which shall be freed
887 */ 941 */
942 cx_attr_export
888 void cxListFree(CxList *list); 943 void cxListFree(CxList *list);
889 944
890 /** 945 /**
891 * A shared instance of an empty list. 946 * A shared instance of an empty list.
892 * 947 *
893 * Writing to that list is not allowed. 948 * Writing to that list is not allowed.
894 * 949 *
895 * You can use this is a placeholder for initializing CxList pointers 950 * You can use this is a placeholder for initializing CxList pointers
896 * for which you do not want to reserve memory right from the beginning. 951 * for which you do not want to reserve memory right from the beginning.
897 */ 952 */
953 cx_attr_export
898 extern CxList *const cxEmptyList; 954 extern CxList *const cxEmptyList;
899 955
900 956
901 #ifdef __cplusplus 957 #ifdef __cplusplus
902 } // extern "C" 958 } // extern "C"

mercurial