|
|
- #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:
- 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))
- {
- 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};
- }
- }
- };
- }
|