|
|
|
#pragma once
|
|
|
|
#include "ft_conatainer.hpp"
|
|
|
|
#include "iterator.hpp"
|
|
|
|
#include <memory>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
namespace ft {
|
|
|
|
|
|
|
|
template < class T, class Allocator = std::allocator< T > > class vector {
|
|
|
|
public:
|
|
|
|
typedef T value_type;
|
|
|
|
typedef Allocator allocator_type;
|
|
|
|
typedef typename Allocator::pointer pointer;
|
|
|
|
typedef typename Allocator::const_pointer cst_pointer;
|
|
|
|
typedef value_type &reference;
|
|
|
|
typedef const value_type &cst_reference;
|
|
|
|
typedef ft::ra_iterator< reference > iterator;
|
|
|
|
typedef ft::ra_iterator< cst_reference > cst_iterator;
|
|
|
|
typedef ft::rev_iterator< iterator > reverse_iterator;
|
|
|
|
typedef ft::rev_iterator< cst_iterator > cst_reverse_iterator;
|
|
|
|
typedef std::ptrdiff_t difference_type;
|
|
|
|
typedef std::size_t size_type;
|
|
|
|
|
|
|
|
private:
|
|
|
|
Allocator _alloc;
|
|
|
|
pointer _begin;
|
|
|
|
size_type _size;
|
|
|
|
size_type _capacity;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit vector(const Allocator &alloc = allocator_type())
|
|
|
|
: _alloc(alloc), _begin(NULL), _size(0), _capacity(0){};
|
|
|
|
|
|
|
|
explicit vector(size_type count, cst_reference value = T(), const Allocator &alloc = allocator_type())
|
|
|
|
: _alloc(alloc), _size(count), _capacity(count) {
|
|
|
|
_begin = _alloc.allocate(count);
|
|
|
|
for (size_type i = 0; i < count; i++)
|
|
|
|
_alloc.construct(_begin + i, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
template < class It >
|
|
|
|
vector(It first, It last, const Allocator &alloc = allocator_type(), typename enable_if<!is_integral<It>, 1>::type is_it = 0 )
|
|
|
|
: _alloc(alloc) {
|
|
|
|
_size = distance(first, last);
|
|
|
|
_capacity = _size;
|
|
|
|
_begin = _alloc.allocate(_size);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
|
|
_alloc.construct(_begin + i, first[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
vector(const vector &other)
|
|
|
|
: _alloc(other._alloc), _size(other._size), _capacity(other._capacity) {
|
|
|
|
_begin = _alloc.allocate(_capacity);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
|
|
_alloc.construct(_begin + i, other._begin[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
~vector(void) {
|
|
|
|
clear();
|
|
|
|
if (_capacity)
|
|
|
|
_alloc.deallocate(_begin, _capacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
vector &operator=(const vector &other) {
|
|
|
|
clear();
|
|
|
|
_alloc.deallocate(_begin, _capacity);
|
|
|
|
_alloc = other._alloc;
|
|
|
|
_capacity = other._capacity;
|
|
|
|
_size = other._size;
|
|
|
|
_begin = _alloc.allocate(_capacity);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
|
|
_alloc.construct(_begin + i, other._begin[i]);
|
|
|
|
return (*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void assign(size_type count, cst_reference value) {
|
|
|
|
resize(count);
|
|
|
|
while (count > 0){
|
|
|
|
_alloc.destroy(this[count]);
|
|
|
|
_alloc.contruct(this[count], value);
|
|
|
|
count--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template < class It > void assign(It first, It last) {
|
|
|
|
size_type i = ft::distance(first, last);
|
|
|
|
resize(i);
|
|
|
|
while (i > 0) {
|
|
|
|
_alloc.destroy(this[i]);
|
|
|
|
_alloc.contruct(this[i], first[i - 1]);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allocator_type get_allocator(void) const { return _alloc; }
|
|
|
|
|
|
|
|
// ACCESS:
|
|
|
|
reference at(size_type pos) {
|
|
|
|
if (pos > _size) throw (std::out_of_range("vector: Out of range access"));
|
|
|
|
return *(_begin + pos);
|
|
|
|
}
|
|
|
|
cst_reference at(size_type pos) const {
|
|
|
|
if (pos > _size) throw (std::out_of_range("vector: Out of range access"));
|
|
|
|
return *(_begin + pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
reference operator[](size_type pos) {return *(_begin + pos);}
|
|
|
|
cst_reference operator[](size_type pos) const {return *(_begin + pos);}
|
|
|
|
|
|
|
|
reference front(void) {return this[0];}
|
|
|
|
cst_reference front(void) const {return this[0];}
|
|
|
|
|
|
|
|
reference back(void) {return this[_size - 1];}
|
|
|
|
cst_reference back(void) const {return this[_size - 1];}
|
|
|
|
|
|
|
|
pointer data(void) {return _begin;}
|
|
|
|
cst_pointer data(void) const {return _begin;}
|
|
|
|
|
|
|
|
// ITERATORS:
|
|
|
|
ra_iterator< T > begin(void) {return ra_iterator<T>(front());}
|
|
|
|
ra_iterator< const T > begin(void) const {return ra_iterator<const T>(front());}
|
|
|
|
|
|
|
|
ra_iterator< T > end(void) {return ra_iterator<T>(this[_size]);}
|
|
|
|
ra_iterator< const T > end(void) const {return ra_iterator<const T>(this[_size]);}
|
|
|
|
|
|
|
|
rev_iterator< iterator > rbegin(void) {return rev_iterator<pointer>(end());}
|
|
|
|
rev_iterator< cst_iterator > rbegin(void) const {return rev_iterator<cst_pointer>(end());}
|
|
|
|
|
|
|
|
rev_iterator< iterator > rend(void) {return rev_iterator<pointer>(begin());}
|
|
|
|
rev_iterator< cst_iterator > rend(void) const {return rev_iterator<cst_pointer>(begin());}
|
|
|
|
|
|
|
|
// CAPACITY:
|
|
|
|
bool empty(void) const { return _size == 0; }
|
|
|
|
size_type size(void) const { return _size; }
|
|
|
|
size_type max_size(void) const { return _alloc.max_size(); }
|
|
|
|
void reserve(size_type new_cap) {
|
|
|
|
if (new_cap > max_size())
|
|
|
|
throw(std::length_error("vector::reserve: new_cap > max_size"));
|
|
|
|
Allocator new_alloc;
|
|
|
|
pointer new_begin;
|
|
|
|
new_begin = new_alloc.allocate(new_cap);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
|
|
new_alloc.construct(new_begin + i, *(_begin + i));
|
|
|
|
clear();
|
|
|
|
_alloc.deallocate(_begin, _capacity);
|
|
|
|
_alloc = new_alloc;
|
|
|
|
_begin = new_begin;
|
|
|
|
_capacity = new_cap;
|
|
|
|
}
|
|
|
|
size_type capacity(void) const { return _capacity; }
|
|
|
|
|
|
|
|
// MODIFIERS:
|
|
|
|
void clear(void) {
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
|
|
_alloc.destroy(_begin + i);
|
|
|
|
_size = 0;
|
|
|
|
}
|
|
|
|
iterator insert(iterator pos, cst_reference value) {
|
|
|
|
if (_size == _capacity)
|
|
|
|
resize(_size + 1);
|
|
|
|
iterator it = end() + 1;;
|
|
|
|
while (--it >= pos)
|
|
|
|
*it = *(it - 1);
|
|
|
|
*it = value;
|
|
|
|
return _begin;
|
|
|
|
}
|
|
|
|
iterator insert(iterator pos, size_type count, cst_reference value) {
|
|
|
|
if ((_size + count) > _capacity)
|
|
|
|
resize(_size + count);
|
|
|
|
iterator it = end() + count;
|
|
|
|
while (--it >= (pos + count))
|
|
|
|
*it = *(it - count);
|
|
|
|
while (it >= pos) {
|
|
|
|
*it = value;
|
|
|
|
it--;
|
|
|
|
}
|
|
|
|
return _begin;
|
|
|
|
}
|
|
|
|
template < class It > iterator insert(iterator pos, It first, It last) {
|
|
|
|
size_type count = ft::distance(first, last);
|
|
|
|
if ((_size + count) > _capacity)
|
|
|
|
resize(_size + count);
|
|
|
|
iterator it = end() + count;
|
|
|
|
while (--it >= (pos + count))
|
|
|
|
*it = *(it - count);
|
|
|
|
while (it >= pos) {
|
|
|
|
*it = *last;
|
|
|
|
it--;
|
|
|
|
last--;
|
|
|
|
}
|
|
|
|
return _begin;
|
|
|
|
}
|
|
|
|
iterator erase(iterator pos) {
|
|
|
|
while (pos < end()) {
|
|
|
|
_alloc.destroy(pos);
|
|
|
|
*pos = *(pos + 1);
|
|
|
|
pos++;
|
|
|
|
}
|
|
|
|
_size--;
|
|
|
|
return _begin;
|
|
|
|
}
|
|
|
|
iterator erase(iterator first, iterator last) {
|
|
|
|
while (last++ < end()){
|
|
|
|
_alloc.destroy(first);
|
|
|
|
*(first++) = *last;
|
|
|
|
}
|
|
|
|
while (first < end() && _size--) {
|
|
|
|
_alloc.destroy(first);
|
|
|
|
*(first++) = value_type();
|
|
|
|
}
|
|
|
|
return _begin;
|
|
|
|
}
|
|
|
|
void push_back(cst_reference value) {
|
|
|
|
if (_size == _capacity)
|
|
|
|
resize(_size + 1);
|
|
|
|
_alloc.construct(back(), value);
|
|
|
|
}
|
|
|
|
void pop_back(void) {
|
|
|
|
_alloc.destroy(back());
|
|
|
|
_size--;
|
|
|
|
}
|
|
|
|
void resize(size_type count, T value = T()) {
|
|
|
|
size_type i = count;
|
|
|
|
if (count < _size) {
|
|
|
|
while (i < _size && --_size)
|
|
|
|
_alloc.destroy(this[i]);
|
|
|
|
} else {
|
|
|
|
if (count > _capacity)
|
|
|
|
reserve(count);
|
|
|
|
while (i >= _size)
|
|
|
|
_alloc.construct(_begin[--i], value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void swap(vector &other) {
|
|
|
|
vector<T> tmp = other;
|
|
|
|
other = this;
|
|
|
|
this = tmp;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace ft
|