29 template <
typename TYPE,
typename ALLOC = allocator<TYPE>>
31 static constexpr u_integer BLOCK_MAX_SIZE = 16;
32 static constexpr u_integer POS_INIT = (BLOCK_MAX_SIZE - 1) / 2 + 1;
54 TYPE* blockArrayInit();
61 void blocksListInit();
68 void blocksListDestroy()
noexcept;
195 mutable TYPE** data_;
421 Iterator*
ends()
const override;
503 template<
typename TYPE,
typename ALLOC>
507 template <
typename TYPE,
typename ALLOC>
510 this->map = vector({this->blockArrayInit()});
512 this->first_ = POS_INIT + 1;
513 this->last_ = POS_INIT;
514 this->first_block = this->map.
size() / 2;
515 this->last_block = this->map.size() / 2;
518 template <
typename TYPE,
typename ALLOC>
521 for (
auto* block : this->map) {
522 for (u_integer i = 0; i < BLOCK_MAX_SIZE; ++i) {
523 this->destroy(&block[i]);
525 this->deallocate(block, BLOCK_MAX_SIZE);
529 template <
typename TYPE,
typename ALLOC>
531 auto arr = this->allocate(BLOCK_MAX_SIZE);
532 for (u_integer i = 0; i < BLOCK_MAX_SIZE; i++) {
533 this->construct(&arr[i]);
538 template <
typename TYPE,
typename ALLOC>
541 return block * BLOCK_MAX_SIZE + pos;
544 template <
typename TYPE,
typename ALLOC>
547 return innerIdxToAbsIdx(this->first_block, this->first_);
550 template <
typename TYPE,
typename ALLOC>
553 return innerIdxToAbsIdx(this->last_block, this->last_);
556 template <
typename TYPE,
typename ALLOC>
559 return absIdx - this->firstAbsIdx();
562 template <
typename TYPE,
typename ALLOC>
565 return this->firstAbsIdx() + outerIdx;
568 template <
typename TYPE,
typename ALLOC>
571 return {absIdx / BLOCK_MAX_SIZE, absIdx % BLOCK_MAX_SIZE};
574 template <
typename TYPE,
typename ALLOC>
576 const integer offset) -> couple<u_integer, u_integer>
578 return absIdxToInnerIdx(
static_cast<u_integer
>(
static_cast<integer
>(innerIdxToAbsIdx(block, pos)) + offset));
581 template <
typename TYPE,
typename ALLOC>
584 return absIdxToInnerIdx(this->outerIdxToAbsIdx(outerIdx));
587 template <
typename TYPE,
typename ALLOC>
590 return this->absIdxToOuterIdx(innerIdxToAbsIdx(block, pos));
593 template <
typename TYPE,
typename ALLOC>
596 return this->map.
get(block)[pos];
599 template <
typename TYPE,
typename ALLOC>
602 this->map.
get(block)[pos] = e;
605 template <
typename TYPE,
typename ALLOC>
608 return is_first ? firstAbsIdx() < increment
609 : lastAbsIdx() + increment > innerIdxToAbsIdx(this->map.size() - 1, BLOCK_MAX_SIZE - 1);
612 template <
typename TYPE,
typename ALLOC>
614 const u_integer len,
const integer offset) ->
void
618 for (u_integer i = 0; i < len; i++)
620 auto idx = innerIdxOffset(start_block, start_pos, len - 1 - i);
621 auto idx_offset = innerIdxOffset(start_block, start_pos, len - 1 - i + offset);
622 this->setElem(idx_offset.first(), idx_offset.second(),
623 this->getElem(idx.first(), idx.second()));
627 for (u_integer i = 0; i < len; i++)
629 auto idx = innerIdxOffset(start_block, start_pos, i);
630 auto idx_offset = innerIdxOffset(start_block, start_pos, i + offset);
631 this->setElem(idx_offset.first(), idx_offset.second(),
632 this->getElem(idx.first(), idx.second()));
637 template <
typename TYPE,
typename ALLOC>
640 auto* new_block = this->blockArrayInit();
641 is_first ? this->map.pushBegin(new_block) : this->map.pushEnd(new_block);
644 template <
typename TYPE,
typename ALLOC>
647 if (this->growNeeded(increment, is_first)){
648 u_integer new_blocks_cnt = increment / BLOCK_MAX_SIZE + 1;
649 for (u_integer i = 0; i < new_blocks_cnt; ++i) {
650 this->addBlock(is_first);
653 this->first_block += new_blocks_cnt;
654 this->last_block += new_blocks_cnt;
659 template <
typename TYPE,
typename ALLOC>
661 : cur_pos(pos), cur_block(block), data_(data_ptr), container_(container) {}
663 template <
typename TYPE,
typename ALLOC>
666 auto* other_it =
dynamic_cast<const Iterator*
>(other);
667 return other_it !=
nullptr
668 && this->cur_pos == other_it->cur_pos
669 && this->cur_block == other_it->cur_block
670 && this->data_ == other_it->data_
671 && this->container_ == other_it->container_;
674 template <
typename TYPE,
typename ALLOC>
680 template <
typename TYPE,
typename ALLOC>
686 this->cur_pos =
other.cur_pos;
687 this->cur_block =
other.cur_block;
688 this->data_ =
other.data_;
689 this->container_ =
other.container_;
693 template <
typename TYPE,
typename ALLOC>
699 template <
typename TYPE,
typename ALLOC>
702 return blocksList::innerIdxToAbsIdx(this->cur_block, this->cur_pos) < this->container_->lastAbsIdx();
705 template <
typename TYPE,
typename ALLOC>
708 return blocksList::innerIdxToAbsIdx(this->cur_block, this->cur_pos) > this->container_->firstAbsIdx();
711 template <
typename TYPE,
typename ALLOC>
717 template <
typename TYPE,
typename ALLOC>
723 template <
typename TYPE,
typename ALLOC>
726 auto new_idx = innerIdxOffset(this->cur_block, this->cur_pos,
steps);
727 this->cur_block =
new_idx.first();
728 this->cur_pos =
new_idx.second();
731 template <
typename TYPE,
typename ALLOC>
734 auto new_idx = innerIdxOffset(this->cur_block, this->cur_pos, -
steps);
735 this->cur_block =
new_idx.first();
736 this->cur_pos =
new_idx.second();
739 template <
typename TYPE,
typename ALLOC>
744 return this > &
other ?
745 (std::numeric_limits<integer>::max)() :
746 (std::numeric_limits<integer>::min)();
747 if (this->container_ !=
other_it->container_)
748 return this->container_ >
other_it->container_ ?
749 (std::numeric_limits<integer>::max)() :
750 (std::numeric_limits<integer>::min)();
752 return static_cast<integer>(innerIdxToAbsIdx(this->cur_block, this->cur_pos)) -
756 template <
typename TYPE,
typename ALLOC>
760 auto*
it = this->clone();
765 template <
typename TYPE,
typename ALLOC>
769 auto*
it = this->clone();
774 template <
typename TYPE,
typename ALLOC>
778 return this->data_[this->cur_block][this->cur_pos];
781 template <
typename TYPE,
typename ALLOC>
785 return this->data_[this->cur_block][this->cur_pos];
788 template <
typename TYPE,
typename ALLOC>
792 this->data_[this->cur_block][this->cur_pos] = data;
795 template <
typename TYPE,
typename ALLOC>
798 return this->container_->innerIdxToOuterIdx(this->cur_block, this->cur_pos) >= 0 &&
799 this->container_->innerIdxToOuterIdx(this->cur_block, this->cur_pos) < this->container_->size();
802 template <
typename TYPE,
typename ALLOC>
811 template <
typename TYPE,
typename ALLOC>
820 template <
typename TYPE,
typename ALLOC>
822 return "blocksList::Iterator";
825 template <
typename TYPE,
typename ALLOC>
829 this->blocksListInit();
832 template <
typename TYPE,
typename ALLOC>
834 this->adjust(
lst.size(),
false);
835 for (
const auto&
e :
lst) {
836 auto new_idx = innerIdxOffset(this->last_block, this->last_, 1);
837 this->last_block =
new_idx.first();
838 this->last_ =
new_idx.second();
839 this->setElem(this->last_block, this->last_,
e);
844 template <
typename TYPE,
typename ALLOC>
846 this->adjust(
arr.size(),
false);
847 for (
const auto&
e :
arr) {
848 auto new_idx = innerIdxOffset(this->last_block, this->last_, 1);
849 this->last_block =
new_idx.first();
850 this->last_ =
new_idx.second();
851 this->setElem(this->last_block, this->last_,
e);
856 template <
typename TYPE,
typename ALLOC>
861 template <
typename TYPE,
typename ALLOC>
863 if (
this == &
other)
return *
this;
865 this->blocksListDestroy();
869 auto*
block = this->blockArrayInit();
876 this->first_ =
other.first_;
877 this->last_ =
other.last_;
878 this->size_ =
other.size_;
879 this->first_block =
other.first_block;
880 this->last_block =
other.last_block;
881 if constexpr (ALLOC::propagate_on_container_copy_assignment::value){
887 template <
typename TYPE,
typename ALLOC>
890 this->operator=(std::move(
other));
893 template <
typename TYPE,
typename ALLOC>
899 this->blocksListDestroy();
902 this->first_ =
other.first_;
903 this->last_ =
other.last_;
904 this->first_block =
other.first_block;
905 this->last_block =
other.last_block;
906 this->size_ =
other.size_;
907 if constexpr (ALLOC::propagate_on_container_move_assignment::value){
910 other.blocksListInit();
914 template <
typename TYPE,
typename ALLOC>
926 if constexpr (ALLOC::propagate_on_container_swap::value) {
931 template <
typename TYPE,
typename ALLOC>
933 if (this->indexOutOfBound(this->parseNegIndex(index)))
throw outOfBoundError();
934 index = this->parseNegIndex(index);
935 auto inner_idx = this->outerIdxToInnerIdx(index);
939 template <
typename TYPE,
typename ALLOC>
945 template <
typename TYPE,
typename ALLOC>
947 return new Iterator(this->first_, this->first_block, &this->
map.data(),
this);
950 template <
typename TYPE,
typename ALLOC>
952 return new Iterator(this->last_, this->last_block, &this->
map.data(),
this);
955 template <
typename TYPE,
typename ALLOC>
957 if (this->indexOutOfBound(this->parseNegIndex(index)))
throw outOfBoundError();
958 index = this->parseNegIndex(index);
959 auto inner_idx = this->outerIdxToInnerIdx(index);
963 template <
typename TYPE,
typename ALLOC>
966 index = this->parseNegIndex(index);
967 auto inner_idx = this->outerIdxToInnerIdx(index);
971 template <
typename TYPE,
typename ALLOC>
974 if (
auto idx = this->outerIdxToInnerIdx(
i);
975 this->getElem(
idx.first(),
idx.second()) ==
e)
981 template <
typename TYPE,
typename ALLOC>
984 if (this->parseNegIndex(index) == this->size())
987 }
else if (this->parseNegIndex(index) == 0)
991 if (this->indexOutOfBound(index))
994 index = this->parseNegIndex(index);
995 const bool is_first = index <= (this->size() - 1) / 2;
998 this->moveElements(this->first_block, this->first_, index + 1, -1);
999 auto new_idx = innerIdxOffset(this->first_block, this->first_, -1);
1000 this->first_block =
new_idx.first();
1001 this->first_ =
new_idx.second();
1003 auto idx = outerIdxToInnerIdx(index);
1004 this->moveElements(
idx.first(),
idx.second(),
this->size() - index, 1);
1005 auto new_idx = innerIdxOffset(this->last_block, this->last_, 1);
1006 this->last_block =
new_idx.first();
1007 this->last_ =
new_idx.second();
1010 auto idx = outerIdxToInnerIdx(index);
1011 this->setElem(
idx.first(),
idx.second(),
e);
1015 template <
typename TYPE,
typename ALLOC>
1018 if (this->parseNegIndex(index) == 0)
1019 return this->popBegin();
1020 if (this->parseNegIndex(index) == this->size() - 1)
1021 return this->popEnd();
1022 if (this->indexOutOfBound(index))
1025 index = this->parseNegIndex(index);
1026 auto idx = outerIdxToInnerIdx(index);
1028 if (index <= (this->size() - 1) / 2){
1029 moveElements(this->first_block, this->first_, index, 1);
1030 auto new_idx = innerIdxOffset(this->first_block, this->first_, 1);
1031 this->first_block =
new_idx.first();
1032 this->first_ =
new_idx.second();
1036 auto new_idx = innerIdxOffset(this->last_block, this->last_, -1);
1037 this->last_block =
new_idx.first();
1038 this->last_ =
new_idx.second();
1044 template <
typename TYPE,
typename ALLOC>
1047 this->adjust(1,
true);
1048 auto new_idx = innerIdxOffset(this->first_block, this->first_, -1);
1049 this->first_block =
new_idx.first();
1050 this->first_ =
new_idx.second();
1051 this->setElem(this->first_block, this->first_,
e);
1055 template <
typename TYPE,
typename ALLOC>
1060 TYPE res = this->getElem(this->first_block, this->first_);
1061 auto new_idx = innerIdxOffset(this->first_block, this->first_, 1);
1062 this->first_block =
new_idx.first();
1063 this->first_ =
new_idx.second();
1068 template <
typename TYPE,
typename ALLOC>
1071 this->adjust(1,
false);
1072 auto new_idx = innerIdxOffset(this->last_block, this->last_, 1);
1073 this->last_block =
new_idx.first();
1074 this->last_ =
new_idx.second();
1075 this->setElem(this->last_block, this->last_,
e);
1079 template <
typename TYPE,
typename ALLOC>
1084 TYPE res = this->getElem(this->last_block, this->last_);
1085 auto new_idx = innerIdxOffset(this->last_block, this->last_, -1);
1086 this->last_block =
new_idx.first();
1087 this->last_ =
new_idx.second();
1092 template <
typename TYPE,
typename ALLOC>
1094 return "blocksList";
1097 template <
typename TYPE,
typename ALLOC>
1099 this->blocksListDestroy();
1102 template <
typename TYPE,
typename ALLOC>
Provides a base class for variable-size serial containers.
Default memory allocator using allocators utilities.
Definition allocator.h:153
void swap(autoPtr &other) noexcept
Swaps the reference counters between two autoPtr instances.
Definition autoPtr.h:703
A base class for basic iterators.
Definition iterator.h:296
Base class for variable-size serial containers.
Definition baseList.h:43
Iterator for blocksList, supports forward and backward iteration.
Definition blocksList.h:192
Iterator * getNext() const override
Gets the next iterator.
Definition blocksList.h:766
Iterator * clone() const override
Clones the iterator.
Definition blocksList.h:694
void operator-=(integer steps) const override
Moves the iterator backward by the specified number of steps.
Definition blocksList.h:732
Iterator & operator=(const Iterator &other)
Assignment operator for the Iterator.
Definition blocksList.h:681
void prev() const override
Moves the iterator to the previous element.
Definition blocksList.h:718
bool hasNext() const override
Checks if there is a next element.
Definition blocksList.h:700
Iterator * getPrev() const override
Gets the previous iterator.
Definition blocksList.h:757
void next() const override
Moves the iterator to the next element.
Definition blocksList.h:712
bool hasPrev() const override
Checks if there is a previous element.
Definition blocksList.h:706
void operator+=(integer steps) const override
Advances the iterator by the specified number of steps.
Definition blocksList.h:724
void set(const TYPE &data) override
Sets the value of the element pointed to by the iterator.
Definition blocksList.h:789
TYPE & get() override
Gets the element pointed to by the iterator.
Definition blocksList.h:775
bool isValid() const override
Checks if the iterator is valid.
Definition blocksList.h:796
bool atPrev(const iterator< TYPE > *other) const override
Checks if the iterator is at the previous element relative to another iterator.
Definition blocksList.h:803
bool atNext(const iterator< TYPE > *other) const override
Checks if the iterator is at the next element relative to another iterator.
Definition blocksList.h:812
std::string className() const override
Gets the class name of the iterator.
Definition blocksList.h:821
A block-based list implementation.
Definition blocksList.h:30
std::string className() const override
Gets the class name of the blocksList.
Definition blocksList.h:1093
u_integer indexOf(const TYPE &e) const override
Finds the index of the first occurrence of the specified element.
Definition blocksList.h:972
void pushEnd(const TYPE &e) override
Pushes an element to the end of the blocksList.
Definition blocksList.h:1069
TYPE get(integer index) const override
Gets the element at the specified index.
Definition blocksList.h:932
blocksList(blocksList &&other) noexcept
Move constructor.
Definition blocksList.h:888
void pushBegin(const TYPE &e) override
Pushes an element to the beginning of the blocksList.
Definition blocksList.h:1045
void swap(blocksList &other) noexcept
Swaps the contents of this blocksList with another.
Definition blocksList.h:915
TYPE popEnd() override
Pops the element from the end of the blocksList.
Definition blocksList.h:1080
blocksList(ALLOC alloc=ALLOC{})
Constructs an empty blocksList.
Definition blocksList.h:826
u_integer size() const override
Gets the size of the blocksList.
Definition blocksList.h:940
Iterator * begins() const override
Gets an iterator to the beginning of the blocksList.
Definition blocksList.h:946
void set(integer index, const TYPE &e) override
Sets the element at the specified index.
Definition blocksList.h:964
blocksList(const array< TYPE > &arr)
Constructs a blocksList from an array.
Definition blocksList.h:845
TYPE popBegin() override
Pops the element from the beginning of the blocksList.
Definition blocksList.h:1056
void push(integer index, const TYPE &e) override
Pushes an element to the specified index in the blocksList.
Definition blocksList.h:982
blocksList & operator=(blocksList &&other) noexcept
Move assignment operator.
Definition blocksList.h:894
blocksList(const std::initializer_list< TYPE > &lst)
Constructs a blocksList from an initializer list.
Definition blocksList.h:833
TYPE pop(integer index) override
Pops the element at the specified index in the blocksList.
Definition blocksList.h:1016
blocksList(const blocksList &other)
Copy constructor.
Definition blocksList.h:857
Iterator * ends() const override
Gets an iterator to the end of the blocksList.
Definition blocksList.h:951
blocksList & operator=(const blocksList &other)
Copy assignment operator.
Definition blocksList.h:862
~blocksList() override
Destructor for the blocksList.
Definition blocksList.h:1098
TYPE & operator[](integer index) override
Gets a reference to the element at the specified index.
Definition blocksList.h:956
Abstract base class for containers.
Definition container.h:26
A stream class that allows iteration, comparison, hashing and printing.
Definition iterationStream.h:60
friend iterator< T > * operator-(const iterator< T > &it, integer steps)
Subtracts a number of steps from the iterator's current position and returns a new iterator.
Abstract base class for key-value mapping containers.
Definition map.h:49
Exception for missing element requests.
Definition error.h:298
Exception for container index out-of-range errors.
Definition error.h:192
Unique ownership smart pointer with move semantics.
Definition ownerPtr.h:37
Abstract base class for unique element containers.
Definition set.h:44
Generic pair container implementation.
Main namespace for the project Original.
Definition algorithms.h:21
auto operator-(const iterator< T > &it, integer steps) -> iterator< T > *
Subtracts a number of steps from the iterator's current position and returns a new iterator.
Standard namespace extensions for original::alternative.
Definition allocator.h:351
void swap(original::objPoolAllocator< TYPE > &lhs, original::objPoolAllocator< TYPE > &rhs) noexcept
Specialization of std::swap for objPoolAllocator.
Definition allocator.h:635
Dynamic array container with automatic resizing.