ORIGINAL
Loading...
Searching...
No Matches
vector.h
Go to the documentation of this file.
1#ifndef VECTOR_H
2#define VECTOR_H
3
10
11#include "baseList.h"
12#include "iterationStream.h"
13#include "array.h"
14
15
16namespace original{
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 const u_integer INNER_SIZE_INIT = 16;
46 u_integer max_size;
47 u_integer inner_begin;
48 TYPE* body;
49
53 void vectorInit();
54
77 void vectorArrayDestruct() noexcept;
78
87 TYPE* vectorArrayInit(u_integer size);
88
97 static void moveElements(TYPE* old_body, u_integer inner_idx,
98 u_integer len, TYPE* new_body, integer offset);
99
105 [[nodiscard]] u_integer toInnerIdx(integer index) const;
106
112 [[nodiscard]] bool outOfMaxSize(u_integer increment) const;
113
123 void grow(u_integer new_size);
124
129 void adjust(u_integer increment);
130
150 explicit vector(u_integer size, ALLOC alloc = ALLOC{});
151
152 public:
162 class Iterator final : public randomAccessIterator<TYPE, ALLOC>
163 {
170 explicit Iterator(TYPE* ptr, const vector* container, integer pos);
171 public:
172 friend vector;
173
178 Iterator(const Iterator& other);
179
185 Iterator& operator=(const Iterator& other);
186
191 Iterator* clone() const override;
192
198 bool atPrev(const iterator<TYPE> *other) const override;
199
205 bool atNext(const iterator<TYPE> *other) const override;
206
211 [[nodiscard]] std::string className() const override;
212 };
213
220 explicit vector(ALLOC alloc = ALLOC{});
221
236 template<typename... ARGS>
237 vector(u_integer size, ALLOC alloc, ARGS&&... args);
238
243 vector(const vector& other);
244
249 vector(const std::initializer_list<TYPE>& list);
250
255 explicit vector(const array<TYPE>& arr);
256
262 vector& operator=(const vector& other);
263
268 vector(vector&& other) noexcept;
269
275 vector& operator=(vector&& other) noexcept;
276
281 [[nodiscard]] u_integer size() const override;
282
287 TYPE& data() const;
288
294 TYPE get(integer index) const override;
295
301 TYPE& operator[](integer index) override;
302
303 // const version
304 using serial<TYPE, ALLOC>::operator[];
305
311 void set(integer index, const TYPE &e) override;
312
318 u_integer indexOf(const TYPE &e) const override;
319
324 void pushBegin(const TYPE &e) override;
325
331 void push(integer index, const TYPE &e) override;
332
337 void pushEnd(const TYPE &e) override;
338
343 TYPE popBegin() override;
344
350 TYPE pop(integer index) override;
351
356 TYPE popEnd() override;
357
362 Iterator* begins() const override;
363
368 Iterator* ends() const override;
369
374 [[nodiscard]] std::string className() const override;
375
379 ~vector() override;
380
381 template<typename T, typename... ARGS>
382 friend vector<T> makeVector(u_integer size, ARGS&&... args);
383 };
384
404 template<typename T, typename... ARGS>
405 vector<T> makeVector(u_integer size, ARGS&&... args);
406}
407
408 template <typename TYPE, typename ALLOC>
409 auto original::vector<TYPE, ALLOC>::vectorInit() -> void
410 {
411 this->size_ = 0;
412 this->max_size = this->INNER_SIZE_INIT;
413 this->inner_begin = (this->INNER_SIZE_INIT - 1)/2;
414 this->body = vector::vectorArrayInit(this->INNER_SIZE_INIT);
415 }
416
417 template <typename TYPE, typename ALLOC>
418 auto original::vector<TYPE, ALLOC>::vectorArrayDestruct() noexcept -> void
419 {
420 if (this->body) {
421 for (u_integer i = 0; i < this->max_size; ++i) {
422 this->destroy(&this->body[i]);
423 }
424 this->deallocate(this->body, this->max_size);
425 this->body = nullptr;
426 }
427 }
428
429 template <typename TYPE, typename ALLOC>
430 auto original::vector<TYPE, ALLOC>::vectorArrayInit(const u_integer size) -> TYPE* {
431 auto arr = this->allocate(size);
432 for (u_integer i = 0; i < size; i++) {
433 this->construct(&arr[i]);
434 }
435 return arr;
436 }
437
438 template <typename TYPE, typename ALLOC>
439 auto original::vector<TYPE, ALLOC>::moveElements(TYPE* old_body, const u_integer inner_idx,
440 const u_integer len, TYPE* new_body, const integer offset) -> void{
441 if (offset > 0)
442 {
443 for (u_integer i = 0; i < len; i += 1)
444 {
445 new_body[inner_idx + offset + len - 1 - i] = old_body[inner_idx + len - 1 - i];
446 }
447 }else
448 {
449 for (u_integer i = 0; i < len; i += 1)
450 {
451 new_body[inner_idx + offset + i] = old_body[inner_idx + i];
452 }
453 }
454 }
455
456 template <typename TYPE, typename ALLOC>
457 auto original::vector<TYPE, ALLOC>::toInnerIdx(integer index) const -> u_integer
458 {
459 return this->inner_begin + index;
460 }
461
462 template <typename TYPE, typename ALLOC>
463 auto original::vector<TYPE, ALLOC>::outOfMaxSize(u_integer increment) const -> bool
464 {
465 return this->inner_begin + this->size() + increment > this->max_size - 1 || static_cast<integer>(this->inner_begin) - static_cast<integer>(increment) < 0;
466 }
467
468 template <typename TYPE, typename ALLOC>
469 auto original::vector<TYPE, ALLOC>::grow(const u_integer new_size) -> void
470 {
471 TYPE* new_body = vector::vectorArrayInit(new_size);
472 u_integer new_begin = (new_size - 1) / 4;
473 const integer offset = static_cast<integer>(new_begin) - static_cast<integer>(this->inner_begin);
474 vector::moveElements(this->body, this->inner_begin,
475 this->size(), new_body, offset);
476 this->vectorArrayDestruct();
477 this->body = new_body;
478 this->max_size = new_size;
479 this->inner_begin = new_begin;
480 }
481
482 template <typename TYPE, typename ALLOC>
483 auto original::vector<TYPE, ALLOC>::adjust(u_integer increment) -> void {
484 if (!this->outOfMaxSize(increment)) {
485 return;
486 }
487 u_integer new_begin = (this->max_size - this->size() - increment) / 2;
488 if (this->max_size >= this->size_ + increment && new_begin > 0) {
489 const integer offset = static_cast<integer>(new_begin) - static_cast<integer>(this->inner_begin);
490 vector::moveElements(this->body, this->inner_begin, this->size(),
491 this->body, offset);
492 this->inner_begin = new_begin;
493 } else {
494 const u_integer new_max_size = (this->size() + increment) * 2;
495 this->grow(new_max_size);
496 }
497 }
498
499 template <typename TYPE, typename ALLOC>
500 original::vector<TYPE, ALLOC>::Iterator::Iterator(TYPE* ptr, const vector* container, integer pos)
501 : randomAccessIterator<TYPE, ALLOC>(ptr, container, pos) {}
502
503 template <typename TYPE, typename ALLOC>
504 original::vector<TYPE, ALLOC>::Iterator::Iterator(const Iterator& other)
505 : randomAccessIterator<TYPE, ALLOC>(nullptr, nullptr, 0)
506 {
507 this->operator=(other);
508 }
509
510 template <typename TYPE, typename ALLOC>
511 auto original::vector<TYPE, ALLOC>::Iterator::operator=(const Iterator& other) -> Iterator&
512 {
513 if (this == &other) {
514 return *this;
515 }
517 return *this;
518 }
519
520 template <typename TYPE, typename ALLOC>
522 return new Iterator(*this);
523 }
524
525 template <typename TYPE, typename ALLOC>
527 auto other_it = dynamic_cast<const Iterator*>(other);
528 return this->_ptr + 1 == other_it->_ptr;
529 }
530
531 template <typename TYPE, typename ALLOC>
533 auto other_it = dynamic_cast<const Iterator*>(other);
534 return other_it->_ptr + 1 == this->_ptr;
535 }
536
537 template <typename TYPE, typename ALLOC>
539 return "vector::Iterator";
540 }
541
542 template <typename TYPE, typename ALLOC>
543 original::vector<TYPE, ALLOC>::vector(ALLOC alloc)
544 : baseList<TYPE, ALLOC>(std::move(alloc)), size_(), max_size(), inner_begin()
545 {
546 this->vectorInit();
547 }
548
549template<typename TYPE, typename ALLOC>
550template<typename... ARGS>
551original::vector<TYPE, ALLOC>::vector(u_integer size, ALLOC alloc, ARGS&&... args)
552 : vector(size, std::move(alloc)) {
553 this->body = this->allocate(this->max_size);
554 for (u_integer i = 0; i < this->size_; ++i) {
555 this->construct(&this->body[this->toInnerIdx(i)], std::forward<ARGS>(args)...);
556 }
557}
558
559template<typename TYPE, typename ALLOC>
560 original::vector<TYPE, ALLOC>::vector(const u_integer size, ALLOC alloc)
561 : baseList<TYPE, ALLOC>(std::move(alloc)), size_(size),
562 max_size(size * 4 / 3), inner_begin(size / 3 >= 1 ? size / 3 - 1 : 0), body(nullptr) {
563}
564
565 template <typename TYPE, typename ALLOC>
566 original::vector<TYPE, ALLOC>::vector(const vector& other) : vector(){
567 this->operator=(other);
568 }
569
570 template <typename TYPE, typename ALLOC>
571 original::vector<TYPE, ALLOC>::vector(const std::initializer_list<TYPE>& list) : vector()
572 {
573 this->adjust(list.size());
574 for (const TYPE& e: list)
575 {
576 this->body[this->inner_begin + this->size()] = e;
577 this->size_ += 1;
578 }
579 }
580
581 template <typename TYPE, typename ALLOC>
582 auto original::vector<TYPE, ALLOC>::operator=(const vector& other) -> vector&
583 {
584 if (this == &other)
585 return *this;
586
587 this->vectorArrayDestruct();
588
589 this->max_size = other.max_size;
590 this->inner_begin = other.inner_begin;
591 this->size_ = other.size_;
592 this->body = vector::vectorArrayInit(this->max_size);
593 for (u_integer i = 0; i < this->size(); ++i) {
594 const TYPE& data = other.body[this->toInnerIdx(i)];
595 this->body[this->toInnerIdx(i)] = data;
596 }
597 if constexpr (ALLOC::propagate_on_container_copy_assignment::value){
598 this->allocator = other.allocator;
599 }
600 return *this;
601 }
602
603 template <typename TYPE, typename ALLOC>
604 original::vector<TYPE, ALLOC>::vector(vector&& other) noexcept : vector()
605 {
606 this->operator=(std::move(other));
607 }
608
609 template <typename TYPE, typename ALLOC>
610 auto original::vector<TYPE, ALLOC>::operator=(vector&& other) noexcept -> vector&
611 {
612 if (this == &other)
613 return *this;
614
615 this->vectorArrayDestruct();
616 this->body = other.body;
617 other.body = nullptr;
618 this->max_size = other.max_size;
619 this->inner_begin = other.inner_begin;
620 this->size_ = other.size_;
621 if constexpr (ALLOC::propagate_on_container_move_assignment::value){
622 this->allocator = std::move(other.allocator);
623 }
624 other.vectorInit();
625 return *this;
626 }
627
628 template <typename TYPE, typename ALLOC>
629 original::vector<TYPE, ALLOC>::vector(const array<TYPE>& arr) : vector()
630 {
631 this->adjust(arr.size());
632 for (u_integer i = 0; i < arr.size(); i += 1)
633 {
634 this->body[this->toInnerIdx(i)] = arr.get(i);
635 this->size_ += 1;
636 }
637 }
638
639 template <typename TYPE, typename ALLOC>
641 {
642 return this->size_;
643 }
644
645 template <typename TYPE, typename ALLOC>
647 return this->body[this->toInnerIdx(0)];
648 }
649
650 template <typename TYPE, typename ALLOC>
652 {
653 if (this->indexOutOfBound(index))
654 {
655 throw outOfBoundError();
656 }
657 index = this->toInnerIdx(this->parseNegIndex(index));
658 return this->body[index];
659 }
660
661 template <typename TYPE, typename ALLOC>
663 {
664 if (this->indexOutOfBound(index))
665 {
666 throw outOfBoundError();
667 }
668 index = this->toInnerIdx(this->parseNegIndex(index));
669 return this->body[index];
670 }
671
672 template <typename TYPE, typename ALLOC>
673 auto original::vector<TYPE, ALLOC>::set(integer index, const TYPE &e) -> void
674 {
675 if (this->indexOutOfBound(index))
676 {
677 throw outOfBoundError();
678 }
679 index = this->toInnerIdx(this->parseNegIndex(index));
680 this->body[index] = e;
681 }
682
683 template <typename TYPE, typename ALLOC>
685 {
686 for (u_integer i = 0; i < this->size(); i += 1)
687 {
688 if (this->get(i) == e)
689 {
690 return i;
691 }
692 }
693 return this->size();
694 }
695
696 template <typename TYPE, typename ALLOC>
698 {
699 this->adjust(1);
700 this->inner_begin -= 1;
701 this->body[this->toInnerIdx(0)] = e;
702 this->size_ += 1;
703 }
704
705 template <typename TYPE, typename ALLOC>
706 auto original::vector<TYPE, ALLOC>::push(integer index, const TYPE &e) -> void
707 {
708 if (this->parseNegIndex(index) == this->size())
709 {
710 this->pushEnd(e);
711 }else if (this->parseNegIndex(index) == 0)
712 {
713 this->pushBegin(e);
714 }else
715 {
716 if (this->indexOutOfBound(index))
717 {
718 throw outOfBoundError();
719 }
720 this->adjust(1);
721 index = this->toInnerIdx(this->parseNegIndex(index));
722 u_integer rel_idx = index - this->inner_begin;
723 if (index - this->inner_begin <= (this->size() - 1) / 2)
724 {
725 vector::moveElements(this->body, this->inner_begin,
726 rel_idx + 1, this->body, -1);
727 this->inner_begin -= 1;
728 }else
729 {
730 vector::moveElements(this->body, index,
731 this->size() - rel_idx, this->body, 1);
732 }
733 this->body[this->toInnerIdx(rel_idx)] = e;
734 this->size_ += 1;
735 }
736 }
737
738 template <typename TYPE, typename ALLOC>
739 auto original::vector<TYPE, ALLOC>::pushEnd(const TYPE &e) -> void
740 {
741 this->adjust(1);
742 this->body[this->toInnerIdx(this->size())] = e;
743 this->size_ += 1;
744 }
745
746 template <typename TYPE, typename ALLOC>
748 {
749 if (this->size() == 0){
750 throw noElementError();
751 }
752 TYPE res = this->get(0);
753 this->inner_begin += 1;
754 this->size_ -= 1;
755 return res;
756 }
757
758 template <typename TYPE, typename ALLOC>
760 {
761 if (this->parseNegIndex(index) == 0)
762 {
763 return this->popBegin();
764 }
765 if (this->parseNegIndex(index) == this->size() - 1)
766 {
767 return this->popEnd();
768 }
769 if (this->indexOutOfBound(index)){
770 throw outOfBoundError();
771 }
772 TYPE res = this->get(index);
773 index = this->toInnerIdx(this->parseNegIndex(index));
774 u_integer rel_idx = index - this->inner_begin;
775 if (index - this->inner_begin <= (this->size() - 1) / 2)
776 {
777 vector::moveElements(this->body, this->inner_begin,
778 rel_idx, this->body, 1);
779 this->inner_begin += 1;
780 }else
781 {
782 vector::moveElements(this->body, index + 1,
783 this->size() - 1 - rel_idx, this->body, -1);
784 }
785 this->size_ -= 1;
786 return res;
787 }
788
789 template <typename TYPE, typename ALLOC>
791 {
792 if (this->size() == 0){
793 throw noElementError();
794 }
795 TYPE res = this->get(this->size() - 1);
796 this->size_ -= 1;
797 return res;
798 }
799
800 template <typename TYPE, typename ALLOC>
802 return new Iterator(&this->body[this->toInnerIdx(0)], this, 0);
803 }
804
805 template <typename TYPE, typename ALLOC>
807 return new Iterator(&this->body[this->toInnerIdx(this->size() - 1)], this, this->size() - 1);
808 }
809
810 template <typename TYPE, typename ALLOC>
812 {
813 return "vector";
814 }
815
816 template <typename TYPE, typename ALLOC>
818 this->vectorArrayDestruct();
819 }
820
821 template<typename T, typename... ARGS>
822 original::vector<T> original::makeVector(u_integer size, ARGS &&... args) {
823 return original::vector<T>(size, original::allocator<T>{}, std::forward<ARGS>(args)...);
824 }
825
826#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:397
u_integer size() const override
Returns the size of the array.
Definition array.h:386
Base class for variable-size serial containers.
Definition baseList.h:43
Abstract base class for containers.
Definition container.h:28
TYPE * allocate(u_integer size)
Allocates raw memory for elements.
Definition container.h:133
void construct(O_TYPE *o_ptr, Args &&... args)
Constructs an element in-place.
Definition container.h:144
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:37
Exception for missing element requests.
Definition error.h:136
Exception for container index out-of-range errors.
Definition error.h:84
randomAccessIterator(TYPE *ptr, const container< TYPE, ALLOC > *container, integer pos)
Protected constructor for derived classes.
Definition randomAccessIterator.h:181
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
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
Random access iterator implementation for vector.
Definition vector.h:163
Iterator * clone() const override
Clones the iterator.
Definition vector.h:521
Iterator & operator=(const Iterator &other)
Assignment operator for the iterator.
Definition vector.h:511
std::string className() const override
Gets the class name of the iterator.
Definition vector.h:538
bool atNext(const iterator< TYPE > *other) const override
Checks if the iterator is at the next element relative to another iterator.
Definition vector.h:532
bool atPrev(const iterator< TYPE > *other) const override
Checks if the iterator is at the previous element relative to another iterator.
Definition vector.h:526
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:640
vector(const std::initializer_list< TYPE > &list)
Constructs a vector from an initializer list.
Definition vector.h:571
vector & operator=(const vector &other)
Assignment operator for the vector.
Definition vector.h:582
vector(const array< TYPE > &arr)
Constructs a vector from an array.
Definition vector.h:629
TYPE popBegin() override
Removes and returns the first element in the vector.
Definition vector.h:747
TYPE & data() const
Gets a reference to the first element in the vector.
Definition vector.h:646
void push(integer index, const TYPE &e) override
Inserts an element at the specified index in the vector.
Definition vector.h:706
vector(vector &&other) noexcept
Move constructor for the vector.
Definition vector.h:604
~vector() override
Destructor for the vector.
Definition vector.h:817
Iterator * ends() const override
Gets an iterator to the end of the vector.
Definition vector.h:806
vector & operator=(vector &&other) noexcept
Move assignment operator for the vector.
Definition vector.h:610
void pushEnd(const TYPE &e) override
Inserts an element at the end of the vector.
Definition vector.h:739
void pushBegin(const TYPE &e) override
Inserts an element at the beginning of the vector.
Definition vector.h:697
std::string className() const override
Gets the class name of the vector.
Definition vector.h:811
vector(u_integer size, ALLOC alloc, ARGS &&... args)
Constructs a vector with specified size and allocator, initializing elements with provided arguments.
Definition vector.h:551
vector(ALLOC alloc=ALLOC{})
Constructs a vector with specified allocator.
Definition vector.h:543
TYPE pop(integer index) override
Removes and returns the element at the specified index.
Definition vector.h:759
u_integer indexOf(const TYPE &e) const override
Finds the index of the first occurrence of the specified element.
Definition vector.h:684
TYPE get(integer index) const override
Gets an element at the specified index.
Definition vector.h:651
void set(integer index, const TYPE &e) override
Sets the element at the specified index.
Definition vector.h:673
Iterator * begins() const override
Gets an iterator to the beginning of the vector.
Definition vector.h:801
TYPE & operator[](integer index) override
Gets a reference to the element at the specified index.
Definition vector.h:662
TYPE popEnd() override
Removes and returns the last element in the vector.
Definition vector.h:790
vector(const vector &other)
Copy constructor for the vector.
Definition vector.h:566
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 and indexes
Definition config.h:43
std::int64_t integer
64-bit signed integer type for arithmetic operations
Definition config.h:35