#pragma once #include #include #include #include #include #include #include namespace gp{ template class buffer final{ public: private: pointer_iterator begin_elem; pointer_iterator end_elem; static constexpr size_t local_strlen(const char* str) { auto ptr = str; do{}while(*(ptr++)); return ptr-str-1; } public: using associated_iterator = pointer_iterator; constexpr buffer(const char* val) requires std::is_same_v : begin_elem{const_cast(val)} , end_elem{const_cast(val)+local_strlen(val)} {} constexpr buffer(T* beg_ptr, T* end_ptr) : begin_elem{beg_ptr} , end_elem{end_ptr} {} constexpr buffer(associated_iterator beg_ptr, associated_iterator 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 size_t 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); } constexpr const T& operator[](std::size_t offset) const { if constexpr (gp_config::has_buffer_bounds) { gp_config::assertion( offset < size(), "Buffer bounds infringed" ); } return *(begin_elem+offset); } optional> at(std::size_t offset) { auto elem = begin()+offset; if(!contains(elem)) { return nullopt; } return elem; } constexpr bool contains(pointer_iterator ptr) { return ptr.data < end_elem.data && ptr.data >= begin_elem.data; } template buffer cast() { if constexpr(sizeof(T)%sizeof(U) == 0) { return buffer(reinterpret_cast(&*begin_elem), size()*(sizeof(T)/sizeof(U))); } else { if((size()*sizeof(T))%sizeof(U) == 0) { return buffer(reinterpret_cast(&*begin_elem), size()*sizeof(T)/sizeof(U)); } else if constexpr (gp_config::has_exceptions) { throw bad_buffer_cast{}; } else { return buffer(reinterpret_cast(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()-(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}; } } }; }