|
@ -0,0 +1,251 @@ |
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
#include <gp/buffer.hpp>
|
|
|
|
|
|
#include <gp/allocator/allocator.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
#include <initializer_list>
|
|
|
|
|
|
|
|
|
|
|
|
namespace gp{ |
|
|
|
|
|
template<typename T> |
|
|
|
|
|
class vector{ |
|
|
|
|
|
public: |
|
|
|
|
|
T* ary; |
|
|
|
|
|
size_t sz; |
|
|
|
|
|
size_t cap; |
|
|
|
|
|
gp::reference_wrapper<allocator> alloc; |
|
|
|
|
|
using associated_iterator = pointer_iterator<T, 1>; |
|
|
|
|
|
using associated_const_iterator = const_pointer_iterator<T, 1>; |
|
|
|
|
|
using associated_riterator = pointer_iterator<T, -1>; |
|
|
|
|
|
using associated_const_riterator = const_pointer_iterator<T, -1>; |
|
|
|
|
|
|
|
|
|
|
|
vector(allocator& v) |
|
|
|
|
|
: ary() |
|
|
|
|
|
, alloc(v) |
|
|
|
|
|
{} |
|
|
|
|
|
|
|
|
|
|
|
vector(const vector& oth) |
|
|
|
|
|
{ |
|
|
|
|
|
sz = 0; |
|
|
|
|
|
cap = 0; |
|
|
|
|
|
ary = nullptr; |
|
|
|
|
|
alloc = oth.alloc; |
|
|
|
|
|
gp_config::assertion(reserve(oth.size()), "could not reserve space on building"); |
|
|
|
|
|
sz = oth.size(); |
|
|
|
|
|
cap = oth.size(); |
|
|
|
|
|
auto it_l = begin(); |
|
|
|
|
|
auto it_o = oth.cbegin(); |
|
|
|
|
|
for(size_t i = 0; i < sz; ++i) |
|
|
|
|
|
{ |
|
|
|
|
|
new(&*(it_l++)) T(*(it_o++)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
vector(vector&& oth) |
|
|
|
|
|
: ary(oth.ary) |
|
|
|
|
|
, sz(oth.sz) |
|
|
|
|
|
, cap(oth.cap) |
|
|
|
|
|
, alloc(oth.alloc) |
|
|
|
|
|
{ |
|
|
|
|
|
oth.ary = nullptr; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* TODO: Build the templated equivalents
|
|
|
|
|
|
array(T (& oth)[sz]) { |
|
|
|
|
|
gp::move_uninitialized<T>( |
|
|
|
|
|
gp::nameless_range<int*>(oth, oth+sz), |
|
|
|
|
|
gp::nameless_range<associated_iterator>(begin(), end()) |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
array(T (&& oth)[sz]) { |
|
|
|
|
|
gp::move_uninitialized( |
|
|
|
|
|
gp::nameless_range<int*>((T*)oth, (T*)oth+sz), |
|
|
|
|
|
gp::nameless_range<associated_iterator>(begin(), end()) |
|
|
|
|
|
); |
|
|
|
|
|
}*/ |
|
|
|
|
|
|
|
|
|
|
|
vector& operator=(vector& oth) |
|
|
|
|
|
{ |
|
|
|
|
|
gp_config::assertion(reserve(oth.size()), "could not reserve space on assign"); |
|
|
|
|
|
for(size_t i = 0; i < gp::min(sz, oth.sz); ++i) |
|
|
|
|
|
{ |
|
|
|
|
|
ary[i]=oth[i]; |
|
|
|
|
|
} |
|
|
|
|
|
if(sz < oth.sz) { |
|
|
|
|
|
for(size_t i = sz; i < oth.sz; ++i) { |
|
|
|
|
|
new(ary+i) T(oth[i]); |
|
|
|
|
|
} |
|
|
|
|
|
} else if(sz > oth.sz) { |
|
|
|
|
|
for(size_t i = oth.sz; i < sz; ++i) { |
|
|
|
|
|
ary[i]->~T(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
sz = oth.sz; |
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
vector& operator=(vector&& oth) |
|
|
|
|
|
{ |
|
|
|
|
|
gp::swap(ary, oth.ary); |
|
|
|
|
|
gp::swap(alloc, oth.alloc); |
|
|
|
|
|
gp::swap(sz, oth.sz); |
|
|
|
|
|
gp::swap(cap, oth.cap); |
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr T& operator[] (size_t off) |
|
|
|
|
|
{ |
|
|
|
|
|
if constexpr (gp_config::has_buffer_bounds) |
|
|
|
|
|
{ |
|
|
|
|
|
gp_config::assertion( |
|
|
|
|
|
off < sz, |
|
|
|
|
|
"Array bounds infringed" |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
return ary[off]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
~vector() |
|
|
|
|
|
{ |
|
|
|
|
|
if(ary) |
|
|
|
|
|
{ |
|
|
|
|
|
for(auto& elem : *this) { |
|
|
|
|
|
elem->~T(); |
|
|
|
|
|
} |
|
|
|
|
|
gp_config::assertion(alloc.get().deallocate(ary), "could not deallocate"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool grow() { |
|
|
|
|
|
if(sz == cap) return reserve(sz + (sz >> 1)); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool reserve(size_t new_cap) { |
|
|
|
|
|
if(new_cap <= cap) return true; |
|
|
|
|
|
|
|
|
|
|
|
size_t new_data_size = new_cap*sizeof(T); |
|
|
|
|
|
|
|
|
|
|
|
if(alloc.get().try_reallocate(ary, new_data_size)) return true; |
|
|
|
|
|
|
|
|
|
|
|
if(T* new_ary = alloc.get().allocate(new_data_size); new_ary) { |
|
|
|
|
|
auto new_it = new_ary; |
|
|
|
|
|
for(auto* elem : *this) { |
|
|
|
|
|
++new_it = gp::move(elem); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gp_config::assertion(alloc.get().deallocate(ary), "failed to deallocate old range"); |
|
|
|
|
|
|
|
|
|
|
|
ary = new_ary; |
|
|
|
|
|
cap = new_cap; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr const T& operator[] (size_t off) const |
|
|
|
|
|
{ |
|
|
|
|
|
return ary[off]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr size_t size() const |
|
|
|
|
|
{ |
|
|
|
|
|
return sz; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr size_t capacity() const |
|
|
|
|
|
{ |
|
|
|
|
|
return cap; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr bool push_back(T& value) { |
|
|
|
|
|
if(grow()) { |
|
|
|
|
|
new(ary+sz) T(value); |
|
|
|
|
|
sz++; |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr bool push_back(T&& value) { |
|
|
|
|
|
if(grow()) { |
|
|
|
|
|
new(ary+sz) T(gp::move(value)); |
|
|
|
|
|
sz++; |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr gp::optional<T> pop_back() { |
|
|
|
|
|
if(sz == 0) return gp::nullopt; |
|
|
|
|
|
sz--; |
|
|
|
|
|
gp::optional<T> ret_val = gp::move(ary[sz]); |
|
|
|
|
|
ary[sz]->~T(); |
|
|
|
|
|
return gp::move(ret_val); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr pointer_iterator<T, 1> begin() |
|
|
|
|
|
{ |
|
|
|
|
|
return associated_iterator(&ary[0]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr pointer_iterator<T, 1> end() |
|
|
|
|
|
{ |
|
|
|
|
|
return associated_iterator(&ary[sz]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr const_pointer_iterator<T, 1> cbegin() const |
|
|
|
|
|
{ |
|
|
|
|
|
return associated_const_iterator(&ary[0]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr const_pointer_iterator<T, 1> cend() const |
|
|
|
|
|
{ |
|
|
|
|
|
return associated_const_iterator(&ary[sz]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr pointer_iterator<T, -1> rbegin() |
|
|
|
|
|
{ |
|
|
|
|
|
return associated_riterator(&ary[sz-1]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr pointer_iterator<T, -1> rend() |
|
|
|
|
|
{ |
|
|
|
|
|
return associated_riterator(ary-1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr const_pointer_iterator<T, -1> crbegin() const |
|
|
|
|
|
{ |
|
|
|
|
|
return associated_const_riterator(&ary[sz-1]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr const_pointer_iterator<T, -1> crend() const |
|
|
|
|
|
{ |
|
|
|
|
|
return associated_const_riterator(ary-1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr bool operator==(const vector& oth) const |
|
|
|
|
|
{ |
|
|
|
|
|
for(size_t idx = 0; idx<sz; idx++) |
|
|
|
|
|
{ |
|
|
|
|
|
if(ary[idx] != oth.ary[idx]) |
|
|
|
|
|
{ |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr bool operator!=(const vector& oth) const |
|
|
|
|
|
{ |
|
|
|
|
|
return !(*this == oth); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gp::buffer<T> as_buffer() |
|
|
|
|
|
{ |
|
|
|
|
|
return gp::buffer<T>{(T*)ary, (T*)ary+sz}; |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
} |