479 } else { |
479 } else { |
480 return cx_linked_list_at(list->begin, 0, CX_LL_LOC_NEXT, index); |
480 return cx_linked_list_at(list->begin, 0, CX_LL_LOC_NEXT, index); |
481 } |
481 } |
482 } |
482 } |
483 |
483 |
484 static int cx_ll_insert( |
484 static int cx_ll_insert_at( |
485 cx_list_s *list, |
485 cx_list_s *list, |
486 size_t index, |
486 cx_linked_list_node *node, |
487 void const *elem |
487 void const *elem |
488 ) { |
488 ) { |
489 // out-of bounds check |
|
490 if (index > list->size) return 1; |
|
491 |
|
492 // cast a linked list pointer |
|
493 cx_linked_list *ll = (cx_linked_list *) list; |
|
494 |
489 |
495 // create the new new_node |
490 // create the new new_node |
496 cx_linked_list_node *new_node = cxMalloc(list->allocator, |
491 cx_linked_list_node *new_node = cxMalloc(list->allocator, |
497 sizeof(cx_linked_list_node) + list->itemsize); |
492 sizeof(cx_linked_list_node) + list->itemsize); |
498 |
493 |
501 |
496 |
502 // initialize new new_node |
497 // initialize new new_node |
503 new_node->prev = new_node->next = NULL; |
498 new_node->prev = new_node->next = NULL; |
504 memcpy(new_node->payload, elem, list->itemsize); |
499 memcpy(new_node->payload, elem, list->itemsize); |
505 |
500 |
506 // find position efficiently |
|
507 cx_linked_list_node *node = index == 0 ? NULL : cx_ll_node_at(ll, index - 1); |
|
508 |
|
509 // insert |
501 // insert |
|
502 cx_linked_list *ll = (cx_linked_list *) list; |
510 cx_linked_list_insert_chain( |
503 cx_linked_list_insert_chain( |
511 (void **) &ll->begin, (void **) &ll->end, |
504 (void **) &ll->begin, (void **) &ll->end, |
512 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, |
505 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, |
513 node, new_node, new_node |
506 node, new_node, new_node |
514 ); |
507 ); |
515 |
508 |
516 // increase the size and return |
509 // increase the size and return |
517 list->size++; |
510 list->size++; |
518 return 0; |
511 return 0; |
|
512 } |
|
513 |
|
514 static int cx_ll_insert( |
|
515 cx_list_s *list, |
|
516 size_t index, |
|
517 void const *elem |
|
518 ) { |
|
519 // out-of bounds check |
|
520 if (index > list->size) return 1; |
|
521 |
|
522 // find position efficiently |
|
523 cx_linked_list_node *node = index == 0 ? NULL : cx_ll_node_at((cx_linked_list *) list, index - 1); |
|
524 |
|
525 // perform insert |
|
526 return cx_ll_insert_at(list, node, elem); |
519 } |
527 } |
520 |
528 |
521 static int cx_ll_add( |
529 static int cx_ll_add( |
522 cx_list_s *list, |
530 cx_list_s *list, |
523 void const *elem |
531 void const *elem |
693 CxIterator iter = cx_ll_iterator(list, index); |
701 CxIterator iter = cx_ll_iterator(list, index); |
694 iter.current = cx_pll_iter_current; |
702 iter.current = cx_pll_iter_current; |
695 return iter; |
703 return iter; |
696 } |
704 } |
697 |
705 |
|
706 static int cx_ll_insert_iter( |
|
707 CxIterator *iter, |
|
708 void const *elem, |
|
709 int prepend |
|
710 ) { |
|
711 cx_list_s *list = iter->src_handle; |
|
712 cx_linked_list_node *node = iter->elem_handle; |
|
713 if (node != NULL) { |
|
714 assert(prepend >= 0 && prepend <= 1); |
|
715 cx_linked_list_node *choice[2] = {node, node->prev}; |
|
716 int result = cx_ll_insert_at(list, choice[prepend], elem); |
|
717 iter->index += prepend * (0 == result); |
|
718 return result; |
|
719 } else { |
|
720 int result = cx_ll_insert(list, list->size, elem); |
|
721 iter->index = list->size; |
|
722 return result; |
|
723 } |
|
724 } |
|
725 |
|
726 static int cx_pll_insert_iter( |
|
727 CxIterator *iter, |
|
728 void const *elem, |
|
729 int prepend |
|
730 ) { |
|
731 return cx_ll_insert_iter(iter, &elem, prepend); |
|
732 } |
|
733 |
698 static cx_list_class cx_linked_list_class = { |
734 static cx_list_class cx_linked_list_class = { |
699 cx_ll_add, |
735 cx_ll_add, |
700 cx_ll_insert, |
736 cx_ll_insert, |
|
737 cx_ll_insert_iter, |
701 cx_ll_remove, |
738 cx_ll_remove, |
702 cx_ll_at, |
739 cx_ll_at, |
703 cx_ll_find, |
740 cx_ll_find, |
704 cx_ll_sort, |
741 cx_ll_sort, |
705 cx_ll_compare, |
742 cx_ll_compare, |
706 cx_ll_reverse, |
743 cx_ll_reverse, |
707 cx_ll_iterator, |
744 cx_ll_iterator |
708 }; |
745 }; |
709 |
746 |
710 static cx_list_class cx_pointer_linked_list_class = { |
747 static cx_list_class cx_pointer_linked_list_class = { |
711 cx_pll_add, |
748 cx_pll_add, |
712 cx_pll_insert, |
749 cx_pll_insert, |
|
750 cx_pll_insert_iter, |
713 cx_ll_remove, |
751 cx_ll_remove, |
714 cx_pll_at, |
752 cx_pll_at, |
715 cx_pll_find, |
753 cx_pll_find, |
716 cx_pll_sort, |
754 cx_pll_sort, |
717 cx_pll_compare, |
755 cx_pll_compare, |