| 567 cx_linked_list_node *node = cx_ll_node_at(ll, index); |
567 cx_linked_list_node *node = cx_ll_node_at(ll, index); |
| 568 |
568 |
| 569 // out-of-bounds check |
569 // out-of-bounds check |
| 570 if (node == NULL) return 1; |
570 if (node == NULL) return 1; |
| 571 |
571 |
| |
572 // element destruction |
| |
573 if (list->content_destructor_type != CX_DESTRUCTOR_NONE) { |
| |
574 cx_list_invoke_destructor(list, node->payload); |
| |
575 } |
| |
576 |
| 572 // remove |
577 // remove |
| 573 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
578 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
| 574 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
579 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
| 575 |
580 |
| 576 // adjust size |
581 // adjust size |
| 578 |
583 |
| 579 // free and return |
584 // free and return |
| 580 cxFree(list->allocator, node); |
585 cxFree(list->allocator, node); |
| 581 |
586 |
| 582 return 0; |
587 return 0; |
| |
588 } |
| |
589 |
| |
590 static void cx_ll_clear(struct cx_list_s *list) { |
| |
591 if (list->size == 0) return; |
| |
592 |
| |
593 cx_linked_list *ll = (cx_linked_list *) list; |
| |
594 cx_linked_list_node *node = ll->begin; |
| |
595 |
| |
596 // looks super redundant, but avoids repeatedly checking |
| |
597 // the destructor type for each element |
| |
598 switch (list->content_destructor_type) { |
| |
599 case CX_DESTRUCTOR_SIMPLE: { |
| |
600 while (node != NULL) { |
| |
601 list->simple_destructor(node->payload); |
| |
602 cx_linked_list_node *next = node->next; |
| |
603 cxFree(list->allocator, node); |
| |
604 node = next; |
| |
605 } |
| |
606 break; |
| |
607 } |
| |
608 case CX_DESTRUCTOR_ADVANCED: { |
| |
609 while (node != NULL) { |
| |
610 list->advanced_destructor.func(list->advanced_destructor.data, |
| |
611 node->payload); |
| |
612 cx_linked_list_node *next = node->next; |
| |
613 cxFree(list->allocator, node); |
| |
614 node = next; |
| |
615 } |
| |
616 break; |
| |
617 } |
| |
618 case CX_DESTRUCTOR_NONE: { |
| |
619 while (node != NULL) { |
| |
620 cx_linked_list_node *next = node->next; |
| |
621 cxFree(list->allocator, node); |
| |
622 node = next; |
| |
623 } |
| |
624 break; |
| |
625 } |
| |
626 } |
| |
627 |
| |
628 ll->begin = ll->end = NULL; |
| |
629 list->size = 0; |
| 583 } |
630 } |
| 584 |
631 |
| 585 #ifndef CX_LINKED_LIST_SWAP_SBO_SIZE |
632 #ifndef CX_LINKED_LIST_SWAP_SBO_SIZE |
| 586 #define CX_LINKED_LIST_SWAP_SBO_SIZE 16 |
633 #define CX_LINKED_LIST_SWAP_SBO_SIZE 16 |
| 587 #endif |
634 #endif |
| 751 static void cx_ll_iter_next(void *it) { |
798 static void cx_ll_iter_next(void *it) { |
| 752 struct cx_iterator_base_s *itbase = it; |
799 struct cx_iterator_base_s *itbase = it; |
| 753 if (itbase->remove) { |
800 if (itbase->remove) { |
| 754 itbase->remove = false; |
801 itbase->remove = false; |
| 755 struct cx_mut_iterator_s *iter = it; |
802 struct cx_mut_iterator_s *iter = it; |
| |
803 struct cx_list_s *list = iter->src_handle; |
| 756 cx_linked_list *ll = iter->src_handle; |
804 cx_linked_list *ll = iter->src_handle; |
| 757 cx_linked_list_node *node = iter->elem_handle; |
805 cx_linked_list_node *node = iter->elem_handle; |
| 758 iter->elem_handle = node->next; |
806 iter->elem_handle = node->next; |
| |
807 if (list->content_destructor_type != CX_DESTRUCTOR_NONE) { |
| |
808 cx_list_invoke_destructor(list, node->payload); |
| |
809 } |
| 759 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
810 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
| 760 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
811 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
| 761 ll->base.size--; |
812 list->size--; |
| 762 cxFree(ll->base.allocator, node); |
813 cxFree(list->allocator, node); |
| 763 } else { |
814 } else { |
| 764 struct cx_iterator_s *iter = it; |
815 struct cx_iterator_s *iter = it; |
| 765 iter->index++; |
816 iter->index++; |
| 766 cx_linked_list_node *node = iter->elem_handle; |
817 cx_linked_list_node *node = iter->elem_handle; |
| 767 iter->elem_handle = node->next; |
818 iter->elem_handle = node->next; |
| 771 static void cx_ll_iter_prev(void *it) { |
822 static void cx_ll_iter_prev(void *it) { |
| 772 struct cx_iterator_base_s *itbase = it; |
823 struct cx_iterator_base_s *itbase = it; |
| 773 if (itbase->remove) { |
824 if (itbase->remove) { |
| 774 itbase->remove = false; |
825 itbase->remove = false; |
| 775 struct cx_mut_iterator_s *iter = it; |
826 struct cx_mut_iterator_s *iter = it; |
| |
827 struct cx_list_s *list = iter->src_handle; |
| 776 cx_linked_list *ll = iter->src_handle; |
828 cx_linked_list *ll = iter->src_handle; |
| 777 cx_linked_list_node *node = iter->elem_handle; |
829 cx_linked_list_node *node = iter->elem_handle; |
| 778 iter->elem_handle = node->prev; |
830 iter->elem_handle = node->prev; |
| 779 iter->index--; |
831 iter->index--; |
| |
832 if (list->content_destructor_type != CX_DESTRUCTOR_NONE) { |
| |
833 cx_list_invoke_destructor(list, node->payload); |
| |
834 } |
| 780 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
835 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
| 781 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
836 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
| 782 ll->base.size--; |
837 list->size--; |
| 783 cxFree(ll->base.allocator, node); |
838 cxFree(list->allocator, node); |
| 784 } else { |
839 } else { |
| 785 struct cx_iterator_s *iter = it; |
840 struct cx_iterator_s *iter = it; |
| 786 iter->index--; |
841 iter->index--; |
| 787 cx_linked_list_node *node = iter->elem_handle; |
842 cx_linked_list_node *node = iter->elem_handle; |
| 788 iter->elem_handle = node->prev; |
843 iter->elem_handle = node->prev; |