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 = 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();
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>
399 : data_(data), prev(prev), next(next) {}
401 template <
typename TYPE,
typename ALLOC>
403 : data_(other.data_), prev(other.prev), next(other.next) {}
405 template <
typename TYPE,
typename ALLOC>
407 if (
this != &other) {
415 template <
typename TYPE,
typename ALLOC>
421 template <
typename TYPE,
typename ALLOC>
427 template <
typename TYPE,
typename ALLOC>
433 template <
typename TYPE,
typename ALLOC>
438 template <
typename TYPE,
typename ALLOC>
443 template <
typename TYPE,
typename ALLOC>
445 this->prev = new_prev;
448 template <
typename TYPE,
typename ALLOC>
450 this->next = new_next;
453 template <
typename TYPE,
typename ALLOC>
456 if (prev !=
nullptr) prev->setPNext(next);
457 if (next !=
nullptr) next->setPPrev(prev);
460 template <
typename TYPE,
typename ALLOC>
462 const bool reverse_visit = index <= this->size() / 2 ? 0 : 1;
466 for(u_integer i = 0; i < index; i++)
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>
482 auto node = this->rebind_alloc.
allocate(1);
483 this->rebind_alloc.construct(node, value, prev, next);
487 template<
typename TYPE,
typename ALLOC>
489 this->rebind_alloc.
destroy(node);
490 this->rebind_alloc.deallocate(node, 1);
493 template <
typename TYPE,
typename ALLOC>
496 auto pivot = this->createNode();
498 this->begin_ = pivot->getPNext();
502 template <
typename TYPE,
typename ALLOC>
505 chainNode::connect(this->end_, node);
511 template <
typename TYPE,
typename ALLOC>
514 auto last = this->end_;
515 this->destroyNode(last->getPPrev());
516 chainNode::connect(
nullptr, last);
521 template <
typename TYPE,
typename ALLOC>
524 auto current = this->end_;
526 auto prev = current->getPPrev();
527 this->destroyNode(current);
532 template <
typename TYPE,
typename ALLOC>
534 : doubleDirectionIterator<TYPE>::doubleDirectionIterator(ptr) {}
536 template <
typename TYPE,
typename ALLOC>
542 template <
typename TYPE,
typename ALLOC>
544 if (
this == &other)
return *
this;
549 template <
typename TYPE,
typename ALLOC>
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->chainDestroy();
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>
647 this->operator=(std::move(other));
650 template <
typename TYPE,
typename ALLOC>
656 this->chainDestroy();
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>
700 if (this->indexOutOfBound(index)){
704 chainNode* cur = this->findNode(this->parseNegIndex(index));
705 return cur->getVal();
708 template <
typename TYPE,
typename ALLOC>
711 if (this->indexOutOfBound(index)){
715 chainNode* cur = this->findNode(this->parseNegIndex(index));
716 return cur->getVal();
719 template <
typename TYPE,
typename ALLOC>
722 if (this->indexOutOfBound(index)){
726 auto cur = this->findNode(this->parseNegIndex(index));
730 template <
typename TYPE,
typename ALLOC>
733 for (chainNode* current = this->begin_; current !=
nullptr; current = current->getPNext()) {
734 if (current->getVal() == e) {
742 template <
typename TYPE,
typename ALLOC>
745 auto new_node = this->createNode(e);
746 if (this->size() == 0){
747 this->firstAdd(new_node);
749 auto pivot = this->begin_->getPPrev();
750 chainNode::connect(new_node, this->begin_);
751 chainNode::connect(pivot, new_node);
752 this->begin_ = new_node;
757 template <
typename TYPE,
typename ALLOC>
760 index = this->parseNegIndex(index);
763 }
else if (index == this->size()){
766 if (this->indexOutOfBound(index)){
770 auto new_node = this->createNode(e);
771 auto cur = this->findNode(index);
772 auto prev = cur->getPPrev();
773 chainNode::connect(prev, new_node);
774 chainNode::connect(new_node, cur);
779 template <
typename TYPE,
typename ALLOC>
782 auto new_node = this->createNode(e);
783 if (this->size() == 0){
784 this->firstAdd(new_node);
786 chainNode::connect(this->end_, new_node);
787 this->end_ = new_node;
792 template <
typename TYPE,
typename ALLOC>
796 if (this->size() == 0){
797 throw noElementError(
"chain::popBegin: Cannot pop from empty chain");
799 if (this->size() == 1){
800 auto del = this->lastDelete();
802 this->destroyNode(del);
804 res = this->begin_->getVal();
805 auto new_begin = this->begin_->getPNext();
806 auto pivot = this->begin_->getPPrev();
807 this->destroyNode(this->begin_);
808 this->begin_ = new_begin;
809 chainNode::connect(pivot, this->begin_);
815 template <
typename TYPE,
typename ALLOC>
818 index = this->parseNegIndex(index);
820 return this->popBegin();
822 if (index == this->size() - 1){
823 return this->popEnd();
825 if (this->indexOutOfBound(index)){
830 chainNode* cur = this->findNode(index);
832 auto prev = cur->getPPrev();
833 auto next = cur->getPNext();
834 chainNode::connect(prev, next);
835 this->destroyNode(cur);
840 template <
typename TYPE,
typename ALLOC>
844 if (this->size() == 0){
845 throw noElementError(
"chain::popEnd: Cannot pop from empty chain");
847 if (this->size() == 1){
848 auto del = this->lastDelete();
850 this->destroyNode(del);
852 res = this->end_->getVal();
853 auto new_end = this->end_->getPPrev();
854 this->destroyNode(this->end_);
855 this->end_ = new_end;
856 chainNode::connect(this->end_,
nullptr);
862 template <
typename TYPE,
typename ALLOC>
867 template <
typename TYPE,
typename ALLOC>
872 template <
typename TYPE,
typename ALLOC>
874 this->chainDestroy();
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:446
u_integer size() const override
Returns the size of the array.
Definition array.h:435
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:731
TYPE popEnd() override
Pops an element from the end of the chain.
Definition chain.h:841
TYPE pop(integer index) override
Pops an element at the specified index in the chain.
Definition chain.h:816
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:868
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:863
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:793
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:873
TYPE & operator[](integer index) override
Gets a reference to the element at the specified index.
Definition chain.h:709
void push(integer index, const TYPE &e) override
Pushes an element at the specified index in the chain.
Definition chain.h:758
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:780
void pushBegin(const TYPE &e) override
Pushes an element to the beginning of the chain.
Definition chain.h:743
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:720
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:32
TYPE * allocate(u_integer size)
Allocates raw memory for elements.
Definition container.h:131
void destroy(O_TYPE *o_ptr)
Destroys an element.
Definition container.h:148
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
A stream class that allows iteration, comparison, and printing.
Definition iterationStream.h:32
Base iterator interface that supports common operations for iteration.
Definition iterator.h:37
Exception for missing element requests.
Definition error.h:213
Exception for container index out-of-range errors.
Definition error.h:129
static std::string formatString(const TYPE &t)
Universal value-to-string conversion.
Definition printable.h:263
wrapper< TYPE > * _ptr
Pointer to the current wrapper.
Definition stepIterator.h:40
Base class for linked value containers with formatted output.
Definition wrapper.h:28
Double-direction iterator base class.
std::uint32_t u_integer
32-bit unsigned integer type for sizes and indexes
Definition config.h:263
std::int64_t integer
64-bit signed integer type for arithmetic operations
Definition config.h:254
Provides functionality for an iteration stream.
Main namespace for the project Original.
Definition algorithms.h:21