/**
This file is a part of rexy's general purpose library
Copyright (C) 2021 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef REXY_BUFFER_TPP
#define REXY_BUFFER_TPP
#include //exchange, swap
#include //max
namespace rexy{
template
constexpr buffer::buffer(void){}
template
REXY_CPP20_CONSTEXPR buffer::buffer(const_pointer data, size_type length)noexcept(noexcept(this->allocate(0))):
m_data(this->allocate(sizeof(value_type) * length)),
m_cap(length),
m_size(length)
{
for(size_type i = 0;i < length;++i){
new (m_data + i) T(data[i]);
}
}
template
template
REXY_CPP20_CONSTEXPR buffer::buffer(const Iter& start, const Iter& last){
size_type count = 0;
for(auto it = start;it != end;++it){
++count;
}
m_data = this->allocate(sizeof(value_type) * count);
m_cap = count;
count = 0;
for(auto it = start;it != end;++it){
new (m_data + count) T(*it);
++count;
}
m_size = count;
}
template
REXY_CPP20_CONSTEXPR buffer::buffer(size_type cap)noexcept(noexcept(this->allocate(0))):
m_data(this->allocate(sizeof(value_type) * cap)),
m_cap(cap),
m_size(0){}
template
REXY_CPP20_CONSTEXPR buffer::buffer(const buffer& b)noexcept(noexcept(this->allocate(0))):
m_data(this->allocate(sizeof(value_type) * b.m_cap)),
m_cap(b.m_cap),
m_size(b.m_size)
{
for(size_type i = 0;i < b.m_size;++i){
new (m_data + i) T(b.m_data[i]);
}
}
template
constexpr buffer::buffer(buffer&& b)noexcept:
m_data(std::exchange(b.m_data, nullptr)),
m_cap(b.m_cap),
m_size(b.m_size){}
template
REXY_CPP20_CONSTEXPR buffer::~buffer(void)noexcept(noexcept(this->deallocate(nullptr, 0))){
for(size_type i = 0;i < m_size;++i){
m_data[i].~T();
}
this->deallocate(m_data, m_cap * sizeof(value_type));
}
template
REXY_CPP20_CONSTEXPR buffer& buffer::operator=(const buffer& b)
noexcept(noexcept(this->allocate(0)) &&
noexcept(this->deallocate(nullptr, 0)))
{
return (*this = buffer(b));
}
template
constexpr buffer& buffer::operator=(buffer&& b)noexcept{
std::swap(m_data, b.m_data);
std::swap(m_size, b.m_size);
std::swap(m_cap, b.m_cap);
return *this;
}
template
constexpr auto buffer::data(void) -> pointer{
return m_data;
}
template
constexpr auto buffer::data(void)const -> const_pointer{
return m_data;
}
template
REXY_CPP20_CONSTEXPR void buffer::resize(size_type new_cap){
if(new_cap > m_cap){
buffer tmp(new_cap);
for(size_type i = 0;i < m_size;++i){
new (tmp.m_data + i) T(std::move(m_data[i]));
}
std::swap(tmp.m_data, m_data);
}
m_cap = new_cap;
}
template
constexpr void buffer::set_size(size_type size){
m_size = size;
}
template
constexpr auto buffer::cap(void)const -> size_type{
return m_cap;
}
template
constexpr auto buffer::size(void)const -> const size_type&{
return m_size;
}
template
constexpr auto buffer::size(void) -> size_type&{
return m_size;
}
template
constexpr auto buffer::release(void) -> pointer{
return std::exchange(m_data, nullptr);
}
template
constexpr auto buffer::operator[](size_type i) -> reference{
return m_data[i];
}
template
constexpr auto buffer::operator[](size_type i)const -> const_reference{
return m_data[i];
}
template
constexpr auto buffer::at(size_type i) -> reference{
return m_data[i];
}
template
constexpr auto buffer::at(size_type i)const -> const_reference{
return m_data[i];
}
template
constexpr auto buffer::begin(void) -> iterator{
return m_data;
}
template
constexpr auto buffer::begin(void)const -> const_iterator{
return m_data;
}
template
constexpr auto buffer::cbegin(void)const -> const_iterator{
return m_data;
}
template
constexpr auto buffer::end(void) -> iterator{
return m_data + m_size;
}
template
constexpr auto buffer::end(void)const -> const_iterator{
return m_data + m_size;
}
template
constexpr auto buffer::cend(void)const -> const_iterator{
return m_data + m_size;
}
template
constexpr auto buffer::rbegin(void) -> reverse_iterator{
return reverse_iterator(m_data + m_size);
}
template
constexpr auto buffer::rbegin(void)const -> const_reverse_iterator{
return const_reverse_iterator(m_data + m_size);
}
template
constexpr auto buffer::rend(void) -> reverse_iterator{
return reverse_iterator(m_data - 1);
}
template
constexpr auto buffer::rend(void)const -> const_reverse_iterator{
return const_reverse_iterator(m_data - 1);
}
template
constexpr auto buffer::crbegin(void)const -> const_reverse_iterator{
return const_reverse_iterator(m_data + m_size);
}
template
constexpr auto buffer::crend(void)const -> const_reverse_iterator{
return const_reverse_iterator(m_data - 1);
}
template
REXY_CPP20_CONSTEXPR void buffer::append(const_pointer p, size_type len){
if(len + m_size > m_cap){
resize(std::max(m_cap * 2, len + m_size));
}
for(size_type i = 0;i < len;++i){
new (m_data + (m_size + i)) T(p[i]);
}
m_size += len;
}
}
#endif