General Purpose library for Freestanding C++ and POSIX systems
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.
 
 

224 lines
4.7 KiB

#pragma once
#include "gp/containers/array.hpp"
namespace gp {
template<typename T, size_t cap>
class dynarray {
struct build_order{};
struct v_element{
char data[sizeof(T)];
operator T&() {
return *(T*)data;
}
v_element()
: data{}
{}
template<typename ...Args>
v_element(build_order, Args&&... argv) {
new(data) T(gp::forward<Args>(argv)...);
}
template<typename arg>
T& operator=(arg& argv) {
return *(T*)data = argv;
}
template<typename arg>
T& operator=(arg&& argv) {
return *(T*)data = gp::forward<arg>(argv);
}
template<typename ...Args>
void build(Args&&... argv) {
new(data) T(gp::forward<Args>(argv)...);
}
T& value() {
return *(T*)data;
}
T& value() const {
return *(T*)data;
}
void clear(){
((T*)data)->~T();
}
};
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>;
v_element data[cap];
size_t sz = 0;
public:
dynarray() = default;
dynarray(dynarray& oth)
{
for(auto& ref : oth) {
push_back(ref);
}
}
dynarray(dynarray&& oth)
{
for(auto& ref : oth) {
emplace_back(gp::move(ref));
}
oth.sz = 0;
}
dynarray& operator=(const dynarray& oth) {
for(auto& self : data) {
self.clear();
}
sz = 0;
for(auto& ref : oth) {
push_back(ref);
}
return *this;
}
dynarray& operator=(dynarray&& oth) {
for(auto& self : data) {
self.clear();
}
sz = 0;
for(auto& ref : oth) {
emplace_back(gp::forward<T>(ref));
}
oth.sz = 0;
return *this;
}
constexpr associated_iterator begin()
{
return associated_iterator((T*)&data[0]);
}
constexpr associated_iterator end()
{
return associated_iterator((T*)&data[sz]);
}
constexpr const associated_iterator begin() const
{
return associated_iterator((T*)&data[0]);
}
constexpr const associated_iterator end() const
{
return associated_iterator((T*)&data[sz]);
}
constexpr associated_const_iterator cbegin() const
{
return associated_const_iterator((T*)&data[0]);
}
constexpr associated_const_iterator cend() const
{
return associated_const_iterator((T*)&data[sz]);
}
constexpr associated_riterator rbegin()
{
return associated_riterator((T*)&data[sz-1]);
}
constexpr associated_riterator rend()
{
return associated_riterator((T*)data-1);
}
constexpr associated_const_riterator crbegin() const
{
return associated_const_riterator((T*)&data[sz-1]);
}
constexpr associated_const_riterator crend() const
{
return associated_const_riterator((T*)data-1);
}
constexpr bool operator==(const dynarray& oth) const
{
if(size() != oth.size()) return false;
for(size_t idx = 0; idx<sz; idx++)
{
if(data[idx].value() != oth.data[idx].value())
{
return false;
}
}
return true;
}
constexpr bool operator!=(const dynarray& oth) const
{
return !(*this == oth);
}
size_t size() const {
return sz;
}
constexpr size_t capacity() const {
return cap;
}
T& operator[] (size_t idx) {
return data[idx];
}
const T& operator[] (size_t idx) const {
return data[idx];
}
void push_back(T& value) {
data[sz].build(value);
++sz;
}
void push_back(T&& value) {
data[sz].build(value);
++sz;
}
template<typename ...Args>
void emplace_back(Args&&... argv) {
data[sz].build(gp::forward<Args>(argv)...);
++sz;
}
void remove_back() {
--sz;
data[sz].clear();
}
gp::buffer<T> as_buffer()
{
return gp::buffer<T>{(T*)data, (T*)data+sz};
}
~dynarray() {
auto it = data;
auto end = data + size();
while(it != end) {
(*it).clear();
++it;
}
}
};
}