35 template <
typename TYPE,
typename ALLOC = allocator<TYPE>>
46 class chainNode final :
public wrapper<TYPE>{
57 explicit chainNode(
const TYPE& data = TYPE{}, chainNode* prev =
nullptr, chainNode* next =
nullptr);
68 chainNode(
const chainNode& other);
75 chainNode&
operator=(
const chainNode& other);
81 TYPE& getVal()
override;
87 const TYPE& getVal()
const override;
93 void setVal(TYPE data)
override;
99 chainNode* getPPrev()
const override;
105 chainNode* getPNext()
const override;
111 void setPPrev(chainNode* new_prev);
117 void setPNext(chainNode* new_next);
124 static void connect(chainNode* prev, chainNode* next);
131 using rebind_alloc_node =
typename ALLOC::template rebind_alloc<chainNode>;
136 rebind_alloc_node rebind_alloc{};
144 chainNode* findNode(
integer index)
const;
153 chainNode* createNode(
const TYPE& value = TYPE{}, chainNode* prev =
nullptr, chainNode* next =
nullptr);
160 void destroyNode(chainNode* node)
noexcept;
171 void firstAdd(chainNode* node);
177 chainNode* lastDelete();
182 void chainDestruction();
201 explicit Iterator(chainNode* ptr);
209 Iterator(
const Iterator& other);
249 explicit chain(ALLOC alloc = ALLOC{});
262 chain(
const std::initializer_list<TYPE>& list);
382 Iterator*
ends()
const override;
397 template <
typename TYPE,
typename ALLOC>
398 original::chain<TYPE, ALLOC>::chainNode::chainNode(
const TYPE& data, chainNode* prev, chainNode* next)
399 : data_(data), prev(prev), next(next) {}
401 template <
typename TYPE,
typename ALLOC>
402 original::chain<TYPE, ALLOC>::chainNode::chainNode(
const chainNode& other)
403 : data_(other.data_), prev(other.prev), next(other.next) {}
405 template <
typename TYPE,
typename ALLOC>
406 auto original::chain<TYPE, ALLOC>::chainNode::operator=(
const chainNode& other) -> chainNode& {
407 if (
this != &other) {
415 template <
typename TYPE,
typename ALLOC>
416 auto original::chain<TYPE, ALLOC>::chainNode::getVal() -> TYPE&
421 template <
typename TYPE,
typename ALLOC>
422 auto original::chain<TYPE, ALLOC>::chainNode::getVal() const -> const TYPE&
427 template <
typename TYPE,
typename ALLOC>
428 auto original::chain<TYPE, ALLOC>::chainNode::setVal(TYPE data) ->
void
433 template <
typename TYPE,
typename ALLOC>
434 auto original::chain<TYPE, ALLOC>::chainNode::getPPrev() const -> chainNode* {
438 template <
typename TYPE,
typename ALLOC>
439 auto original::chain<TYPE, ALLOC>::chainNode::getPNext() const -> chainNode* {
443 template <
typename TYPE,
typename ALLOC>
444 auto original::chain<TYPE, ALLOC>::chainNode::setPPrev(chainNode* new_prev) ->
void {
445 this->prev = new_prev;
448 template <
typename TYPE,
typename ALLOC>
449 auto original::chain<TYPE, ALLOC>::chainNode::setPNext(chainNode* new_next) ->
void {
450 this->next = new_next;
453 template <
typename TYPE,
typename ALLOC>
454 auto original::chain<TYPE, ALLOC>::chainNode::connect(chainNode* prev, chainNode* next) ->
void
456 if (prev !=
nullptr) prev->setPNext(next);
457 if (next !=
nullptr) next->setPPrev(prev);
460 template <
typename TYPE,
typename ALLOC>
461 auto original::chain<TYPE, ALLOC>::findNode(
integer index)
const -> chainNode* {
462 const bool reverse_visit = index <= this->size() / 2 ? 0 : 1;
468 cur = cur->getPNext();
472 for(
u_integer i = this->size() - 1; i > index; i -= 1)
474 cur = cur->getPPrev();
480 template<
typename TYPE,
typename ALLOC>
481 auto original::chain<TYPE, ALLOC>::createNode(
const TYPE &value, chainNode* prev, chainNode* next) -> chainNode* {
482 auto node = this->rebind_alloc.allocate(1);
483 this->rebind_alloc.construct(node, value, prev, next);
487 template<
typename TYPE,
typename ALLOC>
488 void original::chain<TYPE, ALLOC>::destroyNode(chainNode *node)
noexcept {
489 this->rebind_alloc.destroy(node);
490 this->rebind_alloc.deallocate(node, 1);
493 template <
typename TYPE,
typename ALLOC>
494 auto original::chain<TYPE, ALLOC>::chainInit() ->
void
496 auto pivot = this->createNode();
498 this->begin_ = pivot->getPNext();
502 template <
typename TYPE,
typename ALLOC>
503 auto original::chain<TYPE, ALLOC>::firstAdd(chainNode* node) ->
void
505 chainNode::connect(this->end_, node);
511 template <
typename TYPE,
typename ALLOC>
512 auto original::chain<TYPE, ALLOC>::lastDelete() -> chainNode*
514 auto last = this->end_;
515 this->destroyNode(last->getPPrev());
516 chainNode::connect(
nullptr, last);
521 template <
typename TYPE,
typename ALLOC>
522 auto original::chain<TYPE, ALLOC>::chainDestruction() ->
void
524 auto current = this->end_;
526 auto prev = current->getPPrev();
527 this->destroyNode(current);
532 template <
typename TYPE,
typename ALLOC>
533 original::chain<TYPE, ALLOC>::Iterator::Iterator(chainNode* ptr)
536 template <
typename TYPE,
typename ALLOC>
537 original::chain<TYPE, ALLOC>::Iterator::Iterator(
const Iterator& other)
542 template <
typename TYPE,
typename ALLOC>
544 if (
this == &other)
return *
this;
549 template <
typename TYPE,
typename ALLOC>
551 return new Iterator(*
this);
554 template <
typename TYPE,
typename ALLOC>
556 auto other_it =
dynamic_cast<const Iterator*
>(other);
557 return other_it !=
nullptr && this->
_ptr->getPNext() == other_it->_ptr;
560 template <
typename TYPE,
typename ALLOC>
562 auto other_it =
dynamic_cast<const Iterator*
>(other);
563 return other_it !=
nullptr && other_it->_ptr->getPNext() == this->
_ptr;
566 template <
typename TYPE,
typename ALLOC>
568 return "chain::Iterator";
571 template <
typename TYPE,
typename ALLOC>
577 template <
typename TYPE,
typename ALLOC>
582 template <
typename TYPE,
typename ALLOC>
585 for (
const auto& e : list) {
586 auto cur_node = this->createNode(e);
587 if (this->
size() == 0)
589 this->firstAdd(cur_node);
592 chainNode::connect(this->end_, cur_node);
593 this->end_ = cur_node;
599 template <
typename TYPE,
typename ALLOC>
603 auto cur_node = this->createNode(arr.
get(i));
604 if (this->
size() == 0)
606 this->firstAdd(cur_node);
609 chainNode::connect(this->end_, cur_node);
610 this->end_ = cur_node;
616 template <
typename TYPE,
typename ALLOC>
618 if (
this == &other)
return *
this;
619 this->chainDestruction();
620 this->size_ = other.size_;
621 if (this->
size() != 0){
622 auto other_ = other.begin_->getPPrev();
623 auto pivot = this->createNode(other_->getVal());
624 other_ = other_->getPNext();
625 chainNode::connect(pivot, this->createNode(other_->getVal()));
626 this->begin_ = pivot->getPNext();
627 auto this_ = this->begin_;
628 while (other_ != other.end_){
629 other_ = other_->getPNext();
630 chainNode::connect(this_, this->createNode(other_->getVal()));
631 this_ = this_->getPNext();
637 if constexpr (ALLOC::propagate_on_container_copy_assignment::value){
639 this->rebind_alloc = other.rebind_alloc;
644 template <
typename TYPE,
typename ALLOC>
650 template <
typename TYPE,
typename ALLOC>
656 this->chainDestruction();
657 this->begin_ = other.begin_;
658 this->end_ = other.end_;
659 this->size_ = other.size_;
660 if constexpr (ALLOC::propagate_on_container_move_assignment::value){
661 this->
allocator = std::move(other.allocator);
662 this->rebind_alloc = std::move(other.rebind_alloc);
668 template <
typename TYPE,
typename ALLOC>
671 if (
this == &other || other.empty())
return *
this;
673 this->size_ += other.size_;
674 other.destroyNode(other.begin_->getPPrev());
675 chainNode::connect(this->end_, other.begin_);
676 this->end_ = other.end_;
677 if constexpr (ALLOC::propagate_on_container_merge::value) {
685 template <
typename TYPE,
typename ALLOC>
691 template <
typename TYPE,
typename ALLOC>
697 template <
typename TYPE,
typename ALLOC>
704 return cur->getVal();
707 template <
typename TYPE,
typename ALLOC>
714 return cur->getVal();
717 template <
typename TYPE,
typename ALLOC>
727 template <
typename TYPE,
typename ALLOC>
730 for (chainNode* current = this->begin_; current !=
nullptr; current = current->getPNext()) {
731 if (current->getVal() == e) {
739 template <
typename TYPE,
typename ALLOC>
742 auto new_node = this->createNode(e);
743 if (this->
size() == 0){
744 this->firstAdd(new_node);
746 auto pivot = this->begin_->getPPrev();
747 chainNode::connect(new_node, this->begin_);
748 chainNode::connect(pivot, new_node);
749 this->begin_ = new_node;
754 template <
typename TYPE,
typename ALLOC>
760 }
else if (index == this->
size()){
766 auto new_node = this->createNode(e);
767 auto cur = this->findNode(index);
768 auto prev = cur->getPPrev();
769 chainNode::connect(prev, new_node);
770 chainNode::connect(new_node, cur);
775 template <
typename TYPE,
typename ALLOC>
778 auto new_node = this->createNode(e);
779 if (this->
size() == 0){
780 this->firstAdd(new_node);
782 chainNode::connect(this->end_, new_node);
783 this->end_ = new_node;
788 template <
typename TYPE,
typename ALLOC>
792 if (this->
size() == 0){
795 if (this->
size() == 1){
796 auto del = this->lastDelete();
798 this->destroyNode(del);
800 res = this->begin_->getVal();
801 auto new_begin = this->begin_->getPNext();
802 auto pivot = this->begin_->getPPrev();
803 this->destroyNode(this->begin_);
804 this->begin_ = new_begin;
805 chainNode::connect(pivot, this->begin_);
811 template <
typename TYPE,
typename ALLOC>
818 if (index == this->
size() - 1){
825 chainNode* cur = this->findNode(index);
827 auto prev = cur->getPPrev();
828 auto next = cur->getPNext();
829 chainNode::connect(prev, next);
830 this->destroyNode(cur);
835 template <
typename TYPE,
typename ALLOC>
839 if (this->
size() == 0){
842 if (this->
size() == 1){
843 auto del = this->lastDelete();
845 this->destroyNode(del);
847 res = this->end_->getVal();
848 auto new_end = this->end_->getPPrev();
849 this->destroyNode(this->end_);
850 this->end_ = new_end;
851 chainNode::connect(this->end_,
nullptr);
857 template <
typename TYPE,
typename ALLOC>
862 template <
typename TYPE,
typename ALLOC>
867 template <
typename TYPE,
typename ALLOC>
869 this->chainDestruction();
Provides the array class for a fixed-size container with random access.
Provides a base class for variable-size serial containers.
DERIVED< O_TYPE > rebind_alloc
Rebinds allocator to different type.
Definition allocator.h:97
Default memory allocator using allocators utilities.
Definition allocator.h:154
A fixed-size array container with random access.
Definition array.h:41
TYPE get(integer index) const override
Retrieves an element at a specified index.
Definition array.h:393
u_integer size() const override
Returns the size of the array.
Definition array.h:382
Base class for variable-size serial containers.
Definition baseList.h:43
Bidirectional iterator implementation for chain.
Definition chain.h:195
Iterator & operator=(const Iterator &other)
Assignment operator for Iterator.
Definition chain.h:543
std::string className() const override
Gets the class name of the iterator.
Definition chain.h:567
bool atNext(const iterator< TYPE > *other) const override
Checks if the iterator is at the next position relative to another iterator.
Definition chain.h:561
Iterator * clone() const override
Clones the iterator.
Definition chain.h:550
bool atPrev(const iterator< TYPE > *other) const override
Checks if the iterator is at the previous position relative to another iterator.
Definition chain.h:555
Non-cyclic doubly linked list container.
Definition chain.h:36
u_integer indexOf(const TYPE &e) const override
Finds the index of the first occurrence of the specified element.
Definition chain.h:728
TYPE popEnd() override
Pops an element from the end of the chain.
Definition chain.h:836
TYPE pop(integer index) override
Pops an element at the specified index in the chain.
Definition chain.h:812
chain(chain &&other) noexcept
Move constructs a chain with optional allocator.
Definition chain.h:645
Iterator * ends() const override
Gets an iterator to the end of the chain.
Definition chain.h:863
u_integer size() const override
Gets the size of the chain.
Definition chain.h:686
Iterator * begins() const override
Gets an iterator to the beginning of the chain.
Definition chain.h:858
chain & operator=(chain &&other) noexcept
Move assignment operator with allocator propagation.
Definition chain.h:651
TYPE popBegin() override
Pops an element from the beginning of the chain.
Definition chain.h:789
std::string className() const override
Gets the class name of the chain.
Definition chain.h:692
chain(const array< TYPE > &arr)
Constructs a chain from an array.
Definition chain.h:600
TYPE get(integer index) const override
Gets the element at the specified index.
Definition chain.h:698
~chain() override
Destructor for the chain.
Definition chain.h:868
TYPE & operator[](integer index) override
Gets a reference to the element at the specified index.
Definition chain.h:708
void push(integer index, const TYPE &e) override
Pushes an element at the specified index in the chain.
Definition chain.h:755
chain(ALLOC alloc=ALLOC{})
Constructs an empty chain with specified allocator.
Definition chain.h:572
chain(const chain &other)
Copy constructs a chain with optional allocator.
Definition chain.h:578
void pushEnd(const TYPE &e) override
Pushes an element to the end of the chain.
Definition chain.h:776
void pushBegin(const TYPE &e) override
Pushes an element to the beginning of the chain.
Definition chain.h:740
chain & operator=(const chain &other)
Copy assignment operator with allocator propagation.
Definition chain.h:617
chain(const std::initializer_list< TYPE > &list)
Constructs a chain from an initializer list.
Definition chain.h:583
void set(integer index, const TYPE &e) override
Sets the element at the specified index.
Definition chain.h:718
chain & operator+=(chain &other)
Concatenates another chain to this one.
Definition chain.h:669
ALLOC allocator
The allocator instance used for memory management.
Definition container.h:34
Abstract base class for double-direction iterators.
Definition doubleDirectionIterator.h:24
doubleDirectionIterator & operator=(const doubleDirectionIterator &other)
Copy assignment operator for doubleDirectionIterator.
Definition doubleDirectionIterator.h:77
doubleDirectionIterator(wrapper< TYPE > *ptr)
Protected constructor for doubleDirectionIterator.
Definition doubleDirectionIterator.h:67
A stream class that allows iteration, comparison, and printing.
Definition iterationStream.h:33
Base iterator interface that supports common operations for iteration.
Definition iterator.h:35
Exception for missing element requests.
Definition error.h:136
Exception for container index out-of-range errors.
Definition error.h:84
bool indexOutOfBound(integer index) const
Checks if the provided index is out of bounds.
Definition serial.h:133
integer parseNegIndex(integer index) const
Converts negative indices into valid positive indices.
Definition serial.h:140
wrapper< TYPE > * _ptr
Pointer to the current wrapper.
Definition stepIterator.h:39
Base class for linked value containers with formatted output.
Definition wrapper.h:28
Double-direction iterator base class.
Provides functionality for an iteration stream.
Main namespace for the project Original.
Definition algorithms.h:21
std::uint32_t u_integer
32-bit unsigned integer type for sizes/indexes
Definition config.h:17
std::int64_t integer
64-bit signed integer type for arithmetic operations
Definition config.h:15