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.
 
 

205 lines
3.9 KiB

#pragma once
#include <cstddef>
#include <cstdint>
#include <gp/optional.hpp>
#include <gp/iterator.hpp>
#include <gp/function.hpp>
#include <gp/exception.hpp>
#include <gp/algorithm/move.hpp>
namespace gp{
template<typename T>
class buffer final{
public:
struct buffer_iterator final
{
T* data;
typedef T value_type;
typedef std::size_t difference_type;
static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator;
constexpr buffer_iterator(const buffer_iterator& oth)
: data{oth.data}
{}
constexpr buffer_iterator(T* ptr)
: data{ptr}
{}
constexpr operator T&()
{
return *data;
}
constexpr T& operator*(){
return *data;
}
constexpr buffer_iterator operator++()
{
return buffer_iterator{++data};
}
constexpr buffer_iterator operator++(int)
{
return buffer_iterator{data++};
}
constexpr buffer_iterator operator--()
{
return buffer_iterator{--data};
}
constexpr buffer_iterator operator--(int)
{
return buffer_iterator{data--};
}
constexpr buffer_iterator operator+(const std::size_t offset)
{
return buffer_iterator{data+offset};
}
constexpr buffer_iterator operator+(const int offset)
{
return buffer_iterator{data+offset};
}
constexpr buffer_iterator operator-(const std::size_t offset)
{
return buffer_iterator{data-offset};
}
constexpr buffer_iterator operator-(const int offset)
{
return buffer_iterator{data-offset};
}
constexpr difference_type operator-(const buffer_iterator& oth) const
{
return (T*)data-(T*)oth.data;
}
constexpr bool operator==(const buffer_iterator& oth)
{
return data==oth.data;
}
constexpr bool operator!=(buffer_iterator& oth)
{
return data!=oth.data;
}
constexpr bool before_or_equal(const buffer_iterator& oth)
{
return reinterpret_cast<std::intptr_t>(data) <= reinterpret_cast<std::intptr_t>(oth.data);
}
constexpr bool operator<=(const buffer_iterator& oth)
{
return before_or_equal(oth);
}
};
private:
buffer_iterator begin_elem;
buffer_iterator end_elem;
public:
using associated_iterator = buffer_iterator;
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 buffer_iterator::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)
{
return *(begin_elem+offset);
}
optional<buffer_iterator> at(std::size_t offset)
{
auto elem = begin()+offset;
if(!contains(elem))
{
return nullopt;
}
return elem;
}
constexpr bool contains(buffer_iterator 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))
{
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};
}
}
};
}