216 lines
6.7 KiB
C++
216 lines
6.7 KiB
C++
/**
|
|
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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef REXY_BUFFER_TPP
|
|
#define REXY_BUFFER_TPP
|
|
|
|
#include <utility> //exchange, swap
|
|
#include <algorithm> //max
|
|
|
|
namespace rexy{
|
|
|
|
template<class T, class Allocator>
|
|
constexpr buffer<T,Allocator>::buffer(void){}
|
|
template<class T, class Allocator>
|
|
REXY_CPP20_CONSTEXPR buffer<T,Allocator>::buffer(const_pointer data, size_type length)noexcept(is_nothrow_allocator_v<Allocator>):
|
|
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<class T, class Allocator>
|
|
template<class Iter>
|
|
REXY_CPP20_CONSTEXPR buffer<T,Allocator>::buffer(const Iter& start, const Iter& last){
|
|
size_type count = 0;
|
|
for(auto it = start;it != last;++it){
|
|
++count;
|
|
}
|
|
m_data = this->allocate(sizeof(value_type) * count);
|
|
m_cap = count;
|
|
|
|
count = 0;
|
|
for(auto it = start;it != last;++it){
|
|
new (m_data + count) T(*it);
|
|
++count;
|
|
}
|
|
m_size = count;
|
|
}
|
|
template<class T, class Allocator>
|
|
REXY_CPP20_CONSTEXPR buffer<T,Allocator>::buffer(size_type cap)noexcept(is_nothrow_allocator_v<Allocator>):
|
|
m_data(this->allocate(sizeof(value_type) * cap)),
|
|
m_cap(cap),
|
|
m_size(0){}
|
|
template<class T, class Allocator>
|
|
REXY_CPP20_CONSTEXPR buffer<T,Allocator>::buffer(const buffer& b)noexcept(is_nothrow_allocator_v<Allocator>):
|
|
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<class T, class Allocator>
|
|
constexpr buffer<T,Allocator>::buffer(buffer&& b)noexcept:
|
|
m_data(std::exchange(b.m_data, nullptr)),
|
|
m_cap(b.m_cap),
|
|
m_size(b.m_size){}
|
|
template<class T, class Allocator>
|
|
REXY_CPP20_CONSTEXPR buffer<T,Allocator>::~buffer(void)noexcept(is_nothrow_allocator_v<Allocator>){
|
|
for(size_type i = 0;i < m_size;++i){
|
|
m_data[i].~T();
|
|
}
|
|
this->deallocate(m_data, m_cap * sizeof(value_type));
|
|
}
|
|
template<class T, class Allocator>
|
|
REXY_CPP20_CONSTEXPR buffer<T,Allocator>& buffer<T,Allocator>::operator=(const buffer& b)
|
|
noexcept(is_nothrow_allocator_v<Allocator>)
|
|
{
|
|
return (*this = buffer(b));
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr buffer<T,Allocator>& buffer<T,Allocator>::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<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::data(void) -> pointer{
|
|
return m_data;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::data(void)const -> const_pointer{
|
|
return m_data;
|
|
}
|
|
template<class T, class Allocator>
|
|
REXY_CPP20_CONSTEXPR void buffer<T,Allocator>::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<class T, class Allocator>
|
|
constexpr void buffer<T,Allocator>::set_size(size_type size){
|
|
m_size = size;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::cap(void)const -> size_type{
|
|
return m_cap;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::size(void)const -> const size_type&{
|
|
return m_size;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::size(void) -> size_type&{
|
|
return m_size;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::release(void) -> pointer{
|
|
return std::exchange(m_data, nullptr);
|
|
}
|
|
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::operator[](size_type i) -> reference{
|
|
return m_data[i];
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::operator[](size_type i)const -> const_reference{
|
|
return m_data[i];
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::at(size_type i) -> reference{
|
|
return m_data[i];
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::at(size_type i)const -> const_reference{
|
|
return m_data[i];
|
|
}
|
|
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::begin(void) -> iterator{
|
|
return m_data;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::begin(void)const -> const_iterator{
|
|
return m_data;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::cbegin(void)const -> const_iterator{
|
|
return m_data;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::end(void) -> iterator{
|
|
return m_data + m_size;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::end(void)const -> const_iterator{
|
|
return m_data + m_size;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::cend(void)const -> const_iterator{
|
|
return m_data + m_size;
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::rbegin(void) -> reverse_iterator{
|
|
return reverse_iterator(m_data + m_size);
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::rbegin(void)const -> const_reverse_iterator{
|
|
return const_reverse_iterator(m_data + m_size);
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::rend(void) -> reverse_iterator{
|
|
return reverse_iterator(m_data - 1);
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::rend(void)const -> const_reverse_iterator{
|
|
return const_reverse_iterator(m_data - 1);
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::crbegin(void)const -> const_reverse_iterator{
|
|
return const_reverse_iterator(m_data + m_size);
|
|
}
|
|
template<class T, class Allocator>
|
|
constexpr auto buffer<T,Allocator>::crend(void)const -> const_reverse_iterator{
|
|
return const_reverse_iterator(m_data - 1);
|
|
}
|
|
|
|
template<class T, class Allocator>
|
|
REXY_CPP20_CONSTEXPR void buffer<T,Allocator>::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
|