61 ptrdiff_t loc_advance, |
62 ptrdiff_t loc_advance, |
62 ptrdiff_t loc_data, |
63 ptrdiff_t loc_data, |
63 cx_compare_func cmp_func, |
64 cx_compare_func cmp_func, |
64 void const *elem |
65 void const *elem |
65 ) { |
66 ) { |
|
67 void *dummy; |
|
68 return cx_linked_list_find_node( |
|
69 &dummy, start, |
|
70 loc_advance, loc_data, |
|
71 cmp_func, elem |
|
72 ); |
|
73 } |
|
74 |
|
75 ssize_t cx_linked_list_find_node( |
|
76 void **result, |
|
77 void const *start, |
|
78 ptrdiff_t loc_advance, |
|
79 ptrdiff_t loc_data, |
|
80 cx_compare_func cmp_func, |
|
81 void const *elem |
|
82 ) { |
|
83 assert(result != NULL); |
66 assert(start != NULL); |
84 assert(start != NULL); |
67 assert(loc_advance >= 0); |
85 assert(loc_advance >= 0); |
68 assert(loc_data >= 0); |
86 assert(loc_data >= 0); |
69 assert(cmp_func); |
87 assert(cmp_func); |
70 |
88 |
71 void const *node = start; |
89 void const *node = start; |
72 ssize_t index = 0; |
90 ssize_t index = 0; |
73 do { |
91 do { |
74 void *current = ll_data(node); |
92 void *current = ll_data(node); |
75 if (cmp_func(current, elem) == 0) { |
93 if (cmp_func(current, elem) == 0) { |
|
94 *result = (void*) node; |
76 return index; |
95 return index; |
77 } |
96 } |
78 node = ll_advance(node); |
97 node = ll_advance(node); |
79 index++; |
98 index++; |
80 } while (node != NULL); |
99 } while (node != NULL); |
|
100 *result = NULL; |
81 return -1; |
101 return -1; |
82 } |
102 } |
83 |
103 |
84 void *cx_linked_list_first( |
104 void *cx_linked_list_first( |
85 void const *node, |
105 void const *node, |
481 |
499 |
482 static cx_linked_list_node *cx_ll_node_at( |
500 static cx_linked_list_node *cx_ll_node_at( |
483 cx_linked_list const *list, |
501 cx_linked_list const *list, |
484 size_t index |
502 size_t index |
485 ) { |
503 ) { |
486 if (index >= list->base.size) { |
504 if (index >= list->base.collection.size) { |
487 return NULL; |
505 return NULL; |
488 } else if (index > list->base.size / 2) { |
506 } else if (index > list->base.collection.size / 2) { |
489 return cx_linked_list_at(list->end, list->base.size - 1, CX_LL_LOC_PREV, index); |
507 return cx_linked_list_at(list->end, list->base.collection.size - 1, CX_LL_LOC_PREV, index); |
490 } else { |
508 } else { |
491 return cx_linked_list_at(list->begin, 0, CX_LL_LOC_NEXT, index); |
509 return cx_linked_list_at(list->begin, 0, CX_LL_LOC_NEXT, index); |
492 } |
510 } |
493 } |
511 } |
494 |
512 |
497 cx_linked_list_node *node, |
515 cx_linked_list_node *node, |
498 void const *elem |
516 void const *elem |
499 ) { |
517 ) { |
500 |
518 |
501 // create the new new_node |
519 // create the new new_node |
502 cx_linked_list_node *new_node = cxMalloc(list->allocator, |
520 cx_linked_list_node *new_node = cxMalloc(list->collection.allocator, |
503 sizeof(cx_linked_list_node) + list->item_size); |
521 sizeof(cx_linked_list_node) + list->collection.elem_size); |
504 |
522 |
505 // sortir if failed |
523 // sortir if failed |
506 if (new_node == NULL) return 1; |
524 if (new_node == NULL) return 1; |
507 |
525 |
508 // initialize new new_node |
526 // initialize new new_node |
509 new_node->prev = new_node->next = NULL; |
527 new_node->prev = new_node->next = NULL; |
510 memcpy(new_node->payload, elem, list->item_size); |
528 memcpy(new_node->payload, elem, list->collection.elem_size); |
511 |
529 |
512 // insert |
530 // insert |
513 cx_linked_list *ll = (cx_linked_list *) list; |
531 cx_linked_list *ll = (cx_linked_list *) list; |
514 cx_linked_list_insert_chain( |
532 cx_linked_list_insert_chain( |
515 (void **) &ll->begin, (void **) &ll->end, |
533 (void **) &ll->begin, (void **) &ll->end, |
516 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, |
534 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, |
517 node, new_node, new_node |
535 node, new_node, new_node |
518 ); |
536 ); |
519 |
537 |
520 // increase the size and return |
538 // increase the size and return |
521 list->size++; |
539 list->collection.size++; |
522 return 0; |
540 return 0; |
523 } |
541 } |
524 |
542 |
525 static size_t cx_ll_insert_array( |
543 static size_t cx_ll_insert_array( |
526 struct cx_list_s *list, |
544 struct cx_list_s *list, |
527 size_t index, |
545 size_t index, |
528 void const *array, |
546 void const *array, |
529 size_t n |
547 size_t n |
530 ) { |
548 ) { |
531 // out-of bounds and corner case check |
549 // out-of bounds and corner case check |
532 if (index > list->size || n == 0) return 0; |
550 if (index > list->collection.size || n == 0) return 0; |
533 |
551 |
534 // find position efficiently |
552 // find position efficiently |
535 cx_linked_list_node *node = index == 0 ? NULL : cx_ll_node_at((cx_linked_list *) list, index - 1); |
553 cx_linked_list_node *node = index == 0 ? NULL : cx_ll_node_at((cx_linked_list *) list, index - 1); |
536 |
554 |
537 // perform first insert |
555 // perform first insert |
581 // remove |
599 // remove |
582 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
600 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
583 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
601 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
584 |
602 |
585 // adjust size |
603 // adjust size |
586 list->size--; |
604 list->collection.size--; |
587 |
605 |
588 // free and return |
606 // free and return |
589 cxFree(list->allocator, node); |
607 cxFree(list->collection.allocator, node); |
590 |
608 |
591 return 0; |
609 return 0; |
592 } |
610 } |
593 |
611 |
594 static void cx_ll_clear(struct cx_list_s *list) { |
612 static void cx_ll_clear(struct cx_list_s *list) { |
595 if (list->size == 0) return; |
613 if (list->collection.size == 0) return; |
596 |
614 |
597 cx_linked_list *ll = (cx_linked_list *) list; |
615 cx_linked_list *ll = (cx_linked_list *) list; |
598 cx_linked_list_node *node = ll->begin; |
616 cx_linked_list_node *node = ll->begin; |
599 while (node != NULL) { |
617 while (node != NULL) { |
600 cx_invoke_destructor(list, node->payload); |
618 cx_invoke_destructor(list, node->payload); |
601 cx_linked_list_node *next = node->next; |
619 cx_linked_list_node *next = node->next; |
602 cxFree(list->allocator, node); |
620 cxFree(list->collection.allocator, node); |
603 node = next; |
621 node = next; |
604 } |
622 } |
605 ll->begin = ll->end = NULL; |
623 ll->begin = ll->end = NULL; |
606 list->size = 0; |
624 list->collection.size = 0; |
607 } |
625 } |
608 |
626 |
609 #ifndef CX_LINKED_LIST_SWAP_SBO_SIZE |
627 #ifndef CX_LINKED_LIST_SWAP_SBO_SIZE |
610 #define CX_LINKED_LIST_SWAP_SBO_SIZE 128 |
628 #define CX_LINKED_LIST_SWAP_SBO_SIZE 128 |
611 #endif |
629 #endif |
|
630 unsigned cx_linked_list_swap_sbo_size = CX_LINKED_LIST_SWAP_SBO_SIZE; |
612 |
631 |
613 static int cx_ll_swap( |
632 static int cx_ll_swap( |
614 struct cx_list_s *list, |
633 struct cx_list_s *list, |
615 size_t i, |
634 size_t i, |
616 size_t j |
635 size_t j |
617 ) { |
636 ) { |
618 if (i >= list->size || j >= list->size) return 1; |
637 if (i >= list->collection.size || j >= list->collection.size) return 1; |
619 if (i == j) return 0; |
638 if (i == j) return 0; |
620 |
639 |
621 // perform an optimized search that finds both elements in one run |
640 // perform an optimized search that finds both elements in one run |
622 cx_linked_list *ll = (cx_linked_list *) list; |
641 cx_linked_list *ll = (cx_linked_list *) list; |
623 size_t mid = list->size / 2; |
642 size_t mid = list->collection.size / 2; |
624 size_t left, right; |
643 size_t left, right; |
625 if (i < j) { |
644 if (i < j) { |
626 left = i; |
645 left = i; |
627 right = j; |
646 right = j; |
628 } else { |
647 } else { |
631 } |
650 } |
632 cx_linked_list_node *nleft, *nright; |
651 cx_linked_list_node *nleft, *nright; |
633 if (left < mid && right < mid) { |
652 if (left < mid && right < mid) { |
634 // case 1: both items left from mid |
653 // case 1: both items left from mid |
635 nleft = cx_ll_node_at(ll, left); |
654 nleft = cx_ll_node_at(ll, left); |
|
655 assert(nleft != NULL); |
636 nright = nleft; |
656 nright = nleft; |
637 for (size_t c = left; c < right; c++) { |
657 for (size_t c = left; c < right; c++) { |
638 nright = nright->next; |
658 nright = nright->next; |
639 } |
659 } |
640 } else if (left >= mid && right >= mid) { |
660 } else if (left >= mid && right >= mid) { |
641 // case 2: both items right from mid |
661 // case 2: both items right from mid |
642 nright = cx_ll_node_at(ll, right); |
662 nright = cx_ll_node_at(ll, right); |
|
663 assert(nright != NULL); |
643 nleft = nright; |
664 nleft = nright; |
644 for (size_t c = right; c > left; c--) { |
665 for (size_t c = right; c > left; c--) { |
645 nleft = nleft->prev; |
666 nleft = nleft->prev; |
646 } |
667 } |
647 } else { |
668 } else { |
648 // case 3: one item left, one item right |
669 // case 3: one item left, one item right |
649 |
670 |
650 // chose the closest to begin / end |
671 // chose the closest to begin / end |
651 size_t closest; |
672 size_t closest; |
652 size_t other; |
673 size_t other; |
653 size_t diff2boundary = list->size - right - 1; |
674 size_t diff2boundary = list->collection.size - right - 1; |
654 if (left <= diff2boundary) { |
675 if (left <= diff2boundary) { |
655 closest = left; |
676 closest = left; |
656 other = right; |
677 other = right; |
657 nleft = cx_ll_node_at(ll, left); |
678 nleft = cx_ll_node_at(ll, left); |
658 } else { |
679 } else { |
733 cx_linked_list *ll = (cx_linked_list *) list; |
754 cx_linked_list *ll = (cx_linked_list *) list; |
734 cx_linked_list_node *node = cx_ll_node_at(ll, index); |
755 cx_linked_list_node *node = cx_ll_node_at(ll, index); |
735 return node == NULL ? NULL : node->payload; |
756 return node == NULL ? NULL : node->payload; |
736 } |
757 } |
737 |
758 |
738 static ssize_t cx_ll_find( |
759 static ssize_t cx_ll_find_remove( |
739 struct cx_list_s const *list, |
760 struct cx_list_s *list, |
740 void const *elem |
761 void const *elem, |
741 ) { |
762 bool remove |
742 return cx_linked_list_find(((cx_linked_list *) list)->begin, |
763 ) { |
743 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
764 if (remove) { |
744 list->cmpfunc, elem); |
765 cx_linked_list *ll = ((cx_linked_list *) list); |
|
766 cx_linked_list_node *node; |
|
767 ssize_t index = cx_linked_list_find_node( |
|
768 (void **) &node, |
|
769 ll->begin, |
|
770 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
|
771 list->collection.cmpfunc, elem |
|
772 ); |
|
773 if (node != NULL) { |
|
774 cx_invoke_destructor(list, node->payload); |
|
775 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
|
776 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
|
777 list->collection.size--; |
|
778 cxFree(list->collection.allocator, node); |
|
779 } |
|
780 return index; |
|
781 } else { |
|
782 return cx_linked_list_find( |
|
783 ((cx_linked_list *) list)->begin, |
|
784 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
|
785 list->collection.cmpfunc, elem |
|
786 ); |
|
787 } |
745 } |
788 } |
746 |
789 |
747 static void cx_ll_sort(struct cx_list_s *list) { |
790 static void cx_ll_sort(struct cx_list_s *list) { |
748 cx_linked_list *ll = (cx_linked_list *) list; |
791 cx_linked_list *ll = (cx_linked_list *) list; |
749 cx_linked_list_sort((void **) &ll->begin, (void **) &ll->end, |
792 cx_linked_list_sort((void **) &ll->begin, (void **) &ll->end, |
750 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
793 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
751 list->cmpfunc); |
794 list->collection.cmpfunc); |
752 } |
795 } |
753 |
796 |
754 static void cx_ll_reverse(struct cx_list_s *list) { |
797 static void cx_ll_reverse(struct cx_list_s *list) { |
755 cx_linked_list *ll = (cx_linked_list *) list; |
798 cx_linked_list *ll = (cx_linked_list *) list; |
756 cx_linked_list_reverse((void **) &ll->begin, (void **) &ll->end, CX_LL_LOC_PREV, CX_LL_LOC_NEXT); |
799 cx_linked_list_reverse((void **) &ll->begin, (void **) &ll->end, CX_LL_LOC_PREV, CX_LL_LOC_NEXT); |
762 ) { |
805 ) { |
763 cx_linked_list *left = (cx_linked_list *) list; |
806 cx_linked_list *left = (cx_linked_list *) list; |
764 cx_linked_list *right = (cx_linked_list *) other; |
807 cx_linked_list *right = (cx_linked_list *) other; |
765 return cx_linked_list_compare(left->begin, right->begin, |
808 return cx_linked_list_compare(left->begin, right->begin, |
766 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
809 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
767 list->cmpfunc); |
810 list->collection.cmpfunc); |
768 } |
811 } |
769 |
812 |
770 static bool cx_ll_iter_valid(void const *it) { |
813 static bool cx_ll_iter_valid(void const *it) { |
771 struct cx_iterator_s const *iter = it; |
814 struct cx_iterator_s const *iter = it; |
772 return iter->elem_handle != NULL; |
815 return iter->elem_handle != NULL; |
773 } |
816 } |
774 |
817 |
775 static void cx_ll_iter_next(void *it) { |
818 static void cx_ll_iter_next(void *it) { |
776 struct cx_iterator_base_s *itbase = it; |
819 struct cx_iterator_s *iter = it; |
777 if (itbase->remove) { |
820 if (iter->base.remove) { |
778 itbase->remove = false; |
821 iter->base.remove = false; |
779 struct cx_mut_iterator_s *iter = it; |
822 struct cx_list_s *list = iter->src_handle.m; |
780 struct cx_list_s *list = iter->src_handle; |
823 cx_linked_list *ll = iter->src_handle.m; |
781 cx_linked_list *ll = iter->src_handle; |
|
782 cx_linked_list_node *node = iter->elem_handle; |
824 cx_linked_list_node *node = iter->elem_handle; |
783 iter->elem_handle = node->next; |
825 iter->elem_handle = node->next; |
784 cx_invoke_destructor(list, node->payload); |
826 cx_invoke_destructor(list, node->payload); |
785 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
827 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
786 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
828 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
787 list->size--; |
829 list->collection.size--; |
788 cxFree(list->allocator, node); |
830 cxFree(list->collection.allocator, node); |
789 } else { |
831 } else { |
790 struct cx_iterator_s *iter = it; |
|
791 iter->index++; |
832 iter->index++; |
792 cx_linked_list_node *node = iter->elem_handle; |
833 cx_linked_list_node *node = iter->elem_handle; |
793 iter->elem_handle = node->next; |
834 iter->elem_handle = node->next; |
794 } |
835 } |
795 } |
836 } |
796 |
837 |
797 static void cx_ll_iter_prev(void *it) { |
838 static void cx_ll_iter_prev(void *it) { |
798 struct cx_iterator_base_s *itbase = it; |
839 struct cx_iterator_s *iter = it; |
799 if (itbase->remove) { |
840 if (iter->base.remove) { |
800 itbase->remove = false; |
841 iter->base.remove = false; |
801 struct cx_mut_iterator_s *iter = it; |
842 struct cx_list_s *list = iter->src_handle.m; |
802 struct cx_list_s *list = iter->src_handle; |
843 cx_linked_list *ll = iter->src_handle.m; |
803 cx_linked_list *ll = iter->src_handle; |
|
804 cx_linked_list_node *node = iter->elem_handle; |
844 cx_linked_list_node *node = iter->elem_handle; |
805 iter->elem_handle = node->prev; |
845 iter->elem_handle = node->prev; |
806 iter->index--; |
846 iter->index--; |
807 cx_invoke_destructor(list, node->payload); |
847 cx_invoke_destructor(list, node->payload); |
808 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
848 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
809 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
849 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
810 list->size--; |
850 list->collection.size--; |
811 cxFree(list->allocator, node); |
851 cxFree(list->collection.allocator, node); |
812 } else { |
852 } else { |
813 struct cx_iterator_s *iter = it; |
|
814 iter->index--; |
853 iter->index--; |
815 cx_linked_list_node *node = iter->elem_handle; |
854 cx_linked_list_node *node = iter->elem_handle; |
816 iter->elem_handle = node->prev; |
855 iter->elem_handle = node->prev; |
817 } |
856 } |
818 } |
857 } |
821 struct cx_iterator_s const *iter = it; |
860 struct cx_iterator_s const *iter = it; |
822 cx_linked_list_node *node = iter->elem_handle; |
861 cx_linked_list_node *node = iter->elem_handle; |
823 return node->payload; |
862 return node->payload; |
824 } |
863 } |
825 |
864 |
826 static bool cx_ll_iter_flag_rm(void *it) { |
|
827 struct cx_iterator_base_s *iter = it; |
|
828 if (iter->mutating) { |
|
829 iter->remove = true; |
|
830 return true; |
|
831 } else { |
|
832 return false; |
|
833 } |
|
834 } |
|
835 |
|
836 static CxIterator cx_ll_iterator( |
865 static CxIterator cx_ll_iterator( |
837 struct cx_list_s const *list, |
866 struct cx_list_s const *list, |
838 size_t index, |
867 size_t index, |
839 bool backwards |
868 bool backwards |
840 ) { |
869 ) { |
841 CxIterator iter; |
870 CxIterator iter; |
842 iter.index = index; |
871 iter.index = index; |
843 iter.src_handle = list; |
872 iter.src_handle.c = list; |
844 iter.elem_handle = cx_ll_node_at((cx_linked_list const *) list, index); |
873 iter.elem_handle = cx_ll_node_at((cx_linked_list const *) list, index); |
|
874 iter.elem_size = list->collection.elem_size; |
|
875 iter.elem_count = list->collection.size; |
845 iter.base.valid = cx_ll_iter_valid; |
876 iter.base.valid = cx_ll_iter_valid; |
846 iter.base.current = cx_ll_iter_current; |
877 iter.base.current = cx_ll_iter_current; |
847 iter.base.next = backwards ? cx_ll_iter_prev : cx_ll_iter_next; |
878 iter.base.next = backwards ? cx_ll_iter_prev : cx_ll_iter_next; |
848 iter.base.flag_removal = cx_ll_iter_flag_rm; |
|
849 iter.base.mutating = false; |
879 iter.base.mutating = false; |
850 iter.base.remove = false; |
880 iter.base.remove = false; |
851 return iter; |
881 return iter; |
852 } |
882 } |
853 |
883 |
854 static int cx_ll_insert_iter( |
884 static int cx_ll_insert_iter( |
855 CxMutIterator *iter, |
885 CxIterator *iter, |
856 void const *elem, |
886 void const *elem, |
857 int prepend |
887 int prepend |
858 ) { |
888 ) { |
859 struct cx_list_s *list = iter->src_handle; |
889 struct cx_list_s *list = iter->src_handle.m; |
860 cx_linked_list_node *node = iter->elem_handle; |
890 cx_linked_list_node *node = iter->elem_handle; |
861 if (node != NULL) { |
891 if (node != NULL) { |
862 assert(prepend >= 0 && prepend <= 1); |
892 assert(prepend >= 0 && prepend <= 1); |
863 cx_linked_list_node *choice[2] = {node, node->prev}; |
893 cx_linked_list_node *choice[2] = {node, node->prev}; |
864 int result = cx_ll_insert_at(list, choice[prepend], elem); |
894 int result = cx_ll_insert_at(list, choice[prepend], elem); |
865 iter->index += prepend * (0 == result); |
895 iter->index += prepend * (0 == result); |
866 return result; |
896 return result; |
867 } else { |
897 } else { |
868 int result = cx_ll_insert_element(list, list->size, elem); |
898 int result = cx_ll_insert_element(list, list->collection.size, elem); |
869 iter->index = list->size; |
899 iter->index = list->collection.size; |
870 return result; |
900 return result; |
871 } |
901 } |
872 } |
902 } |
873 |
903 |
874 static void cx_ll_destructor(CxList *list) { |
904 static void cx_ll_destructor(CxList *list) { |
892 cx_ll_insert_iter, |
922 cx_ll_insert_iter, |
893 cx_ll_remove, |
923 cx_ll_remove, |
894 cx_ll_clear, |
924 cx_ll_clear, |
895 cx_ll_swap, |
925 cx_ll_swap, |
896 cx_ll_at, |
926 cx_ll_at, |
897 cx_ll_find, |
927 cx_ll_find_remove, |
898 cx_ll_sort, |
928 cx_ll_sort, |
899 cx_ll_compare, |
929 cx_ll_compare, |
900 cx_ll_reverse, |
930 cx_ll_reverse, |
901 cx_ll_iterator, |
931 cx_ll_iterator, |
902 }; |
932 }; |
903 |
933 |
904 CxList *cxLinkedListCreate( |
934 CxList *cxLinkedListCreate( |
905 CxAllocator const *allocator, |
935 CxAllocator const *allocator, |
906 cx_compare_func comparator, |
936 cx_compare_func comparator, |
907 size_t item_size |
937 size_t elem_size |
908 ) { |
938 ) { |
909 if (allocator == NULL) { |
939 if (allocator == NULL) { |
910 allocator = cxDefaultAllocator; |
940 allocator = cxDefaultAllocator; |
911 } |
941 } |
912 |
942 |
913 cx_linked_list *list = cxCalloc(allocator, 1, sizeof(cx_linked_list)); |
943 cx_linked_list *list = cxCalloc(allocator, 1, sizeof(cx_linked_list)); |
914 if (list == NULL) return NULL; |
944 if (list == NULL) return NULL; |
915 |
945 |
916 list->base.cl = &cx_linked_list_class; |
946 list->base.cl = &cx_linked_list_class; |
917 list->base.allocator = allocator; |
947 list->base.collection.allocator = allocator; |
918 list->base.cmpfunc = comparator; |
948 |
919 |
949 if (elem_size > 0) { |
920 if (item_size > 0) { |
950 list->base.collection.elem_size = elem_size; |
921 list->base.item_size = item_size; |
951 list->base.collection.cmpfunc = comparator; |
922 } else { |
952 } else { |
|
953 list->base.collection.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator; |
923 cxListStorePointers((CxList *) list); |
954 cxListStorePointers((CxList *) list); |
924 } |
955 } |
925 |
956 |
926 return (CxList *) list; |
957 return (CxList *) list; |
927 } |
958 } |