641 return cx_linked_list_compare(left->begin, right->begin, |
641 return cx_linked_list_compare(left->begin, right->begin, |
642 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
642 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
643 left->follow_ptr, right->follow_ptr, list->cmpfunc); |
643 left->follow_ptr, right->follow_ptr, list->cmpfunc); |
644 } |
644 } |
645 |
645 |
646 static bool cx_ll_iter_valid(CxIterator const *iter) { |
646 static bool cx_ll_iter_valid(void const *it) { |
|
647 struct cx_iterator_s const *iter = it; |
647 return iter->elem_handle != NULL; |
648 return iter->elem_handle != NULL; |
648 } |
649 } |
649 |
650 |
650 static void cx_ll_iter_next(CxIterator *iter) { |
651 static void cx_ll_iter_next(void *it) { |
651 if (iter->remove) { |
652 struct cx_iterator_base_s *itbase = it; |
652 iter->remove = false; |
653 if (itbase->remove) { |
|
654 itbase->remove = false; |
|
655 struct cx_mut_iterator_s *iter = it; |
653 cx_linked_list *ll = iter->src_handle; |
656 cx_linked_list *ll = iter->src_handle; |
654 cx_linked_list_node *node = iter->elem_handle; |
657 cx_linked_list_node *node = iter->elem_handle; |
655 iter->elem_handle = node->next; |
658 iter->elem_handle = node->next; |
656 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
659 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
657 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
660 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
658 ll->base.size--; |
661 ll->base.size--; |
659 cxFree(ll->base.allocator, node); |
662 cxFree(ll->base.allocator, node); |
660 } else { |
663 } else { |
|
664 struct cx_iterator_s *iter = it; |
661 iter->index++; |
665 iter->index++; |
662 cx_linked_list_node *node = iter->elem_handle; |
666 cx_linked_list_node *node = iter->elem_handle; |
663 iter->elem_handle = node->next; |
667 iter->elem_handle = node->next; |
664 } |
668 } |
665 } |
669 } |
666 |
670 |
667 static void *cx_ll_iter_current(CxIterator const *iter) { |
671 static void *cx_ll_iter_current(void const *it) { |
|
672 struct cx_iterator_s const *iter = it; |
668 cx_linked_list_node *node = iter->elem_handle; |
673 cx_linked_list_node *node = iter->elem_handle; |
669 return node->payload; |
674 return node->payload; |
670 } |
675 } |
671 |
676 |
672 static void *cx_pll_iter_current(CxIterator const *iter) { |
677 static void *cx_pll_iter_current(void const *it) { |
|
678 struct cx_iterator_s const *iter = it; |
673 cx_linked_list_node *node = iter->elem_handle; |
679 cx_linked_list_node *node = iter->elem_handle; |
674 return *(void **) node->payload; |
680 return *(void **) node->payload; |
675 } |
681 } |
676 |
682 |
|
683 static bool cx_ll_iter_flag_rm(void *it) { |
|
684 struct cx_iterator_base_s *iter = it; |
|
685 if (iter->mutating) { |
|
686 iter->remove = true; |
|
687 return true; |
|
688 } else { |
|
689 return false; |
|
690 } |
|
691 } |
|
692 |
677 static CxIterator cx_ll_iterator( |
693 static CxIterator cx_ll_iterator( |
678 struct cx_list_s *list, |
694 struct cx_list_s const *list, |
679 size_t index |
695 size_t index |
680 ) { |
696 ) { |
681 CxIterator iter; |
697 CxIterator iter; |
682 iter.index = index; |
698 iter.index = index; |
683 iter.src_handle = list; |
699 iter.src_handle = list; |
684 iter.elem_handle = cx_ll_node_at((cx_linked_list const *) list, index); |
700 iter.elem_handle = cx_ll_node_at((cx_linked_list const *) list, index); |
685 iter.valid = cx_ll_iter_valid; |
701 iter.base.valid = cx_ll_iter_valid; |
686 iter.current = cx_ll_iter_current; |
702 iter.base.current = cx_ll_iter_current; |
687 iter.next = cx_ll_iter_next; |
703 iter.base.next = cx_ll_iter_next; |
688 iter.remove = false; |
704 iter.base.flag_removal = cx_ll_iter_flag_rm; |
|
705 iter.base.mutating = false; |
|
706 iter.base.remove = false; |
689 return iter; |
707 return iter; |
690 } |
708 } |
691 |
709 |
692 static CxIterator cx_pll_iterator( |
710 static CxIterator cx_pll_iterator( |
|
711 struct cx_list_s const *list, |
|
712 size_t index |
|
713 ) { |
|
714 CxIterator iter = cx_ll_iterator(list, index); |
|
715 iter.base.current = cx_pll_iter_current; |
|
716 return iter; |
|
717 } |
|
718 |
|
719 static CxMutIterator cx_ll_mut_iterator( |
693 struct cx_list_s *list, |
720 struct cx_list_s *list, |
694 size_t index |
721 size_t index |
695 ) { |
722 ) { |
696 CxIterator iter = cx_ll_iterator(list, index); |
723 CxIterator it = cx_ll_iterator(list, index); |
697 iter.current = cx_pll_iter_current; |
724 it.base.mutating = true; |
|
725 |
|
726 // we know the iterators share the same memory layout |
|
727 CxMutIterator iter; |
|
728 memcpy(&iter, &it, sizeof(CxMutIterator)); |
698 return iter; |
729 return iter; |
699 } |
730 } |
700 |
731 |
|
732 static CxMutIterator cx_pll_mut_iterator( |
|
733 struct cx_list_s *list, |
|
734 size_t index |
|
735 ) { |
|
736 CxMutIterator iter = cx_ll_mut_iterator(list, index); |
|
737 iter.base.current = cx_pll_iter_current; |
|
738 return iter; |
|
739 } |
|
740 |
701 static int cx_ll_insert_iter( |
741 static int cx_ll_insert_iter( |
702 CxIterator *iter, |
742 CxMutIterator *iter, |
703 void const *elem, |
743 void const *elem, |
704 int prepend |
744 int prepend |
705 ) { |
745 ) { |
706 struct cx_list_s *list = iter->src_handle; |
746 struct cx_list_s *list = iter->src_handle; |
707 cx_linked_list_node *node = iter->elem_handle; |
747 cx_linked_list_node *node = iter->elem_handle; |