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.
 
 

148 lines
2.6 KiB

#pragma once
#include <gp/algorithm/move.hpp>
#include <gp/function.hpp>
#include <gp/exception.hpp>
#include <gp/iterator.hpp>
#include <gp/optional.hpp>
#include <cstddef>
#include <cstdint>
namespace gp{
template<typename T>
class buffer final{
public:
private:
pointer_iterator<T> begin_elem;
pointer_iterator<T> end_elem;
public:
using associated_iterator = pointer_iterator<T>;
constexpr buffer(T* beg_ptr, T* end_ptr)
: begin_elem{beg_ptr}
, end_elem{end_ptr}
{}
constexpr buffer(T* beg_ptr, std::size_t sz)
: begin_elem{beg_ptr}
, end_elem{beg_ptr+sz}
{}
constexpr typename pointer_iterator<T>::difference_type size() const
{
return end_elem - begin_elem;
}
constexpr associated_iterator begin() const
{
return begin_elem;
}
constexpr associated_iterator end() const
{
return end_elem;
}
constexpr T& operator[](std::size_t offset)
{
if constexpr (gp_config::has_buffer_bounds)
{
gp_config::assertion(
offset < size(),
"Buffer bounds infringed"
);
}
return *(begin_elem+offset);
}
optional<pointer_iterator<T>> at(std::size_t offset)
{
auto elem = begin()+offset;
if(!contains(elem))
{
return nullopt;
}
return elem;
}
constexpr bool contains(pointer_iterator<T> ptr)
{
return
ptr.data < end_elem.data
&& ptr.data >= begin_elem.data;
}
template<typename U>
buffer<U> cast()
{
if constexpr(sizeof(T)%sizeof(U) == 0)
{
return buffer<U>(reinterpret_cast<U*>(&*begin_elem), size()*(sizeof(T)/sizeof(U)));
}
else
{
if((size()*sizeof(T))%sizeof(U) == 0)
{
return buffer<U>(reinterpret_cast<U*>(&*begin_elem), size()*sizeof(T)/sizeof(U));
}
else if constexpr (gp_config::has_exceptions)
{
throw bad_buffer_cast<T, U>{};
}
else
{
return buffer<U>(reinterpret_cast<U*>(nullptr), 0);
}
}
}
buffer slice_start(size_t new_sz)
{
if(new_sz<=size())
{
return buffer{&*begin(), &*(begin()+new_sz)};
}
else
{
return buffer{(T*)nullptr,(size_t)0};
}
}
buffer slice_end(size_t new_sz)
{
if(new_sz<=size())
{
return buffer{&*(end()-(1+new_sz)), &*end()};
}
else
{
return buffer{(T*)nullptr,(size_t)0};
}
}
buffer trim_start(size_t rm_sz)
{
if(rm_sz<=size())
{
return buffer{begin().data + rm_sz, end().data};
}
else
{
return buffer{(T*)nullptr,(size_t)0};
}
}
buffer trim_end(size_t rm_sz)
{
if(rm_sz<=size())
{
return buffer{begin().data, end().data - rm_sz};
}
else
{
return buffer{(T*)nullptr,(size_t)0};
}
}
};
}