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
15namespace original{
41 template <typename TYPE, typename ALLOC = allocator<TYPE>>
42 class vector final : public baseList<TYPE, ALLOC>, public iterationStream<TYPE, vector<TYPE, ALLOC>>{
43 u_integer size_;
44 const u_integer INNER_SIZE_INIT = 16;
45 u_integer max_size;
46 u_integer inner_begin;
47 TYPE* body;
48
52 void vectorInit();
53
76 void vectorArrayDestruct() noexcept;
77
86 TYPE* vectorArrayInit(u_integer size);
87
96 static void moveElements(TYPE* old_body, u_integer inner_idx,
97 u_integer len, TYPE* new_body, integer offset);
98
104 [[nodiscard]] u_integer toInnerIdx(integer index) const;
105
111 [[nodiscard]] bool outOfMaxSize(u_integer increment) const;
112
122 void grow(u_integer new_size);
123
128 void adjust(u_integer increment);
129
130 public:
140 class Iterator final : public randomAccessIterator<TYPE, ALLOC>
141 {
148 explicit Iterator(TYPE* ptr, const vector* container, integer pos);
149 public:
150 friend vector;
151
156 Iterator(const Iterator& other);
157
163 Iterator& operator=(const Iterator& other);
164
169 Iterator* clone() const override;
170
176 bool atPrev(const iterator<TYPE> *other) const override;
177
183 bool atNext(const iterator<TYPE> *other) const override;
184
189 [[nodiscard]] std::string className() const override;
190 };
191
198 explicit vector(ALLOC alloc = ALLOC{});
199
204 vector(const vector& other);
205
210 vector(const std::initializer_list<TYPE>& list);
211
216 explicit vector(const array<TYPE>& arr);
217
223 vector& operator=(const vector& other);
224
229 vector(vector&& other) noexcept;
230
236 vector& operator=(vector&& other) noexcept;
237
242 [[nodiscard]] u_integer size() const override;
243
248 TYPE& data() const;
249
255 TYPE get(integer index) const override;
256
262 TYPE& operator[](integer index) override;
263
269 void set(integer index, const TYPE &e) override;
270
276 u_integer indexOf(const TYPE &e) const override;
277
282 void pushBegin(const TYPE &e) override;
283
289 void push(integer index, const TYPE &e) override;
290
295 void pushEnd(const TYPE &e) override;
296
301 TYPE popBegin() override;
302
308 TYPE pop(integer index) override;
309
314 TYPE popEnd() override;
315
320 Iterator* begins() const override;
321
326 Iterator* ends() const override;
327
332 [[nodiscard]] std::string className() const override;
333
337 ~vector() override;
338 };
339}
340
341 template <typename TYPE, typename ALLOC>
342 auto original::vector<TYPE, ALLOC>::vectorInit() -> void
343 {
344 this->size_ = 0;
345 this->max_size = this->INNER_SIZE_INIT;
346 this->inner_begin = (this->INNER_SIZE_INIT - 1)/2;
347 this->body = vector::vectorArrayInit(this->INNER_SIZE_INIT);
348 }
349
350 template <typename TYPE, typename ALLOC>
351 auto original::vector<TYPE, ALLOC>::vectorArrayDestruct() noexcept -> void
352 {
353 if (this->body) {
354 for (u_integer i = 0; i < this->max_size; ++i) {
355 this->destroy(&this->body[i]);
356 }
357 this->deallocate(this->body, this->max_size);
358 this->body = nullptr;
359 }
360 }
361
362 template <typename TYPE, typename ALLOC>
363 auto original::vector<TYPE, ALLOC>::vectorArrayInit(const u_integer size) -> TYPE* {
364 auto arr = this->allocate(size);
365 for (u_integer i = 0; i < size; i++) {
366 this->construct(&arr[i]);
367 }
368 return arr;
369 }
370
371 template <typename TYPE, typename ALLOC>
372 auto original::vector<TYPE, ALLOC>::moveElements(TYPE* old_body, const u_integer inner_idx,
373 const u_integer len, TYPE* new_body, const integer offset) -> void{
374 if (offset > 0)
375 {
376 for (u_integer i = 0; i < len; i += 1)
377 {
378 new_body[inner_idx + offset + len - 1 - i] = old_body[inner_idx + len - 1 - i];
379 }
380 }else
381 {
382 for (u_integer i = 0; i < len; i += 1)
383 {
384 new_body[inner_idx + offset + i] = old_body[inner_idx + i];
385 }
386 }
387 }
388
389 template <typename TYPE, typename ALLOC>
390 auto original::vector<TYPE, ALLOC>::toInnerIdx(integer index) const -> u_integer
391 {
392 return this->inner_begin + index;
393 }
394
395 template <typename TYPE, typename ALLOC>
396 auto original::vector<TYPE, ALLOC>::outOfMaxSize(u_integer increment) const -> bool
397 {
398 return this->inner_begin + this->size() + increment > this->max_size - 1 || static_cast<integer>(this->inner_begin) - static_cast<integer>(increment) < 0;
399 }
400
401 template <typename TYPE, typename ALLOC>
402 auto original::vector<TYPE, ALLOC>::grow(const u_integer new_size) -> void
403 {
404 TYPE* new_body = vector::vectorArrayInit(new_size);
405 u_integer new_begin = (new_size - 1) / 4;
406 const integer offset = static_cast<integer>(new_begin) - static_cast<integer>(this->inner_begin);
407 vector::moveElements(this->body, this->inner_begin,
408 this->size(), new_body, offset);
409 this->vectorArrayDestruct();
410 this->body = new_body;
411 this->max_size = new_size;
412 this->inner_begin = new_begin;
413 }
414
415 template <typename TYPE, typename ALLOC>
416 auto original::vector<TYPE, ALLOC>::adjust(u_integer increment) -> void {
417 if (!this->outOfMaxSize(increment)) {
418 return;
419 }
420 u_integer new_begin = (this->max_size - this->size() - increment) / 2;
421 if (this->max_size >= this->size_ + increment && new_begin > 0) {
422 const integer offset = static_cast<integer>(new_begin) - static_cast<integer>(this->inner_begin);
423 vector::moveElements(this->body, this->inner_begin, this->size(),
424 this->body, offset);
425 this->inner_begin = new_begin;
426 } else {
427 const u_integer new_max_size = (this->size() + increment) * 2;
428 this->grow(new_max_size);
429 }
430 }
431
432 template <typename TYPE, typename ALLOC>
433 original::vector<TYPE, ALLOC>::Iterator::Iterator(TYPE* ptr, const vector* container, integer pos)
434 : randomAccessIterator<TYPE, ALLOC>(ptr, container, pos) {}
435
436 template <typename TYPE, typename ALLOC>
437 original::vector<TYPE, ALLOC>::Iterator::Iterator(const Iterator& other)
438 : randomAccessIterator<TYPE, ALLOC>(nullptr, nullptr, 0)
439 {
440 this->operator=(other);
441 }
442
443 template <typename TYPE, typename ALLOC>
444 auto original::vector<TYPE, ALLOC>::Iterator::operator=(const Iterator& other) -> Iterator&
445 {
446 if (this == &other) {
447 return *this;
448 }
450 return *this;
451 }
452
453 template <typename TYPE, typename ALLOC>
455 return new Iterator(*this);
456 }
457
458 template <typename TYPE, typename ALLOC>
460 auto other_it = dynamic_cast<const Iterator*>(other);
461 return this->_ptr + 1 == other_it->_ptr;
462 }
463
464 template <typename TYPE, typename ALLOC>
466 auto other_it = dynamic_cast<const Iterator*>(other);
467 return other_it->_ptr + 1 == this->_ptr;
468 }
469
470 template <typename TYPE, typename ALLOC>
472 return "vector::Iterator";
473 }
474
475 template <typename TYPE, typename ALLOC>
477 : baseList<TYPE, ALLOC>(std::move(alloc)), size_(), max_size(), inner_begin()
478 {
479 this->vectorInit();
480 }
481
482 template <typename TYPE, typename ALLOC>
484 this->operator=(other);
485 }
486
487 template <typename TYPE, typename ALLOC>
488 original::vector<TYPE, ALLOC>::vector(const std::initializer_list<TYPE>& list) : vector()
489 {
490 this->adjust(list.size());
491 for (const TYPE& e: list)
492 {
493 this->body[this->inner_begin + this->size()] = e;
494 this->size_ += 1;
495 }
496 }
497
498 template <typename TYPE, typename ALLOC>
500 {
501 if (this == &other)
502 return *this;
503
504 this->vectorArrayDestruct();
505
506 this->max_size = other.max_size;
507 this->inner_begin = other.inner_begin;
508 this->size_ = other.size_;
509 this->body = vector::vectorArrayInit(this->max_size);
510 for (u_integer i = 0; i < this->size(); ++i) {
511 const TYPE& data = other.body[this->toInnerIdx(i)];
512 this->body[this->toInnerIdx(i)] = data;
513 }
514 if constexpr (ALLOC::propagate_on_container_copy_assignment::value){
515 this->allocator = other.allocator;
516 }
517 return *this;
518 }
519
520 template <typename TYPE, typename ALLOC>
522 {
523 this->operator=(std::move(other));
524 }
525
526 template <typename TYPE, typename ALLOC>
528 {
529 if (this == &other)
530 return *this;
531
532 this->vectorArrayDestruct();
533 this->body = other.body;
534 other.body = nullptr;
535 this->max_size = other.max_size;
536 this->inner_begin = other.inner_begin;
537 this->size_ = other.size_;
538 if constexpr (ALLOC::propagate_on_container_move_assignment::value){
539 this->allocator = std::move(other.allocator);
540 }
541 other.vectorInit();
542 return *this;
543 }
544
545 template <typename TYPE, typename ALLOC>
547 {
548 this->adjust(arr.size());
549 for (u_integer i = 0; i < arr.size(); i += 1)
550 {
551 this->body[this->toInnerIdx(i)] = arr.get(i);
552 this->size_ += 1;
553 }
554 }
555
556 template <typename TYPE, typename ALLOC>
558 {
559 return this->size_;
560 }
561
562 template <typename TYPE, typename ALLOC>
564 return this->body[this->toInnerIdx(0)];
565 }
566
567 template <typename TYPE, typename ALLOC>
569 {
570 if (this->indexOutOfBound(index))
571 {
572 throw outOfBoundError();
573 }
574 index = this->toInnerIdx(this->parseNegIndex(index));
575 return this->body[index];
576 }
577
578 template <typename TYPE, typename ALLOC>
580 {
581 if (this->indexOutOfBound(index))
582 {
583 throw outOfBoundError();
584 }
585 index = this->toInnerIdx(this->parseNegIndex(index));
586 return this->body[index];
587 }
588
589 template <typename TYPE, typename ALLOC>
590 auto original::vector<TYPE, ALLOC>::set(integer index, const TYPE &e) -> void
591 {
592 if (this->indexOutOfBound(index))
593 {
594 throw outOfBoundError();
595 }
596 index = this->toInnerIdx(this->parseNegIndex(index));
597 this->body[index] = e;
598 }
599
600 template <typename TYPE, typename ALLOC>
602 {
603 for (u_integer i = 0; i < this->size(); i += 1)
604 {
605 if (this->get(i) == e)
606 {
607 return i;
608 }
609 }
610 return this->size();
611 }
612
613 template <typename TYPE, typename ALLOC>
615 {
616 this->adjust(1);
617 this->inner_begin -= 1;
618 this->body[this->toInnerIdx(0)] = e;
619 this->size_ += 1;
620 }
621
622 template <typename TYPE, typename ALLOC>
623 auto original::vector<TYPE, ALLOC>::push(integer index, const TYPE &e) -> void
624 {
625 if (this->parseNegIndex(index) == this->size())
626 {
627 this->pushEnd(e);
628 }else if (this->parseNegIndex(index) == 0)
629 {
630 this->pushBegin(e);
631 }else
632 {
633 if (this->indexOutOfBound(index))
634 {
635 throw outOfBoundError();
636 }
637 this->adjust(1);
638 index = this->toInnerIdx(this->parseNegIndex(index));
639 u_integer rel_idx = index - this->inner_begin;
640 if (index - this->inner_begin <= (this->size() - 1) / 2)
641 {
642 vector::moveElements(this->body, this->inner_begin,
643 rel_idx + 1, this->body, -1);
644 this->inner_begin -= 1;
645 }else
646 {
647 vector::moveElements(this->body, index,
648 this->size() - rel_idx, this->body, 1);
649 }
650 this->body[this->toInnerIdx(rel_idx)] = e;
651 this->size_ += 1;
652 }
653 }
654
655 template <typename TYPE, typename ALLOC>
656 auto original::vector<TYPE, ALLOC>::pushEnd(const TYPE &e) -> void
657 {
658 this->adjust(1);
659 this->body[this->toInnerIdx(this->size())] = e;
660 this->size_ += 1;
661 }
662
663 template <typename TYPE, typename ALLOC>
665 {
666 if (this->size() == 0){
667 throw noElementError();
668 }
669 TYPE res = this->get(0);
670 this->inner_begin += 1;
671 this->size_ -= 1;
672 return res;
673 }
674
675 template <typename TYPE, typename ALLOC>
677 {
678 if (this->parseNegIndex(index) == 0)
679 {
680 return this->popBegin();
681 }
682 if (this->parseNegIndex(index) == this->size() - 1)
683 {
684 return this->popEnd();
685 }
686 if (this->indexOutOfBound(index)){
687 throw outOfBoundError();
688 }
689 TYPE res = this->get(index);
690 index = this->toInnerIdx(this->parseNegIndex(index));
691 u_integer rel_idx = index - this->inner_begin;
692 if (index - this->inner_begin <= (this->size() - 1) / 2)
693 {
694 vector::moveElements(this->body, this->inner_begin,
695 rel_idx, this->body, 1);
696 this->inner_begin += 1;
697 }else
698 {
699 vector::moveElements(this->body, index + 1,
700 this->size() - 1 - rel_idx, this->body, -1);
701 }
702 this->size_ -= 1;
703 return res;
704 }
705
706 template <typename TYPE, typename ALLOC>
708 {
709 if (this->size() == 0){
710 throw noElementError();
711 }
712 TYPE res = this->get(this->size() - 1);
713 this->size_ -= 1;
714 return res;
715 }
716
717 template <typename TYPE, typename ALLOC>
719 return new Iterator(&this->body[this->toInnerIdx(0)], this, 0);
720 }
721
722 template <typename TYPE, typename ALLOC>
724 return new Iterator(&this->body[this->toInnerIdx(this->size() - 1)], this, this->size() - 1);
725 }
726
727 template <typename TYPE, typename ALLOC>
729 {
730 return "vector";
731 }
732
733 template <typename TYPE, typename ALLOC>
735 this->vectorArrayDestruct();
736 }
737
738#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:393
u_integer size() const override
Returns the size of the array.
Definition array.h:382
Base class for variable-size serial containers.
Definition baseList.h:43
Abstract base class for containers.
Definition container.h:28
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:35
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
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:141
Iterator * clone() const override
Clones the iterator.
Definition vector.h:454
Iterator & operator=(const Iterator &other)
Assignment operator for the iterator.
Definition vector.h:444
std::string className() const override
Gets the class name of the iterator.
Definition vector.h:471
bool atNext(const iterator< TYPE > *other) const override
Checks if the iterator is at the next element relative to another iterator.
Definition vector.h:465
bool atPrev(const iterator< TYPE > *other) const override
Checks if the iterator is at the previous element relative to another iterator.
Definition vector.h:459
u_integer size() const override
Gets the size of the vector.
Definition vector.h:557
vector(const std::initializer_list< TYPE > &list)
Constructs a vector from an initializer list.
Definition vector.h:488
vector & operator=(const vector &other)
Assignment operator for the vector.
Definition vector.h:499
vector(const array< TYPE > &arr)
Constructs a vector from an array.
Definition vector.h:546
TYPE popBegin() override
Removes and returns the first element in the vector.
Definition vector.h:664
TYPE & data() const
Gets a reference to the first element in the vector.
Definition vector.h:563
void push(integer index, const TYPE &e) override
Inserts an element at the specified index in the vector.
Definition vector.h:623
vector(vector &&other) noexcept
Move constructor for the vector.
Definition vector.h:521
~vector() override
Destructor for the vector.
Definition vector.h:734
Iterator * ends() const override
Gets an iterator to the end of the vector.
Definition vector.h:723
vector & operator=(vector &&other) noexcept
Move assignment operator for the vector.
Definition vector.h:527
void pushEnd(const TYPE &e) override
Inserts an element at the end of the vector.
Definition vector.h:656
void pushBegin(const TYPE &e) override
Inserts an element at the beginning of the vector.
Definition vector.h:614
std::string className() const override
Gets the class name of the vector.
Definition vector.h:728
vector(ALLOC alloc=ALLOC{})
Constructs a vector with specified allocator.
Definition vector.h:476
TYPE pop(integer index) override
Removes and returns the element at the specified index.
Definition vector.h:676
u_integer indexOf(const TYPE &e) const override
Finds the index of the first occurrence of the specified element.
Definition vector.h:601
TYPE get(integer index) const override
Gets an element at the specified index.
Definition vector.h:568
void set(integer index, const TYPE &e) override
Sets the element at the specified index.
Definition vector.h:590
Iterator * begins() const override
Gets an iterator to the beginning of the vector.
Definition vector.h:718
TYPE & operator[](integer index) override
Gets a reference to the element at the specified index.
Definition vector.h:579
TYPE popEnd() override
Removes and returns the last element in the vector.
Definition vector.h:707
vector(const vector &other)
Copy constructor for the vector.
Definition vector.h:483
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/indexes
Definition config.h:17
std::int64_t integer
64-bit signed integer type for arithmetic operations
Definition config.h:15