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; |