|
|
@ -7,6 +7,8 @@ |
|
|
|
#include <memory> |
|
|
|
#include <stdexcept> |
|
|
|
|
|
|
|
#define OVER_ALLOC 3 |
|
|
|
|
|
|
|
namespace ft { |
|
|
|
|
|
|
|
template < class T, class Alloc = std::allocator< T > > class vector { |
|
|
@ -36,8 +38,14 @@ public: |
|
|
|
|
|
|
|
explicit vector(size_type count, const_reference value = T(), |
|
|
|
const Alloc &alloc = allocator_type()) |
|
|
|
: _alloc(alloc), _size(count), _capacity(count) { |
|
|
|
_begin = _alloc.allocate(count); |
|
|
|
: _alloc(alloc), _size(count), _capacity(0) { |
|
|
|
if (count > _alloc.max_size()) |
|
|
|
throw std::length_error("vector: too high size."); |
|
|
|
else if (count == 0) |
|
|
|
return; |
|
|
|
else |
|
|
|
_capacity = std::min(OVER_ALLOC * count, _alloc.max_size() - 1); |
|
|
|
_begin = _alloc.allocate(_capacity); |
|
|
|
for (size_type i = 0; i < count; i++) |
|
|
|
_alloc.construct(_begin + i, value); |
|
|
|
} |
|
|
@ -45,16 +53,14 @@ public: |
|
|
|
template < class It > |
|
|
|
vector(It first, It last, const Alloc &alloc = allocator_type(), |
|
|
|
typename ft::enable_if< !is_integral< It >::value, bool >::type = 0) |
|
|
|
: _alloc(alloc) { |
|
|
|
_size = ft::distance(first, last) - 1; |
|
|
|
_capacity = _size; |
|
|
|
_begin = _alloc.allocate(_size); |
|
|
|
for (size_type i = 0; i < _size; i++) |
|
|
|
_alloc.construct(_begin + i, *(first++)); |
|
|
|
: _alloc(alloc), _size(0), _capacity(0) { |
|
|
|
assign(first, last); |
|
|
|
} |
|
|
|
|
|
|
|
vector(const vector &other) |
|
|
|
: _alloc(other._alloc), _size(other._size), _capacity(other._capacity) { |
|
|
|
if (_capacity == 0) |
|
|
|
return; |
|
|
|
_begin = _alloc.allocate(_capacity); |
|
|
|
for (size_type i = 0; i < _size; i++) |
|
|
|
_alloc.construct(_begin + i, other._begin[i]); |
|
|
@ -62,17 +68,19 @@ public: |
|
|
|
|
|
|
|
~vector(void) { |
|
|
|
clear(); |
|
|
|
if (_capacity) |
|
|
|
if (_capacity > 0) |
|
|
|
_alloc.deallocate(_begin, _capacity); |
|
|
|
} |
|
|
|
|
|
|
|
vector &operator=(const vector &other) { |
|
|
|
clear(); |
|
|
|
_alloc.deallocate(_begin, _capacity); |
|
|
|
if (_capacity > 0) |
|
|
|
_alloc.deallocate(_begin, _capacity); |
|
|
|
_alloc = other._alloc; |
|
|
|
_capacity = other._capacity; |
|
|
|
_size = other._size; |
|
|
|
_begin = _alloc.allocate(_capacity); |
|
|
|
if (_capacity > 0) |
|
|
|
_begin = _alloc.allocate(_capacity); |
|
|
|
for (size_type i = 0; i < _size; i++) |
|
|
|
_alloc.construct(_begin + i, other._begin[i]); |
|
|
|
return (*this); |
|
|
@ -80,24 +88,36 @@ public: |
|
|
|
|
|
|
|
void assign(size_type count, const_reference value) { |
|
|
|
resize(count); |
|
|
|
while (count--) { |
|
|
|
_alloc.destroy(_begin + count); |
|
|
|
_alloc.construct(_begin + count, value); |
|
|
|
}; |
|
|
|
iterator it = begin(); |
|
|
|
while (it != end()) |
|
|
|
*it++ = value; |
|
|
|
} |
|
|
|
template < class It > |
|
|
|
void assign(It first, It last, |
|
|
|
void |
|
|
|
assign(It first, It last, |
|
|
|
typename ft::enable_if< !is_integral< It >::value, bool >::type = 0) { |
|
|
|
size_type count = ft::distance(first, last) - 1; |
|
|
|
resize(count); |
|
|
|
size_t i = 0; |
|
|
|
while (i < count) { |
|
|
|
_alloc.destroy(_begin + i); |
|
|
|
_alloc.construct(_begin + i, *(first++)); |
|
|
|
i++; |
|
|
|
} |
|
|
|
typename ft::iterator_traits< It >::iterator_category category; |
|
|
|
range_assign(first, last, category); |
|
|
|
} |
|
|
|
|
|
|
|
template < class It > |
|
|
|
void range_assign(It first, It last, std::input_iterator_tag) { |
|
|
|
clear(); |
|
|
|
while (first != last) |
|
|
|
push_back(*first++); |
|
|
|
} |
|
|
|
|
|
|
|
template < class It > |
|
|
|
void range_assign(It first, It last, std::forward_iterator_tag) { |
|
|
|
size_type count = ft::distance(first, last); |
|
|
|
if (count == 0) |
|
|
|
return clear(); |
|
|
|
vector< T, Alloc > ret(count); |
|
|
|
iterator it = ret.begin(); |
|
|
|
for (size_type i = 0; first != last; i++) |
|
|
|
*(it + i) = *(first++); |
|
|
|
*this = ret; |
|
|
|
} |
|
|
|
allocator_type get_allocator(void) const { return _alloc; } |
|
|
|
|
|
|
|
// ACCESS:
|
|
|
@ -145,115 +165,161 @@ public: |
|
|
|
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) { |
|
|
|
size_type capacity(void) const { return _capacity; } |
|
|
|
|
|
|
|
void reserve(size_type new_cap) { |
|
|
|
if (new_cap > max_size()) |
|
|
|
throw(std::length_error("vector::reserve: new_cap > max_size")); |
|
|
|
if (new_cap < _capacity) |
|
|
|
return ; |
|
|
|
Alloc new_alloc; |
|
|
|
pointer new_begin; |
|
|
|
if (new_cap <= _capacity) |
|
|
|
return; |
|
|
|
else |
|
|
|
new_cap = std::min(OVER_ALLOC * new_cap, _alloc.max_size() - 1); |
|
|
|
Alloc new_alloc; |
|
|
|
pointer new_begin; |
|
|
|
size_type new_size = _size; |
|
|
|
new_begin = new_alloc.allocate(new_cap); |
|
|
|
size_t new_size; |
|
|
|
new_size = new_cap < _capacity ? new_cap : _size; |
|
|
|
for (size_type i = 0; i < new_size; i++) |
|
|
|
for (size_type i = 0; i < _size; i++) |
|
|
|
new_alloc.construct(new_begin + i, *(_begin + i)); |
|
|
|
if (!empty()) |
|
|
|
clear(); |
|
|
|
if (_capacity) |
|
|
|
clear(); |
|
|
|
if (_capacity > 0) |
|
|
|
_alloc.deallocate(_begin, _capacity); |
|
|
|
_alloc = new_alloc; |
|
|
|
_begin = new_begin; |
|
|
|
_capacity = new_cap; |
|
|
|
_size = new_size; |
|
|
|
_capacity = new_cap; |
|
|
|
} |
|
|
|
size_type capacity(void) const { return _capacity; } |
|
|
|
|
|
|
|
// MODIFIERS:
|
|
|
|
void clear(void) { |
|
|
|
if (_size == 0) |
|
|
|
return; |
|
|
|
for (size_type i = 0; i < _size; i++) |
|
|
|
_alloc.destroy(_begin + i); |
|
|
|
_size = 0; |
|
|
|
} |
|
|
|
|
|
|
|
iterator insert(const_iterator pos, const_reference value) { |
|
|
|
if (_size == _capacity) |
|
|
|
resize(_size + 1); |
|
|
|
iterator insert(iterator pos, const_reference value) { |
|
|
|
difference_type pos_i = pos - begin(); |
|
|
|
resize(_size + 1); |
|
|
|
iterator new_pos = begin() + pos_i; |
|
|
|
iterator it = end(); |
|
|
|
while (--it > pos) |
|
|
|
while (--it > new_pos) |
|
|
|
*it = *(it - 1); |
|
|
|
*it = value; |
|
|
|
return _begin; |
|
|
|
return new_pos; |
|
|
|
} |
|
|
|
iterator insert(const_iterator pos, size_type count, const_reference value) { |
|
|
|
if ((_size + count) > _capacity) |
|
|
|
resize(_size + count); |
|
|
|
|
|
|
|
iterator insert(iterator pos, size_type count, const_reference value) { |
|
|
|
if (count == 0) |
|
|
|
return pos; |
|
|
|
iterator new_pos = begin(); |
|
|
|
resize(_size + count); |
|
|
|
new_pos = begin() + (pos - new_pos); |
|
|
|
iterator it = end(); |
|
|
|
while (--it >= (pos + count)) |
|
|
|
while (--it >= (new_pos + count)) |
|
|
|
*it = *(it - count); |
|
|
|
while (it >= pos) |
|
|
|
while (it >= new_pos) { |
|
|
|
*(it--) = value; |
|
|
|
return it; |
|
|
|
} |
|
|
|
return new_pos; |
|
|
|
} |
|
|
|
template < class It > iterator insert(const_iterator pos, It first, It last, |
|
|
|
|
|
|
|
template < class It > |
|
|
|
iterator |
|
|
|
insert(iterator pos, It first, It last, |
|
|
|
typename ft::enable_if< !is_integral< It >::value, bool >::type = 0) { |
|
|
|
size_type count = ft::distance(first, last) - 1; |
|
|
|
typename std::iterator_traits< It >::iterator_category cat; |
|
|
|
return range_insert(pos, first, last, cat); |
|
|
|
} |
|
|
|
|
|
|
|
template < class It > |
|
|
|
iterator range_insert(iterator pos, It first, It last, |
|
|
|
std::input_iterator_tag) { |
|
|
|
size_type count = 0; |
|
|
|
do { |
|
|
|
pos = insert(pos, *first); |
|
|
|
++pos; |
|
|
|
++count; |
|
|
|
} while (++first != last); |
|
|
|
return pos - count; |
|
|
|
} |
|
|
|
|
|
|
|
template < class It > |
|
|
|
iterator range_insert(iterator pos, It first, It last, |
|
|
|
std::forward_iterator_tag) { |
|
|
|
size_type count = ft::distance(first, last); |
|
|
|
if (count == 0) |
|
|
|
return pos; |
|
|
|
iterator new_pos = begin(); |
|
|
|
resize(_size + count); |
|
|
|
new_pos = begin() + (pos - new_pos); |
|
|
|
iterator it = end(); |
|
|
|
while (--it > (pos + count)) |
|
|
|
while (--it >= (new_pos + count)) |
|
|
|
*it = *(it - count); |
|
|
|
while (it > pos) { |
|
|
|
*(it--) = *(last--); |
|
|
|
size_type i = 0; |
|
|
|
while (i < count) { |
|
|
|
*(new_pos + i++) = *(first++); |
|
|
|
} |
|
|
|
return it; |
|
|
|
return new_pos; |
|
|
|
} |
|
|
|
|
|
|
|
iterator erase(iterator pos) { |
|
|
|
while (pos < end()) { |
|
|
|
_alloc.destroy(pos.base()); |
|
|
|
iterator ret = pos; |
|
|
|
while ((pos + 1) < end()) { |
|
|
|
*pos = *(pos + 1); |
|
|
|
pos++; |
|
|
|
} |
|
|
|
_alloc.destroy(pos.base()); |
|
|
|
_size--; |
|
|
|
return _begin; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
iterator erase(iterator first, iterator last) { |
|
|
|
while (last++ < end()) { |
|
|
|
_alloc.destroy(first.base()); |
|
|
|
*(first++) = *last; |
|
|
|
} |
|
|
|
while (first < end() && _size--) { |
|
|
|
_alloc.destroy(first.base()); |
|
|
|
*(first++) = value_type(); |
|
|
|
} |
|
|
|
return _begin; |
|
|
|
if (first == last) |
|
|
|
return last; |
|
|
|
iterator pos = first; |
|
|
|
size_type diff_size = ft::distance(first, last); |
|
|
|
while (last < end()) |
|
|
|
*pos++ = *last++; |
|
|
|
while (pos < end()) |
|
|
|
_alloc.destroy((pos++).base()); |
|
|
|
_size -= diff_size; |
|
|
|
return first; |
|
|
|
} |
|
|
|
|
|
|
|
void push_back(const_reference value) { |
|
|
|
if (_size == _capacity) |
|
|
|
resize(_size + 1); |
|
|
|
_alloc.construct(_begin + _size - 1, value); |
|
|
|
} |
|
|
|
void pop_back(void) { |
|
|
|
_alloc.destroy(_begin + _size - 1); |
|
|
|
_size--; |
|
|
|
reserve(_size + 1); |
|
|
|
_alloc.construct(_begin + _size++, value); |
|
|
|
} |
|
|
|
void pop_back(void) { _alloc.destroy(_begin + --_size); } |
|
|
|
|
|
|
|
void resize(size_type count, T value = T()) { |
|
|
|
if (count < _size) { |
|
|
|
while (count < --_size) |
|
|
|
_alloc.destroy(_begin + _size); |
|
|
|
if (count == _size) |
|
|
|
return; |
|
|
|
if (count < _size) { // 0 < 5
|
|
|
|
while (count < _size) // 0 <= 4 ; 0 <= 3; 0 <=2; 0 <=1; 0<= 0;
|
|
|
|
_alloc.destroy(_begin + --_size); // --5; --4; --3; --2; --1;
|
|
|
|
} else { |
|
|
|
if (count > _capacity) |
|
|
|
reserve(count); |
|
|
|
reserve(count); |
|
|
|
while (_size < count) |
|
|
|
_alloc.construct(_begin + _size++, value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void swap(vector &other) { |
|
|
|
vector< T > tmp(other); |
|
|
|
other = this; |
|
|
|
this = tmp; |
|
|
|
pointer ptr = other._begin; |
|
|
|
size_type size = other._size; |
|
|
|
size_type capacity = other._capacity; |
|
|
|
allocator_type alloc = other._alloc; |
|
|
|
other._begin = _begin; |
|
|
|
other._size = _size; |
|
|
|
other._capacity = _capacity; |
|
|
|
other._alloc = _alloc; |
|
|
|
_begin = ptr; |
|
|
|
_size = size; |
|
|
|
_capacity = capacity; |
|
|
|
_alloc = alloc; |
|
|
|
} |
|
|
|
|
|
|
|
void print(void) { |
|
|
|
ft::random_access_iterator< T > i = begin(); |
|
|
|
while (i < end()) { |
|
|
@ -264,4 +330,43 @@ public: |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
template < class T2, class Alloc2 > |
|
|
|
bool operator==(const vector< T2, Alloc2 > &lhs, |
|
|
|
const vector< T2, Alloc2 > &rhs) { |
|
|
|
if (lhs.size() != rhs.size()) |
|
|
|
return false; |
|
|
|
return ft::equal(lhs.begin(), lhs.end(), rhs.begin()); |
|
|
|
} |
|
|
|
template < class T2, class Alloc2 > |
|
|
|
bool operator!=(const vector< T2, Alloc2 > &lhs, |
|
|
|
const vector< T2, Alloc2 > &rhs) { |
|
|
|
return !(lhs == rhs); |
|
|
|
} |
|
|
|
template < class T2, class Alloc2 > |
|
|
|
bool operator<(const vector< T2, Alloc2 > &lhs, |
|
|
|
const vector< T2, Alloc2 > &rhs) { |
|
|
|
return ft::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), |
|
|
|
rhs.end()); |
|
|
|
} |
|
|
|
template < class T2, class Alloc2 > |
|
|
|
bool operator>(const vector< T2, Alloc2 > &lhs, |
|
|
|
const vector< T2, Alloc2 > &rhs) { |
|
|
|
return rhs < lhs; |
|
|
|
} |
|
|
|
template < class T2, class Alloc2 > |
|
|
|
bool operator<=(const vector< T2, Alloc2 > &lhs, |
|
|
|
const vector< T2, Alloc2 > &rhs) { |
|
|
|
return !(lhs > rhs); |
|
|
|
} |
|
|
|
template < class T2, class Alloc2 > |
|
|
|
bool operator>=(const vector< T2, Alloc2 > &lhs, |
|
|
|
const vector< T2, Alloc2 > &rhs) { |
|
|
|
return !(lhs < rhs); |
|
|
|
} |
|
|
|
|
|
|
|
template < class T, class Alloc > |
|
|
|
void swap(ft::vector< T, Alloc > &lhs, ft::vector< T, Alloc > &rhs) { |
|
|
|
lhs.swap(rhs); |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace ft
|
|
|
|