You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

509 lines
10 KiB

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vector.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: frdescam <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/08/02 14:50:59 by frdescam #+# #+# */
/* Updated: 2021/10/25 22:25:58 by frdescam ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef VECTOR_HPP
# define VECTOR_HPP
# include <iostream>
# include "vectorIterator.hpp"
namespace ft
{
template <class T, class Alloc = std::allocator<T> >
class vector
{
public:
typedef T value_type;
typedef Alloc allocator_type;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef ft::VectorIterator<T> iterator;
typedef ft::ConstVectorIterator<T> const_iterator;
typedef ft::ReverseVectorIterator<T> reverse_iterator;
typedef ft::ConstReverseVectorIterator<T> const_reverse_iterator;
typedef typename std::ptrdiff_t difference_type;
typedef typename std::size_t size_type;
private:
allocator_type _alloc;
pointer _start;
size_type _size;
size_type _capacity;
public:
explicit vector(const allocator_type &alloc = allocator_type()) :
_alloc(alloc),
_start(0),
_size(0),
_capacity(0)
{
/* NOP */
}
explicit vector(size_type n, const value_type &val = value_type(),
const allocator_type &alloc = allocator_type()) :
_alloc(alloc),
_start(0),
_size(0),
_capacity(0)
{
_start = _alloc.allocate(n);
for (size_type i = 0; i < n; i++)
_alloc.construct(&_start[i], val);
}
template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type &alloc = allocator_type()) :
_alloc(alloc),
_start(0),
_size(0),
_capacity(0)
{
this->insert(this->begin(), first, last);
}
vector (const vector &x) :
_alloc(x._alloc),
_start(0),
_size(0),
_capacity(0)
{
this->insert(this->begin(), x.begin(), x.end() - 1);
}
~vector(void)
{
this->_alloc.deallocate(_start, _capacity);
}
vector &operator=(const vector &other)
{
(void)other;
/* TODO: implement that*/
}
/*
* Iterators
*/
iterator begin(void)
{
return (iterator(_start));
}
const_iterator begin(void) const
{
return (const_iterator(_start));
}
iterator end(void)
{
return (iterator(_start + _size));
}
const_iterator end(void) const
{
return (const_iterator(_start + _size));
}
reverse_iterator rbegin(void)
{
return (reverse_iterator(_start + _size - 1));
}
const_reverse_iterator rbegin(void) const
{
return (const_reverse_iterator(_start + _size - 1));
}
reverse_iterator rend(void)
{
return (reverse_iterator(_start - 1));
}
const_reverse_iterator rend(void) const
{
return (const_reverse_iterator(_start - 1));
}
/*
* Capacity
*/
size_type size(void) const
{
return (_size);
}
size_type max_size(void) const
{
return _alloc.max_size();
}
void resize(size_type n, value_type val = value_type())
{
if (n > _capacity)
reserve(n);
if (n > _size)
{
for (size_type i = _size; i < n; i++)
_alloc.construct(&_start[i], val);
_size = n;
}
else if (n < _size)
{
for (size_type i = n; i < _size; i++)
_alloc.destroy(&_start[i]);
_size = n;
}
}
size_type capacity(void) const
{
return (_capacity);
}
bool empty(void) const
{
if (_size == 0)
return true;
else
return false;
}
void reserve(size_type n)
{
if (n > this->max_size())
throw std::length_error("n greater than vector::max_size()");
if (n > _capacity)
{
value_type *tmp = _alloc.allocate(n);
for (size_type i = 0; i < _size; i++)
{
_alloc.construct(&tmp[i], _start[i]);
_alloc.destroy(&_start[i]);
}
if (_start)
_alloc.deallocate(_start, _capacity);
_capacity = n;
_start = tmp;
}
}
/*
* Element access
*/
reference operator[](size_type n)
{
return _start[n];
}
const_reference operator[](size_type n) const
{
return _start[n];
}
reference at(size_type n)
{
if (n >= _size)
throw std::out_of_range("out of range");
return _start[n];
}
const_reference at(size_type n) const
{
if (n >= _size)
throw std::out_of_range("out of range");
return _start[n];
}
reference front(void)
{
return _start[0];
}
const_reference front(void) const
{
return _start[0];
}
reference back(void)
{
return _start[_size - 1];
}
const_reference back(void) const
{
return _start[_size - 1];
}
/*
* Modifiers
*/
template <class InputIterator>
void assign(InputIterator first, InputIterator last)
{
this->clear();
this->insert(this->begin(), first, last);
}
void assign(size_type n, const value_type &val)
{
if (_capacity < n)
{
this->reserve(n);
_capacity = n;
}
for (size_type i = 0; i < _size; i++)
_alloc.destroy(&_start[i]);
for (size_type i = 0; i < n; i++)
_alloc.construct(&_start, val);
_size = n;
}
void push_back(const value_type &val)
{
if (_capacity < _size + 1)
{
this->reserve(_size + 1);
_capacity = _size + 1;
}
_alloc.construct(&_start[_size], val);
_size++;
}
void pop_back(void)
{
_alloc.destroy(&_start[_size - 1]);
_size--;
}
iterator insert(iterator position, const value_type &val)
{
iterator it;
size_type position_len;
position_len = &(*position) - _start;
if (_size + 1 > _capacity)
this->reserve(_size + 1);
it = this->end();
while (it != iterator(_start + position_len))
{
_alloc.construct(&(*(it)), *(it - 1));
_alloc.destroy(&(*(it - 1)));
it--;
}
_alloc.construct(&(*(it)), val);
_size += 1;
return (it);
}
void insert(iterator position, size_type n, const value_type &val)
{
iterator mv_dest;
iterator mv_source;
size_type position_len;
position_len = &(*position) - _start;
if (_size + n > _capacity)
this->reserve(_size + n);
mv_source = this->end() - 1;
mv_dest = mv_source + n;
while (mv_source >= iterator(_start + position_len))
{
_alloc.construct(&(*(mv_dest)), *mv_source);
_alloc.destroy(&(*(mv_source)));
mv_source--;
mv_dest--;
}
mv_source++;
for (size_type i = 0; i < n; i++)
{
_alloc.construct(&(*(mv_source)), val);
mv_source++;
}
_size += n;
}
template <class InputIterator>
void insert(iterator position, InputIterator first, InputIterator last)
{
iterator tmp;
iterator mv_dest;
iterator mv_source;
size_type nb_items;
size_type position_len;
tmp = iterator(&(*first));
nb_items = 0;
while (tmp < iterator(&(*last)))
{
nb_items++;
tmp++;
}
position_len = &(*position) - _start;
if (_size + nb_items > _capacity)
this->reserve(_size + nb_items);
mv_source = this->end() - 1;
mv_dest = mv_source + nb_items;
while (mv_source >= iterator(_start + position_len))
{
_alloc.construct(&(*(mv_dest)), *mv_source);
_alloc.destroy(&(*(mv_source)));
mv_source--;
mv_dest--;
}
mv_source++;
while (first != last)
{
_alloc.construct(&(*(mv_source)), *first);
mv_source++;
first++;
}
_size += nb_items;
}
iterator erase(iterator position)
{
return (this->erase(position, position + 1));
}
iterator erase(iterator first, iterator last)
{
iterator tmp;
size_type i;
if (first == last)
return (first);
tmp = first;
while (tmp != last)
{
_alloc.destroy(&(*tmp));
tmp++;
_size--;
}
tmp = first;
i = 0;
while (tmp != this->end())
{
_alloc.construct(&(*tmp), *(last + i));
_alloc.destroy(&(*(last + i)));
tmp++;
i++;
}
return (first);
}
void clear(void)
{
for (size_type i = 0; i < _size; i++)
_alloc.destroy(&_start[i]);
_size = 0;
}
void swap (vector &x)
{
vector<value_type> tmp;
tmp = *this;
*this = x;
x = tmp;
}
/*
* Allocator
*/
allocator_type get_allocator(void) const
{
return (_alloc);
}
};
/*
* Non-member function overloads
*/
template <class T, class Alloc>
bool operator==(const vector<T,Alloc> &lhs, const vector<T,Alloc> &rhs)
{
typename ft::vector<T>::const_iterator lit;
typename ft::vector<T>::const_iterator rit;
lit = lhs.begin();
rit = rhs.begin();
if (lhs.size() != rhs.size())
return false;
while (lit != lhs.end())
{
if (*lit != *rit)
return false;
lit++;
rit++;
}
return true;
}
template <class T, class Alloc>
bool operator!=(const vector<T,Alloc> &lhs, const vector<T,Alloc> &rhs)
{
return !(lhs == rhs);
}
template <class T, class Alloc>
bool operator<(const vector<T,Alloc> &lhs, const vector<T,Alloc> &rhs)
{
typename ft::vector<T>::const_iterator lit;
typename ft::vector<T>::const_iterator rit;
lit = lhs.begin();
rit = rhs.begin();
while (lit != lhs.end())
{
if (rit == rhs.end() || (*lit) > (*rit))
return false;
else if ((*lit) < (*rit))
return true;
lit++;
rit++;
}
return rit != rhs.end();
}
template <class T, class Alloc>
bool operator<=(const vector<T,Alloc> &lhs, const vector<T,Alloc> &rhs)
{
return !(rhs < lhs);
}
template <class T, class Alloc>
bool operator>(const vector<T,Alloc> &lhs, const vector<T,Alloc> &rhs)
{
return rhs < lhs;
}
template <class T, class Alloc>
bool operator>=(const vector<T,Alloc> &lhs, const vector<T,Alloc> &rhs)
{
return !(lhs < rhs);
}
template <class T, class Alloc>
void swap (vector<T,Alloc> &x, vector<T,Alloc> &y)
{
x.swap(y);
}
}
#endif