ucx/list.c

changeset 870
e167cf006213
parent 845
f3ab28ed22e5
child 943
9b5948aa5b90
equal deleted inserted replaced
869:6b7a178cff7c 870:e167cf006213
27 */ 27 */
28 28
29 #include "cx/list.h" 29 #include "cx/list.h"
30 30
31 #include <string.h> 31 #include <string.h>
32 #include <assert.h>
32 33
33 // <editor-fold desc="Store Pointers Functionality"> 34 // <editor-fold desc="Store Pointers Functionality">
34 35
35 static _Thread_local cx_compare_func cx_pl_cmpfunc_impl; 36 static _Thread_local cx_compare_func cx_pl_cmpfunc_impl;
36 37
112 static int cx_pl_insert_iter( 113 static int cx_pl_insert_iter(
113 struct cx_iterator_s *iter, 114 struct cx_iterator_s *iter,
114 const void *elem, 115 const void *elem,
115 int prepend 116 int prepend
116 ) { 117 ) {
117 struct cx_list_s *list = iter->src_handle.m; 118 struct cx_list_s *list = iter->src_handle;
118 return list->climpl->insert_iter(iter, &elem, prepend); 119 return list->climpl->insert_iter(iter, &elem, prepend);
119 } 120 }
120 121
121 static size_t cx_pl_remove( 122 static size_t cx_pl_remove(
122 struct cx_list_s *list, 123 struct cx_list_s *list,
243 const struct cx_list_s *list, 244 const struct cx_list_s *list,
244 size_t index, 245 size_t index,
245 cx_attr_unused bool backwards 246 cx_attr_unused bool backwards
246 ) { 247 ) {
247 CxIterator iter = {0}; 248 CxIterator iter = {0};
248 iter.src_handle.c = list; 249 iter.src_handle = (void*) list;
249 iter.index = index; 250 iter.index = index;
250 iter.base.valid = cx_emptyl_iter_valid; 251 iter.base.valid = cx_emptyl_iter_valid;
251 return iter; 252 return iter;
252 } 253 }
253 254
297 struct cx_list_s *list, 298 struct cx_list_s *list,
298 size_t index, 299 size_t index,
299 const void *data, 300 const void *data,
300 size_t n 301 size_t n
301 ) { 302 ) {
302 size_t elem_size = list->collection.elem_size;
303 const char *src = data; 303 const char *src = data;
304 size_t i = 0; 304 size_t i = 0;
305 for (; i < n; i++) { 305 for (; i < n; i++) {
306 if (NULL == invoke_list_func( 306 if (NULL == invoke_list_func(
307 insert_element, list, index + i, 307 insert_element, list, index + i, src)
308 src + i * elem_size)
309 ) { 308 ) {
310 return i; // LCOV_EXCL_LINE 309 return i; // LCOV_EXCL_LINE
310 }
311 if (src != NULL) {
312 src += list->collection.elem_size;
311 } 313 }
312 } 314 }
313 return i; 315 return i;
314 } 316 }
315 317
564 // lists are compatible 566 // lists are compatible
565 return list->cl->compare(list, other); 567 return list->cl->compare(list, other);
566 } 568 }
567 } 569 }
568 570
569 CxIterator cxListMutIteratorAt( 571 size_t cxListSize(const CxList *list) {
570 CxList *list, 572 return list->collection.size;
571 size_t index 573 }
572 ) { 574
573 if (list == NULL) list = cxEmptyList; 575 int cxListAdd(CxList *list, const void *elem) {
574 CxIterator it = list->cl->iterator(list, index, false); 576 list->collection.sorted = false;
575 it.base.mutating = true; 577 return list->cl->insert_element(list, list->collection.size, elem) == NULL;
576 return it; 578 }
577 } 579
578 580 size_t cxListAddArray(CxList *list, const void *array, size_t n) {
579 CxIterator cxListMutBackwardsIteratorAt( 581 list->collection.sorted = false;
580 CxList *list, 582 return list->cl->insert_array(list, list->collection.size, array, n);
581 size_t index 583 }
582 ) { 584
583 if (list == NULL) list = cxEmptyList; 585 int cxListInsert(CxList *list, size_t index, const void *elem) {
584 CxIterator it = list->cl->iterator(list, index, true); 586 list->collection.sorted = false;
585 it.base.mutating = true; 587 return list->cl->insert_element(list, index, elem) == NULL;
586 return it; 588 }
587 } 589
588 590 void *cxListEmplaceAt(CxList *list, size_t index) {
589 void cxListFree(CxList *list) { 591 list->collection.sorted = false;
590 if (list == NULL) return; 592 return list->cl->insert_element(list, index, NULL);
591 list->cl->deallocate(list); 593 }
592 } 594
593 595 void *cxListEmplace(CxList *list) {
594 int cxListSet( 596 list->collection.sorted = false;
595 CxList *list, 597 return list->cl->insert_element(list, list->collection.size, NULL);
596 size_t index, 598 }
597 const void *elem 599
598 ) { 600 static bool cx_list_emplace_iterator_valid(const void *it) {
601 const CxIterator *iter = it;
602 return iter->index < iter->elem_count;
603 }
604
605 CxIterator cxListEmplaceArrayAt(CxList *list, size_t index, size_t n) {
606 list->collection.sorted = false;
607 size_t c = list->cl->insert_array(list, index, NULL, n);
608 CxIterator iter = list->cl->iterator(list, index, false);
609 // tweak the fields of this iterator
610 iter.elem_count = c;
611 iter.index = 0;
612 // replace the valid function to abort iteration when c is reached
613 iter.base.valid = cx_list_emplace_iterator_valid;
614 // if we are storing pointers, we want to return the pure pointers.
615 // therefore, we must unwrap the "current" method
616 if (list->collection.store_pointer) {
617 iter.base.current = iter.base.current_impl;
618 }
619 return iter;
620 }
621
622 CxIterator cxListEmplaceArray(CxList *list, size_t n) {
623 return cxListEmplaceArrayAt(list, list->collection.size, n);
624 }
625
626 int cxListInsertSorted(CxList *list, const void *elem) {
627 assert(cxCollectionSorted(list));
628 list->collection.sorted = true;
629 const void *data = list->collection.store_pointer ? &elem : elem;
630 return list->cl->insert_sorted(list, data, 1) == 0;
631 }
632
633 int cxListInsertUnique(CxList *list, const void *elem) {
634 if (cxCollectionSorted(list)) {
635 list->collection.sorted = true;
636 const void *data = list->collection.store_pointer ? &elem : elem;
637 return list->cl->insert_unique(list, data, 1) == 0;
638 } else {
639 if (cxListContains(list, elem)) {
640 return 0;
641 } else {
642 return cxListAdd(list, elem);
643 }
644 }
645 }
646
647 size_t cxListInsertArray(CxList *list, size_t index, const void *array, size_t n) {
648 list->collection.sorted = false;
649 return list->cl->insert_array(list, index, array, n);
650 }
651
652 size_t cxListInsertSortedArray(CxList *list, const void *array, size_t n) {
653 assert(cxCollectionSorted(list));
654 list->collection.sorted = true;
655 return list->cl->insert_sorted(list, array, n);
656 }
657
658 size_t cxListInsertUniqueArray(CxList *list, const void *array, size_t n) {
659 if (cxCollectionSorted(list)) {
660 list->collection.sorted = true;
661 return list->cl->insert_unique(list, array, n);
662 } else {
663 const char *source = array;
664 for (size_t i = 0 ; i < n; i++) {
665 // note: this also checks elements added in a previous iteration
666 const void *data = list->collection.store_pointer ?
667 *((const void**)source) : source;
668 if (!cxListContains(list, data)) {
669 if (cxListAdd(list, data)) {
670 return i; // LCOV_EXCL_LINE
671 }
672 }
673 source += list->collection.elem_size;
674 }
675 return n;
676 }
677 }
678
679 int cxListInsertAfter(CxIterator *iter, const void *elem) {
680 CxList* list = (CxList*)iter->src_handle;
681 list->collection.sorted = false;
682 return list->cl->insert_iter(iter, elem, 0);
683 }
684
685 int cxListInsertBefore(CxIterator *iter, const void *elem) {
686 CxList* list = (CxList*)iter->src_handle;
687 list->collection.sorted = false;
688 return list->cl->insert_iter(iter, elem, 1);
689 }
690
691 int cxListRemove(CxList *list, size_t index) {
692 return list->cl->remove(list, index, 1, NULL) == 0;
693 }
694
695 int cxListRemoveAndGet(CxList *list, size_t index, void *targetbuf) {
696 return list->cl->remove(list, index, 1, targetbuf) == 0;
697 }
698
699 int cxListRemoveAndGetFirst(CxList *list, void *targetbuf) {
700 return list->cl->remove(list, 0, 1, targetbuf) == 0;
701 }
702
703 int cxListRemoveAndGetLast(CxList *list, void *targetbuf) {
704 // note: index may wrap - member function will catch that
705 return list->cl->remove(list, list->collection.size - 1, 1, targetbuf) == 0;
706 }
707
708 size_t cxListRemoveArray(CxList *list, size_t index, size_t num) {
709 return list->cl->remove(list, index, num, NULL);
710 }
711
712 size_t cxListRemoveArrayAndGet(CxList *list, size_t index, size_t num, void *targetbuf) {
713 return list->cl->remove(list, index, num, targetbuf);
714 }
715
716 void cxListClear(CxList *list) {
717 list->cl->clear(list);
718 list->collection.sorted = true; // empty lists are always sorted
719 }
720
721 int cxListSwap(CxList *list, size_t i, size_t j) {
722 list->collection.sorted = false;
723 return list->cl->swap(list, i, j);
724 }
725
726 void *cxListAt(const CxList *list, size_t index) {
727 return list->cl->at(list, index);
728 }
729
730 void *cxListFirst(const CxList *list) {
731 return list->cl->at(list, 0);
732 }
733
734 void *cxListLast(const CxList *list) {
735 return list->cl->at(list, list->collection.size - 1);
736 }
737
738 int cxListSet(CxList *list, size_t index, const void *elem) {
599 if (index >= list->collection.size) { 739 if (index >= list->collection.size) {
600 return 1; 740 return 1;
601 } 741 }
602 742
603 if (list->collection.store_pointer) { 743 if (list->collection.store_pointer) {
609 memcpy(target, elem, list->collection.elem_size); 749 memcpy(target, elem, list->collection.elem_size);
610 } 750 }
611 751
612 return 0; 752 return 0;
613 } 753 }
754
755 CxIterator cxListIteratorAt(const CxList *list, size_t index) {
756 if (list == NULL) list = cxEmptyList;
757 return list->cl->iterator(list, index, false);
758 }
759
760 CxIterator cxListBackwardsIteratorAt(const CxList *list, size_t index) {
761 if (list == NULL) list = cxEmptyList;
762 return list->cl->iterator(list, index, true);
763 }
764
765 CxIterator cxListIterator(const CxList *list) {
766 if (list == NULL) list = cxEmptyList;
767 return list->cl->iterator(list, 0, false);
768 }
769
770 CxIterator cxListBackwardsIterator(const CxList *list) {
771 if (list == NULL) list = cxEmptyList;
772 return list->cl->iterator(list, list->collection.size - 1, true);
773 }
774
775 size_t cxListFind(const CxList *list, const void *elem) {
776 return list->cl->find_remove((CxList*)list, elem, false);
777 }
778
779 bool cxListContains(const CxList* list, const void* elem) {
780 return list->cl->find_remove((CxList*)list, elem, false) < list->collection.size;
781 }
782
783 bool cxListIndexValid(const CxList *list, size_t index) {
784 return index < list->collection.size;
785 }
786
787 size_t cxListFindRemove(CxList *list, const void *elem) {
788 return list->cl->find_remove(list, elem, true);
789 }
790
791 void cxListSort(CxList *list) {
792 if (list->collection.sorted) return;
793 list->cl->sort(list);
794 list->collection.sorted = true;
795 }
796
797 void cxListReverse(CxList *list) {
798 // still sorted, but not according to the cmp_func
799 list->collection.sorted = false;
800 list->cl->reverse(list);
801 }
802
803 void cxListFree(CxList *list) {
804 if (list == NULL) return;
805 list->cl->deallocate(list);
806 }

mercurial