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,
121 u_integer len, TYPE* new_body, integer offset);
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>
265 vector(u_integer size, ALLOC alloc, ARGS&&... args);
266
271 vector(const vector& other);
272
277 vector(const std::initializer_list<TYPE>& list);
278
283 explicit vector(const array<TYPE>& arr);
284
290 vector& operator=(const vector& other);
291
296 vector(vector&& other) noexcept;
297
303 vector& operator=(vector&& other) noexcept;
304
308 ~vector() override;
309
310 // ==================== Capacity Methods ====================
311
316 [[nodiscard]] u_integer size() const override;
317
322 [[nodiscard]] u_integer capacity() const noexcept;
323
324 // ==================== Element Access ====================
325
330 TYPE& data() const;
331
337 TYPE get(integer index) const override;
338
344 TYPE& operator[](integer index) override;
345
346 // const version
347 using serial<TYPE, ALLOC>::operator[];
348
354 void set(integer index, const TYPE &e) override;
355
356 // ==================== Search Operations ====================
357
363 u_integer indexOf(const TYPE &e) const override;
364
365 // ==================== Insertion Operations ====================
366
371 void pushBegin(const TYPE &e) override;
372
378 void push(integer index, const TYPE &e) override;
379
384 void pushEnd(const TYPE &e) override;
385
386 // ==================== Removal Operations ====================
387
392 TYPE popBegin() override;
393
399 TYPE pop(integer index) override;
400
405 TYPE popEnd() override;
406
407 // ==================== Iterator Methods ====================
408
413 Iterator* begins() const override;
414
419 Iterator* ends() const override;
420
421 // ==================== Utility Methods ====================
422
427 [[nodiscard]] std::string className() const override;
428
429 template<typename T, typename... ARGS>
430 friend vector<T> makeVector(u_integer size, ARGS&&... args);
431 };
432
433 // ==================== Factory Function ====================
434
454 template<typename T, typename... ARGS>
455 vector<T> makeVector(u_integer size, ARGS&&... args);
456}
457
458 template <typename TYPE, typename ALLOC>
459 auto original::vector<TYPE, ALLOC>::vectorInit() -> void
460 {
461 this->size_ = 0;
462 this->max_size = INNER_SIZE_INIT;
463 this->inner_begin = (INNER_SIZE_INIT - 1)/2;
464 this->body = vector::vectorArrayInit(INNER_SIZE_INIT);
465 }
466
467 template <typename TYPE, typename ALLOC>
469 {
470 if (this->body) {
471 for (u_integer i = 0; i < this->max_size; ++i) {
472 this->destroy(&this->body[i]);
473 }
474 this->deallocate(this->body, this->max_size);
475 this->body = nullptr;
476 }
477 }
478
479 template <typename TYPE, typename ALLOC>
481 auto arr = this->allocate(size);
482 for (u_integer i = 0; i < size; i++) {
483 this->construct(&arr[i]);
484 }
485 return arr;
486 }
487
488 template <typename TYPE, typename ALLOC>
490 {
491 if constexpr (std::is_copy_constructible_v<TYPE>) {
492 return this->body[pos];
493 } else if constexpr (std::is_move_constructible_v<TYPE>) {
494 return std::move(this->body[pos]);
495 } else {
496 staticError<unSupportedMethodError, !std::is_copy_constructible_v<TYPE> && !std::is_move_constructible_v<TYPE>>::asserts();
497 return TYPE{};
498 }
499 }
500
501 template <typename TYPE, typename ALLOC>
502 void original::vector<TYPE, ALLOC>::setElem(const integer pos, const TYPE& e)
503 {
504 setBufElem(this->body, pos, e);
505 }
506
507 template <typename TYPE, typename ALLOC>
508 void original::vector<TYPE, ALLOC>::setBufElem(TYPE* buf, integer pos, const TYPE& e)
509 {
510 if constexpr (std::is_copy_assignable_v<TYPE>) {
511 buf[pos] = e;
512 } else if constexpr (std::is_move_assignable_v<TYPE>) {
513 buf[pos] = std::move(const_cast<TYPE&>(e));
514 } else {
515 staticError<unSupportedMethodError, !std::is_copy_constructible_v<TYPE> && !std::is_move_constructible_v<TYPE>>::asserts();
516 }
517 }
518
519 template <typename TYPE, typename ALLOC>
520 auto original::vector<TYPE, ALLOC>::moveElements(TYPE* old_body, const u_integer inner_idx,
521 const u_integer len, TYPE* new_body, const integer offset) -> void{
522 if (offset > 0)
523 {
524 for (u_integer i = 0; i < len; i += 1)
525 {
526 setBufElem(new_body, inner_idx + offset + len - 1 - i, old_body[inner_idx + len - 1 - i]);
527 }
528 }else
529 {
530 for (u_integer i = 0; i < len; i += 1)
531 {
532 setBufElem(new_body, inner_idx + offset + i, old_body[inner_idx + i]);
533 }
534 }
535 }
536
537 template <typename TYPE, typename ALLOC>
539 {
540 return this->inner_begin + index;
541 }
542
543 template <typename TYPE, typename ALLOC>
544 auto original::vector<TYPE, ALLOC>::outOfMaxSize(u_integer increment) const -> bool
545 {
546 return this->inner_begin + this->size() + increment > this->max_size - 1 || static_cast<integer>(this->inner_begin) - static_cast<integer>(increment) < 0;
547 }
548
549 template <typename TYPE, typename ALLOC>
550 auto original::vector<TYPE, ALLOC>::grow(const u_integer new_size) -> void
551 {
552 TYPE* new_body = vector::vectorArrayInit(new_size);
553 u_integer new_begin = (new_size - 1) / 4;
554 const integer offset = static_cast<integer>(new_begin) - static_cast<integer>(this->inner_begin);
555 vector::moveElements(this->body, this->inner_begin,
556 this->size(), new_body, offset);
557 this->vectorArrayDestroy();
558 this->body = new_body;
559 this->max_size = new_size;
560 this->inner_begin = new_begin;
561 }
562
563 template <typename TYPE, typename ALLOC>
564 auto original::vector<TYPE, ALLOC>::adjust(u_integer increment) -> void {
565 if (!this->outOfMaxSize(increment)) {
566 return;
567 }
568 u_integer new_begin = (this->max_size - this->size() - increment) / 2;
569 if (this->max_size >= this->size_ + increment && new_begin > 0) {
570 const integer offset = static_cast<integer>(new_begin) - static_cast<integer>(this->inner_begin);
571 vector::moveElements(this->body, this->inner_begin, this->size(),
572 this->body, offset);
573 this->inner_begin = new_begin;
574 } else {
575 const u_integer new_max_size = (this->size() + increment) * 2;
576 this->grow(new_max_size);
577 }
578 }
579
580 template <typename TYPE, typename ALLOC>
582 : randomAccessIterator<TYPE, ALLOC>(ptr, container, pos) {}
583
584 template <typename TYPE, typename ALLOC>
586 : randomAccessIterator<TYPE, ALLOC>(nullptr, nullptr, 0)
587 {
588 this->operator=(other);
589 }
590
591 template <typename TYPE, typename ALLOC>
593 {
594 if (this == &other) {
595 return *this;
596 }
598 return *this;
599 }
600
601 template <typename TYPE, typename ALLOC>
603 return new Iterator(*this);
604 }
605
606 template <typename TYPE, typename ALLOC>
608 auto other_it = dynamic_cast<const Iterator*>(other);
609 return this->_ptr + 1 == other_it->_ptr;
610 }
611
612 template <typename TYPE, typename ALLOC>
614 auto other_it = dynamic_cast<const Iterator*>(other);
615 return other_it->_ptr + 1 == this->_ptr;
616 }
617
618 template <typename TYPE, typename ALLOC>
620 return "vector::Iterator";
621 }
622
623 template <typename TYPE, typename ALLOC>
625 : baseList<TYPE, ALLOC>(std::move(alloc)), size_(), max_size(), inner_begin()
626 {
627 this->vectorInit();
628 }
629
630template<typename TYPE, typename ALLOC>
631template<typename... ARGS>
632original::vector<TYPE, ALLOC>::vector(u_integer size, ALLOC alloc, ARGS&&... args)
633 : vector(size, std::move(alloc)) {
634 this->body = this->allocate(this->max_size);
635 for (u_integer i = 0; i < this->size_; ++i) {
636 this->construct(&this->body[this->toInnerIdx(i)], std::forward<ARGS>(args)...);
637 }
638}
639
640template<typename TYPE, typename ALLOC>
641 original::vector<TYPE, ALLOC>::vector(const u_integer size, ALLOC alloc)
642 : baseList<TYPE, ALLOC>(std::move(alloc)), size_(size),
643 max_size(size * 4 / 3), inner_begin(size / 3 >= 1 ? size / 3 - 1 : 0), body(nullptr) {
644}
645
646 template <typename TYPE, typename ALLOC>
648 this->operator=(other);
649 }
650
651 template <typename TYPE, typename ALLOC>
652 original::vector<TYPE, ALLOC>::vector(const std::initializer_list<TYPE>& list) : vector()
653 {
654 this->adjust(list.size());
655 for (const TYPE& e: list)
656 {
657 this->body[this->inner_begin + this->size()] = e;
658 this->size_ += 1;
659 }
660 }
661
662 template <typename TYPE, typename ALLOC>
664 {
665 if (this == &other)
666 return *this;
667
668 this->vectorArrayDestroy();
669
670 this->max_size = other.max_size;
671 this->inner_begin = other.inner_begin;
672 this->size_ = other.size_;
673 this->body = vector::vectorArrayInit(this->max_size);
674 for (u_integer i = 0; i < this->size(); ++i) {
675 const TYPE& data = other.body[this->toInnerIdx(i)];
676 this->body[this->toInnerIdx(i)] = data;
677 }
678 if constexpr (ALLOC::propagate_on_container_copy_assignment::value){
679 this->allocator = other.allocator;
680 }
681 return *this;
682 }
683
684 template <typename TYPE, typename ALLOC>
686 {
687 this->operator=(std::move(other));
688 }
689
690 template <typename TYPE, typename ALLOC>
692 {
693 if (this == &other)
694 return *this;
695
696 this->vectorArrayDestroy();
697 this->body = other.body;
698 other.body = nullptr;
699 this->max_size = other.max_size;
700 this->inner_begin = other.inner_begin;
701 this->size_ = other.size_;
702 if constexpr (ALLOC::propagate_on_container_move_assignment::value){
703 this->allocator = std::move(other.allocator);
704 }
705 other.vectorInit();
706 return *this;
707 }
708
709 template <typename TYPE, typename ALLOC>
711 {
712 this->adjust(arr.size());
713 for (u_integer i = 0; i < arr.size(); i += 1)
714 {
715 this->body[this->toInnerIdx(i)] = arr.get(i);
716 this->size_ += 1;
717 }
718 }
719
720 template <typename TYPE, typename ALLOC>
722 {
723 return this->size_;
724 }
725
726 template <typename TYPE, typename ALLOC>
728 {
729 return this->max_size;
730 }
731
732 template <typename TYPE, typename ALLOC>
734 return this->body[this->toInnerIdx(0)];
735 }
736
737 template <typename TYPE, typename ALLOC>
739 {
740 if (this->indexOutOfBound(index))
741 {
742 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
743 " out of bound max index " + std::to_string(this->size() - 1) + ".");
744 }
745 index = this->toInnerIdx(this->parseNegIndex(index));
746 return this->getElem(index);
747 }
748
749 template <typename TYPE, typename ALLOC>
751 {
752 if (this->indexOutOfBound(index))
753 {
754 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
755 " out of bound max index " + std::to_string(this->size() - 1) + ".");
756 }
757 index = this->toInnerIdx(this->parseNegIndex(index));
758 return this->body[index];
759 }
760
761 template <typename TYPE, typename ALLOC>
762 auto original::vector<TYPE, ALLOC>::set(integer index, const TYPE &e) -> void
763 {
764 if (this->indexOutOfBound(index))
765 {
766 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
767 " out of bound max index " + std::to_string(this->size() - 1) + ".");
768 }
769 index = this->toInnerIdx(this->parseNegIndex(index));
770 this->setElem(index, e);
771 }
772
773 template <typename TYPE, typename ALLOC>
775 {
776 if constexpr (Comparable<TYPE>) {
777 for (u_integer i = 0; i < this->size(); i += 1)
778 {
779 if (this->get(i) == e)
780 {
781 return i;
782 }
783 }
784 return this->size();
785 } else {
786 throw unSupportedMethodError("Comparison unsupported type");
787 }
788 }
789
790 template <typename TYPE, typename ALLOC>
792 {
793 this->adjust(1);
794 this->inner_begin -= 1;
795 this->setElem(this->toInnerIdx(0), e);
796 this->size_ += 1;
797 }
798
799 template <typename TYPE, typename ALLOC>
800 auto original::vector<TYPE, ALLOC>::push(integer index, const TYPE &e) -> void
801 {
802 if (this->parseNegIndex(index) == this->size())
803 {
804 this->pushEnd(e);
805 }else if (this->parseNegIndex(index) == 0)
806 {
807 this->pushBegin(e);
808 }else
809 {
810 if (this->indexOutOfBound(index))
811 {
812 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
813 " out of bound max index " + std::to_string(this->size() - 1) + ".");
814 }
815 this->adjust(1);
816 index = this->toInnerIdx(this->parseNegIndex(index));
817 u_integer rel_idx = index - this->inner_begin;
818 if (index - this->inner_begin <= (this->size() - 1) / 2)
819 {
820 vector::moveElements(this->body, this->inner_begin,
821 rel_idx + 1, this->body, -1);
822 this->inner_begin -= 1;
823 }else
824 {
825 vector::moveElements(this->body, index,
826 this->size() - rel_idx, this->body, 1);
827 }
828 this->setElem(this->toInnerIdx(rel_idx), e);
829 this->size_ += 1;
830 }
831 }
832
833 template <typename TYPE, typename ALLOC>
834 auto original::vector<TYPE, ALLOC>::pushEnd(const TYPE &e) -> void
835 {
836 this->adjust(1);
837 this->setElem(this->toInnerIdx(this->size()), e);
838 this->size_ += 1;
839 }
840
841 template <typename TYPE, typename ALLOC>
843 {
844 if (this->size() == 0){
845 throw noElementError();
846 }
847 TYPE res = this->get(0);
848 this->inner_begin += 1;
849 this->size_ -= 1;
850 return res;
851 }
852
853 template <typename TYPE, typename ALLOC>
855 {
856 if (this->parseNegIndex(index) == 0)
857 {
858 return this->popBegin();
859 }
860 if (this->parseNegIndex(index) == this->size() - 1)
861 {
862 return this->popEnd();
863 }
864 if (this->indexOutOfBound(index)){
865 throw outOfBoundError("Index " + std::to_string(this->parseNegIndex(index)) +
866 " out of bound max index " + std::to_string(this->size() - 1) + ".");
867 }
868 TYPE res = this->get(index);
869 index = this->toInnerIdx(this->parseNegIndex(index));
870 u_integer rel_idx = index - this->inner_begin;
871 if (index - this->inner_begin <= (this->size() - 1) / 2)
872 {
873 vector::moveElements(this->body, this->inner_begin,
874 rel_idx, this->body, 1);
875 this->inner_begin += 1;
876 }else
877 {
878 vector::moveElements(this->body, index + 1,
879 this->size() - 1 - rel_idx, this->body, -1);
880 }
881 this->size_ -= 1;
882 return res;
883 }
884
885 template <typename TYPE, typename ALLOC>
887 {
888 if (this->size() == 0){
889 throw noElementError();
890 }
891 TYPE res = this->get(this->size() - 1);
892 this->size_ -= 1;
893 return res;
894 }
895
896 template <typename TYPE, typename ALLOC>
898 return new Iterator(&this->body[this->toInnerIdx(0)], this, 0);
899 }
900
901 template <typename TYPE, typename ALLOC>
903 return new Iterator(&this->body[this->toInnerIdx(this->size() - 1)], this, this->size() - 1);
904 }
905
906 template <typename TYPE, typename ALLOC>
908 {
909 return "vector";
910 }
911
912 template <typename TYPE, typename ALLOC>
914 this->vectorArrayDestroy();
915 }
916
917 template<typename T, typename... ARGS>
918 original::vector<T> original::makeVector(u_integer size, ARGS &&... args) {
919 return original::vector<T>(size, original::allocator<T>{}, std::forward<ARGS>(args)...);
920 }
921
922#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: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
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
container(ALLOC alloc=ALLOC{})
Constructs a container with specified allocator.
Definition container.h:127
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, 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
Abstract base class for random-access iterators.
Definition randomAccessIterator.h:39
randomAccessIterator & operator=(const randomAccessIterator &other)
Copy assignment operator.
Definition randomAccessIterator.h:197
TYPE * _ptr
Pointer to the current element.
Definition randomAccessIterator.h:41
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:192
Random access iterator implementation for vector.
Definition vector.h:188
Iterator * clone() const override
Clones the iterator.
Definition vector.h:602
Iterator & operator=(const Iterator &other)
Assignment operator for the iterator.
Definition vector.h:592
std::string className() const override
Gets the class name of the iterator.
Definition vector.h:619
bool atNext(const iterator< TYPE > *other) const override
Checks if the iterator is at the next element relative to another iterator.
Definition vector.h:613
bool atPrev(const iterator< TYPE > *other) const override
Checks if the iterator is at the previous element relative to another iterator.
Definition vector.h:607
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:721
vector(const std::initializer_list< TYPE > &list)
Constructs a vector from an initializer list.
Definition vector.h:652
vector & operator=(const vector &other)
Assignment operator for the vector.
Definition vector.h:663
vector(const array< TYPE > &arr)
Constructs a vector from an array.
Definition vector.h:710
TYPE popBegin() override
Removes and returns the first element in the vector.
Definition vector.h:842
TYPE & data() const
Gets a reference to the first element in the vector.
Definition vector.h:733
void push(integer index, const TYPE &e) override
Inserts an element at the specified index in the vector.
Definition vector.h:800
vector(vector &&other) noexcept
Move constructor for the vector.
Definition vector.h:685
~vector() override
Destructor for the vector.
Definition vector.h:913
Iterator * ends() const override
Gets an iterator to the end of the vector.
Definition vector.h:902
u_integer capacity() const noexcept
Gets the current capacity of the vector.
Definition vector.h:727
vector & operator=(vector &&other) noexcept
Move assignment operator for the vector.
Definition vector.h:691
void pushEnd(const TYPE &e) override
Inserts an element at the end of the vector.
Definition vector.h:834
void pushBegin(const TYPE &e) override
Inserts an element at the beginning of the vector.
Definition vector.h:791
std::string className() const override
Gets the class name of the vector.
Definition vector.h:907
vector(u_integer size, ALLOC alloc, ARGS &&... args)
Constructs a vector with specified size and allocator, initializing elements with provided arguments.
Definition vector.h:632
vector(ALLOC alloc=ALLOC{})
Constructs a vector with specified allocator.
Definition vector.h:624
TYPE pop(integer index) override
Removes and returns the element at the specified index.
Definition vector.h:854
u_integer indexOf(const TYPE &e) const override
Finds the index of the first occurrence of the specified element.
Definition vector.h:774
TYPE get(integer index) const override
Gets an element at the specified index.
Definition vector.h:738
void set(integer index, const TYPE &e) override
Sets the element at the specified index.
Definition vector.h:762
Iterator * begins() const override
Gets an iterator to the beginning of the vector.
Definition vector.h:897
TYPE & operator[](integer index) override
Gets a reference to the element at the specified index.
Definition vector.h:750
TYPE popEnd() override
Removes and returns the last element in the vector.
Definition vector.h:886
vector(const vector &other)
Copy constructor for the vector.
Definition vector.h:647
Requires type to support all comparison operators.
Definition types.h:92
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