ORIGINAL
Loading...
Searching...
No Matches
vector.h
Go to the documentation of this file.
1#ifndef VECTOR_H
2#define VECTOR_H
3
11#include "baseList.h"
12#include "iterationStream.h"
13#include "array.h"
14
15namespace original {
16
42 template <typename TYPE, typename ALLOC = allocator<TYPE>>
43 class vector final : public baseList<TYPE, ALLOC>, public iterationStream<TYPE, vector<TYPE, ALLOC>> {
44 u_integer size_;
45 static constexpr u_integer INNER_SIZE_INIT = 16;
46 u_integer max_size;
47 u_integer inner_begin;
48 TYPE* body;
49
50 // ==================== Private Methods ====================
51
55 void vectorInit();
56
78 void vectorArrayDestroy() noexcept;
79
88 TYPE* vectorArrayInit(u_integer size);
89
95 TYPE getElem(integer pos) const;
96
102 void setElem(integer pos, const TYPE &e);
103
110 static void setBufElem(TYPE* buf, integer pos, const TYPE& e);
111
120 static void moveElements(TYPE* old_body, u_integer inner_idx,
122
128 [[nodiscard]] u_integer toInnerIdx(integer index) const;
129
135 [[nodiscard]] bool outOfMaxSize(u_integer increment) const;
136
146 void grow(u_integer new_size);
147
152 void adjust(u_integer increment);
153
173 explicit vector(u_integer size, ALLOC alloc = ALLOC{});
174
175 public:
176
177 // ==================== Iterator Class ====================
178
188 class Iterator final : public randomAccessIterator<TYPE, ALLOC> {
195 explicit Iterator(TYPE* ptr, const vector* container, integer pos);
196
197 public:
198 friend vector;
199
204 Iterator(const Iterator& other);
205
211 Iterator& operator=(const Iterator& other);
212
217 Iterator* clone() const override;
218
224 bool atPrev(const iterator<TYPE> *other) const override;
225
231 bool atNext(const iterator<TYPE> *other) const override;
232
237 [[nodiscard]] std::string className() const override;
238 };
239
240 // ==================== Constructors and Destructor ====================
241
248 explicit vector(ALLOC alloc = ALLOC{});
249
264 template<typename... ARGS>
266
272
277 vector(const std::initializer_list<TYPE>& list);
278
283 explicit vector(const array<TYPE>& arr);
284
291
296 vector(vector&& other) noexcept;
297
304
308 ~vector() override;
309
310 void swap(vector& other) noexcept;
311
312 // ==================== Capacity Methods ====================
313
318 [[nodiscard]] u_integer size() const override;
319
325
326 // ==================== Element Access ====================
327
333
340
347
348 // const version
350
357
358 // ==================== Search Operations ====================
359
366
367 // ==================== Insertion Operations ====================
368
374
381
387
388 // ==================== Removal Operations ====================
389
395
402
408
409 // ==================== Iterator Methods ====================
410
415 Iterator* begins() const override;
416
421 Iterator* ends() const override;
422
423 // ==================== Utility Methods ====================
424
430
432 friend vector<T> makeVector(u_integer size, ARGS&&... args);
433 };
434
435 // ==================== Factory Function ====================
436
457 vector<T> makeVector(u_integer size, ARGS&&... args);
458}
459
461 template<typename TYPE, typename ALLOC>
463}
464
465 template <typename TYPE, typename ALLOC>
467 {
468 this->size_ = 0;
469 this->max_size = INNER_SIZE_INIT;
470 this->inner_begin = (INNER_SIZE_INIT - 1)/2;
471 this->body = vector::vectorArrayInit(INNER_SIZE_INIT);
472 }
473
474 template <typename TYPE, typename ALLOC>
476 {
477 if (this->body) {
478 for (u_integer i = 0; i < this->max_size; ++i) {
479 this->destroy(&this->body[i]);
480 }
481 this->deallocate(this->body, this->max_size);
482 this->body = nullptr;
483 }
484 }
485
486 template <typename TYPE, typename ALLOC>
488 auto arr = this->allocate(size);
489 for (u_integer i = 0; i < size; i++) {
490 this->construct(&arr[i]);
491 }
492 return arr;
493 }
494
495 template <typename TYPE, typename ALLOC>
497 {
498 if constexpr (std::is_copy_constructible_v<TYPE>) {
499 return this->body[pos];
500 } else if constexpr (std::is_move_constructible_v<TYPE>) {
501 return std::move(this->body[pos]);
502 } else {
503 staticError<unSupportedMethodError, !std::is_copy_constructible_v<TYPE> && !std::is_move_constructible_v<TYPE>>::asserts();
504 return TYPE{};
505 }
506 }
507
508 template <typename TYPE, typename ALLOC>
509 void original::vector<TYPE, ALLOC>::setElem(const integer pos, const TYPE& e)
510 {
511 setBufElem(this->body, pos, e);
512 }
513
514 template <typename TYPE, typename ALLOC>
515 void original::vector<TYPE, ALLOC>::setBufElem(TYPE* buf, integer pos, const TYPE& e)
516 {
517 if constexpr (std::is_copy_assignable_v<TYPE>) {
518 buf[pos] = e;
519 } else if constexpr (std::is_move_assignable_v<TYPE>) {
520 buf[pos] = std::move(const_cast<TYPE&>(e));
521 } else {
522 staticError<unSupportedMethodError, !std::is_copy_constructible_v<TYPE> && !std::is_move_constructible_v<TYPE>>::asserts();
523 }
524 }
525
526 template <typename TYPE, typename ALLOC>
527 auto original::vector<TYPE, ALLOC>::moveElements(TYPE* old_body, const u_integer inner_idx,
528 const u_integer len, TYPE* new_body, const integer offset) -> void{
529 if (offset > 0)
530 {
531 for (u_integer i = 0; i < len; i += 1)
532 {
533 setBufElem(new_body, inner_idx + offset + len - 1 - i, old_body[inner_idx + len - 1 - i]);
534 }
535 }else
536 {
537 for (u_integer i = 0; i < len; i += 1)
538 {
539 setBufElem(new_body, inner_idx + offset + i, old_body[inner_idx + i]);
540 }
541 }
542 }
543
544 template <typename TYPE, typename ALLOC>
546 {
547 return this->inner_begin + index;
548 }
549
550 template <typename TYPE, typename ALLOC>
551 auto original::vector<TYPE, ALLOC>::outOfMaxSize(u_integer increment) const -> bool
552 {
553 return this->inner_begin + this->size() + increment > this->max_size - 1 || static_cast<integer>(this->inner_begin) - static_cast<integer>(increment) < 0;
554 }
555
556 template <typename TYPE, typename ALLOC>
557 auto original::vector<TYPE, ALLOC>::grow(const u_integer new_size) -> void
558 {
559 TYPE* new_body = vector::vectorArrayInit(new_size);
560 u_integer new_begin = (new_size - 1) / 4;
561 const integer offset = static_cast<integer>(new_begin) - static_cast<integer>(this->inner_begin);
562 vector::moveElements(this->body, this->inner_begin,
563 this->size(), new_body, offset);
564 this->vectorArrayDestroy();
565 this->body = new_body;
566 this->max_size = new_size;
567 this->inner_begin = new_begin;
568 }
569
570 template <typename TYPE, typename ALLOC>
571 auto original::vector<TYPE, ALLOC>::adjust(u_integer increment) -> void {
572 if (!this->outOfMaxSize(increment)) {
573 return;
574 }
575 u_integer new_begin = (this->max_size - this->size() - increment) / 2;
576 if (this->max_size >= this->size_ + increment && new_begin > 0) {
577 const integer offset = static_cast<integer>(new_begin) - static_cast<integer>(this->inner_begin);
578 vector::moveElements(this->body, this->inner_begin, this->size(),
579 this->body, offset);
580 this->inner_begin = new_begin;
581 } else {
582 const u_integer new_max_size = (this->size() + increment) * 2;
583 this->grow(new_max_size);
584 }
585 }
586
587 template <typename TYPE, typename ALLOC>
588 original::vector<TYPE, ALLOC>::Iterator::Iterator(TYPE* ptr, const vector* container, integer pos)
589 : randomAccessIterator<TYPE, ALLOC>(ptr, container, pos) {}
590
591 template <typename TYPE, typename ALLOC>
597
598 template <typename TYPE, typename ALLOC>
600 {
601 if (this == &other) {
602 return *this;
603 }
605 return *this;
606 }
607
608 template <typename TYPE, typename ALLOC>
612
613 template <typename TYPE, typename ALLOC>
615 auto other_it = dynamic_cast<const Iterator*>(other);
616 return this->_ptr + 1 == other_it->_ptr;
617 }
618
619 template <typename TYPE, typename ALLOC>
621 auto other_it = dynamic_cast<const Iterator*>(other);
622 return other_it->_ptr + 1 == this->_ptr;
623 }
624
625 template <typename TYPE, typename ALLOC>
627 return "vector::Iterator";
628 }
629
630 template <typename TYPE, typename ALLOC>
632 : baseList<TYPE, ALLOC>(std::move(alloc)), size_(), max_size(), inner_begin()
633 {
634 this->vectorInit();
635 }
636
637template<typename TYPE, typename ALLOC>
638template<typename... ARGS>
640 : vector(size, std::move(alloc)) {
641 this->body = this->allocate(this->max_size);
642 for (u_integer i = 0; i < this->size_; ++i) {
643 this->construct(&this->body[this->toInnerIdx(i)], std::forward<ARGS>(args)...);
644 }
645}
646
647template<typename TYPE, typename ALLOC>
649 : baseList<TYPE, ALLOC>(std::move(alloc)), size_(size),
650 max_size(size * 4 / 3), inner_begin(size / 3 >= 1 ? size / 3 - 1 : 0), body(nullptr) {
651}
652
653 template <typename TYPE, typename ALLOC>
657
658 template <typename TYPE, typename ALLOC>
659 original::vector<TYPE, ALLOC>::vector(const std::initializer_list<TYPE>& list) : vector()
660 {
661 this->adjust(list.size());
662 for (const TYPE& e: list)
663 {
664 this->setElem(this->inner_begin + this->size(), e);
665 this->size_ += 1;
666 }
667 }
668
669 template <typename TYPE, typename ALLOC>
671 {
672 if (this == &other)
673 return *this;
674
675 this->vectorArrayDestroy();
676
677 this->max_size = other.max_size;
678 this->inner_begin = other.inner_begin;
679 this->size_ = other.size_;
680 this->body = vector::vectorArrayInit(this->max_size);
681 for (u_integer i = 0; i < this->size(); ++i) {
682 const TYPE& data = other.body[this->toInnerIdx(i)];
683 this->setElem(this->toInnerIdx(i), data);
684 }
685 if constexpr (ALLOC::propagate_on_container_copy_assignment::value){
686 this->allocator = other.allocator;
687 }
688 return *this;
689 }
690
691 template <typename TYPE, typename ALLOC>
693 {
694 this->operator=(std::move(other));
695 }
696
697 template <typename TYPE, typename ALLOC>
699 {
700 if (this == &other)
701 return *this;
702
703 this->vectorArrayDestroy();
704 this->body = other.body;
705 other.body = nullptr;
706 this->max_size = other.max_size;
707 this->inner_begin = other.inner_begin;
708 this->size_ = other.size_;
709 if constexpr (ALLOC::propagate_on_container_move_assignment::value){
710 this->allocator = std::move(other.allocator);
711 }
712 other.vectorInit();
713 return *this;
714 }
715
716 template <typename TYPE, typename ALLOC>
718 {
719 this->adjust(arr.size());
720 for (u_integer i = 0; i < arr.size(); i += 1)
721 {
722 this->setElem(this->toInnerIdx(i), arr.get(i));
723 this->size_ += 1;
724 }
725 }
726
727 template <typename TYPE, typename ALLOC>
729 {
730 return this->size_;
731 }
732
733 template <typename TYPE, typename ALLOC>
738
739 template <typename TYPE, typename ALLOC>
741 return this->body[this->toInnerIdx(0)];
742 }
743
744 template <typename TYPE, typename ALLOC>
746 {
747 if (this->indexOutOfBound(index))
748 {
749 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
750 " out of bound max index " + std::to_string(this->size() - 1) + ".");
751 }
752 index = this->toInnerIdx(this->parseNegIndex(index));
753 return this->getElem(index);
754 }
755
756 template <typename TYPE, typename ALLOC>
758 {
759 if (this->indexOutOfBound(index))
760 {
761 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
762 " out of bound max index " + std::to_string(this->size() - 1) + ".");
763 }
764 index = this->toInnerIdx(this->parseNegIndex(index));
765 return this->body[index];
766 }
767
768 template <typename TYPE, typename ALLOC>
770 {
771 if (this->indexOutOfBound(index))
772 {
773 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
774 " out of bound max index " + std::to_string(this->size() - 1) + ".");
775 }
776 index = this->toInnerIdx(this->parseNegIndex(index));
777 this->setElem(index, e);
778 }
779
780 template <typename TYPE, typename ALLOC>
782 {
783 if constexpr (Comparable<TYPE>) {
784 for (u_integer i = 0; i < this->size(); i += 1)
785 {
786 if (this->get(i) == e)
787 {
788 return i;
789 }
790 }
791 return this->size();
792 } else {
793 throw unSupportedMethodError("Comparison unsupported type");
794 }
795 }
796
797 template <typename TYPE, typename ALLOC>
799 {
800 this->adjust(1);
801 this->inner_begin -= 1;
802 this->setElem(this->toInnerIdx(0), e);
803 this->size_ += 1;
804 }
805
806 template <typename TYPE, typename ALLOC>
808 {
809 if (this->parseNegIndex(index) == this->size())
810 {
811 this->pushEnd(e);
812 }else if (this->parseNegIndex(index) == 0)
813 {
814 this->pushBegin(e);
815 }else
816 {
817 if (this->indexOutOfBound(index))
818 {
819 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
820 " out of bound max index " + std::to_string(this->size() - 1) + ".");
821 }
822 this->adjust(1);
823 index = this->toInnerIdx(this->parseNegIndex(index));
824 u_integer rel_idx = index - this->inner_begin;
825 if (index - this->inner_begin <= (this->size() - 1) / 2)
826 {
827 vector::moveElements(this->body, this->inner_begin,
828 rel_idx + 1, this->body, -1);
829 this->inner_begin -= 1;
830 }else
831 {
832 vector::moveElements(this->body, index,
833 this->size() - rel_idx, this->body, 1);
834 }
835 this->setElem(this->toInnerIdx(rel_idx), e);
836 this->size_ += 1;
837 }
838 }
839
840 template <typename TYPE, typename ALLOC>
842 {
843 this->adjust(1);
844 this->setElem(this->toInnerIdx(this->size()), e);
845 this->size_ += 1;
846 }
847
848 template <typename TYPE, typename ALLOC>
850 {
851 if (this->size() == 0){
852 throw noElementError();
853 }
854 TYPE res = this->get(0);
855 this->inner_begin += 1;
856 this->size_ -= 1;
857 return res;
858 }
859
860 template <typename TYPE, typename ALLOC>
862 {
863 if (this->parseNegIndex(index) == 0)
864 {
865 return this->popBegin();
866 }
867 if (this->parseNegIndex(index) == this->size() - 1)
868 {
869 return this->popEnd();
870 }
871 if (this->indexOutOfBound(index)){
872 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
873 " out of bound max index " + std::to_string(this->size() - 1) + ".");
874 }
875 TYPE res = this->get(index);
876 index = this->toInnerIdx(this->parseNegIndex(index));
877 u_integer rel_idx = index - this->inner_begin;
878 if (index - this->inner_begin <= (this->size() - 1) / 2)
879 {
880 vector::moveElements(this->body, this->inner_begin,
881 rel_idx, this->body, 1);
882 this->inner_begin += 1;
883 }else
884 {
885 vector::moveElements(this->body, index + 1,
886 this->size() - 1 - rel_idx, this->body, -1);
887 }
888 this->size_ -= 1;
889 return res;
890 }
891
892 template <typename TYPE, typename ALLOC>
894 {
895 if (this->size() == 0){
896 throw noElementError();
897 }
898 TYPE res = this->get(this->size() - 1);
899 this->size_ -= 1;
900 return res;
901 }
902
903 template <typename TYPE, typename ALLOC>
905 return new Iterator(&this->body[this->toInnerIdx(0)], this, 0);
906 }
907
908 template <typename TYPE, typename ALLOC>
910 return new Iterator(&this->body[this->toInnerIdx(this->size() - 1)], this, this->size() - 1);
911 }
912
913 template <typename TYPE, typename ALLOC>
915 {
916 return "vector";
917 }
918
919 template <typename TYPE, typename ALLOC>
921 this->vectorArrayDestroy();
922 }
923
924 template <typename TYPE, typename ALLOC>
926 {
927 if (this == &other)
928 return;
929
930 std::swap(this->size_, other.size_);
931 std::swap(this->max_size, other.max_size);
932 std::swap(this->inner_begin, other.inner_begin);
933 std::swap(this->body, other.body);
934 if constexpr (ALLOC::propagate_on_container_swap::value) {
935 std::swap(this->allocator, other.allocator);
936 }
937 }
938
939 template<typename T, typename... ARGS>
940 original::vector<T> original::makeVector(u_integer size, ARGS &&... args) {
941 return original::vector<T>(size, original::allocator<T>{}, std::forward<ARGS>(args)...);
942 }
943
944 template <typename TYPE, typename ALLOC>
946 {
947 lhs.swap(rhs);
948 }
949
950#endif //VECTOR_H
Provides the array class for a fixed-size container with random access.
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
const TYPE * get() const
Get managed pointer const version.
Definition autoPtr.h:629
Base class for variable-size serial containers.
Definition baseList.h:43
Abstract base class for containers.
Definition container.h:26
void deallocate(TYPE *ptr, u_integer size)
Deallocates memory previously allocated by allocate()
Definition container.h:136
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
void construct(O_TYPE *o_ptr, Args &&... args)
Constructs an element in-place.
Definition container.h:142
A stream class that allows iteration, comparison, hashing and printing.
Definition iterationStream.h:60
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 random-access iterators.
Definition randomAccessIterator.h:39
randomAccessIterator & operator=(const randomAccessIterator &other)
Copy assignment operator.
Definition randomAccessIterator.h:197
Abstract base class for sequential containers with index-based access.
Definition serial.h:34
Abstract base class for unique element containers.
Definition set.h:44
Exception for unimplemented method calls.
Definition error.h:271
Random access iterator implementation for vector.
Definition vector.h:188
Iterator * clone() const override
Clones the iterator.
Definition vector.h:609
Iterator & operator=(const Iterator &other)
Assignment operator for the iterator.
Definition vector.h:599
std::string className() const override
Gets the class name of the iterator.
Definition vector.h:626
bool atNext(const iterator< TYPE > *other) const override
Checks if the iterator is at the next element relative to another iterator.
Definition vector.h:620
bool atPrev(const iterator< TYPE > *other) const override
Checks if the iterator is at the previous element relative to another iterator.
Definition vector.h:614
Dynamic array container with amortized constant time operations.
Definition vector.h:43
u_integer size() const override
Gets the size of the vector.
Definition vector.h:728
vector(const std::initializer_list< TYPE > &list)
Constructs a vector from an initializer list.
Definition vector.h:659
vector & operator=(const vector &other)
Assignment operator for the vector.
Definition vector.h:670
vector(const array< TYPE > &arr)
Constructs a vector from an array.
Definition vector.h:717
TYPE popBegin() override
Removes and returns the first element in the vector.
Definition vector.h:849
TYPE & data() const
Gets a reference to the first element in the vector.
Definition vector.h:740
void push(integer index, const TYPE &e) override
Inserts an element at the specified index in the vector.
Definition vector.h:807
vector(vector &&other) noexcept
Move constructor for the vector.
Definition vector.h:692
~vector() override
Destructor for the vector.
Definition vector.h:920
Iterator * ends() const override
Gets an iterator to the end of the vector.
Definition vector.h:909
u_integer capacity() const noexcept
Gets the current capacity of the vector.
Definition vector.h:734
vector & operator=(vector &&other) noexcept
Move assignment operator for the vector.
Definition vector.h:698
void pushEnd(const TYPE &e) override
Inserts an element at the end of the vector.
Definition vector.h:841
void pushBegin(const TYPE &e) override
Inserts an element at the beginning of the vector.
Definition vector.h:798
std::string className() const override
Gets the class name of the vector.
Definition vector.h:914
vector(u_integer size, ALLOC alloc, ARGS &&... args)
Constructs a vector with specified size and allocator, initializing elements with provided arguments.
Definition vector.h:639
vector(ALLOC alloc=ALLOC{})
Constructs a vector with specified allocator.
Definition vector.h:631
TYPE pop(integer index) override
Removes and returns the element at the specified index.
Definition vector.h:861
u_integer indexOf(const TYPE &e) const override
Finds the index of the first occurrence of the specified element.
Definition vector.h:781
TYPE get(integer index) const override
Gets an element at the specified index.
Definition vector.h:745
void set(integer index, const TYPE &e) override
Sets the element at the specified index.
Definition vector.h:769
Iterator * begins() const override
Gets an iterator to the beginning of the vector.
Definition vector.h:904
TYPE & operator[](integer index) override
Gets a reference to the element at the specified index.
Definition vector.h:757
TYPE popEnd() override
Removes and returns the last element in the vector.
Definition vector.h:893
vector(const vector &other)
Copy constructor for the vector.
Definition vector.h:654
Definition types.h:157
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 with comparison, hashing and printing.
Main namespace for the project Original.
Definition algorithms.h:21
SERIAL< TYPE > list(coroutine::generator< TYPE > gen)
Collects generator elements into a list container.
Standard namespace extensions for original::alternative.
Definition allocator.h:351
std::string to_string(const T &t)
std::to_string overload for printable-derived types
Definition printable.h:415
void swap(original::objPoolAllocator< TYPE > &lhs, original::objPoolAllocator< TYPE > &rhs) noexcept
Specialization of std::swap for objPoolAllocator.
Definition allocator.h:635