Add allocator to public facing api

This commit is contained in:
rexy712 2020-08-04 10:36:11 -07:00
parent ab52132fe1
commit 0f6866e982
10 changed files with 187 additions and 188 deletions

101
include/rexy/allocator.hpp Normal file
View File

@ -0,0 +1,101 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_DEFAULT_ALLOCATOR_HPP
#define REXY_DEFAULT_ALLOCATOR_HPP
#include <cstdlib> //size_t
#include <type_traits> //true_type, false_type
#include <new>
#include <limits> //numeric_limits
namespace rexy{
template<class T>
struct allocator
{
using pointer = T*;
using const_pointer = const T*;
using void_pointer = void*;
using const_void_pointer = const void*;
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using is_always_equal = std::true_type;
using propagate_on_container_copy_assignment = std::false_type;
using propagate_on_container_move_assignment = std::false_type;
using propagate_on_container_swap = std::false_type;
template<class U>
struct rebind{
using other = allocator<U>;
};
private:
constexpr bool has_overflow(size_type n)const{
return n > max_size();
}
public:
allocator(void) = default;
allocator(const allocator&) = default;
allocator(allocator&&) = default;
template<class U>
constexpr allocator(const allocator<U>&)noexcept{}
~allocator(void) = default;
pointer allocate(size_type n){
size_type bytes = has_overflow(n) ? std::numeric_limits<size_type>::max() : n*sizeof(T);
if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){
return reinterpret_cast<pointer>(::operator new(bytes));
}else{
return reinterpret_cast<pointer>(::operator new(bytes, static_cast<std::align_val_t>(alignof(T))));
}
}
void deallocate(pointer p, size_type n){
#if defined(__clang__) && !defined(__cpp_sized_deallocation)
//clang does not enable ::operator delete(void* ptr, std::size_t sz) by default for some reason
if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){
::operator delete(p);
}else{
::operator delete(p, static_cast<std::align_val_t>(alignof(T)));
}
#else
size_type bytes = has_overflow(n) ? std::numeric_limits<size_type>::max() : n*sizeof(T);
if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){
::operator delete(p, bytes);
}else{
::operator delete(p, bytes, static_cast<std::align_val_t>(alignof(T)));
}
#endif
}
constexpr size_type max_size(void)const{
return std::numeric_limits<size_type>::max()/sizeof(T);
}
};
template<class T, class U>
constexpr bool operator==(const allocator<T>&, const allocator<U>&){
return true;
}
template<class T, class U>
constexpr bool operator!=(const allocator<T>&, const allocator<U>&){
return false;
}
}
#endif

View File

@ -20,13 +20,13 @@
#define REXY_BINARY_HPP
#include "binary_base.hpp"
#include "detail/default_allocator.hpp"
#include "allocator.hpp"
namespace rexy{
using binary = basic_binary<detail::default_allocator<char>>;
using binary = basic_binary<allocator<char>>;
extern template class basic_binary<detail::default_allocator<char>>;
extern template class basic_binary<allocator<char>>;
}

View File

@ -24,7 +24,6 @@
#include <cstring> //memcpy
#include <type_traits>
#include "cx/utility.hpp" //max
#include "detail/default_allocator.hpp"
#include "steal.hpp"
#include "expression.hpp"
#include "traits.hpp"

View File

@ -24,7 +24,6 @@
#include <cstring> //memcpy
#include <type_traits>
#include "cx/utility.hpp" //max
#include "detail/default_allocator.hpp"
#include "steal.hpp"
#include "detail/string_appender.hpp"

View File

@ -1,104 +0,0 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_DEFAULT_ALLOCATOR_HPP
#define REXY_DEFAULT_ALLOCATOR_HPP
#include <cstdlib> //size_t
#include <type_traits> //true_type, false_type
#include <new>
#include <limits> //numeric_limits
namespace rexy{
namespace detail{
template<class T>
struct default_allocator
{
using pointer = T*;
using const_pointer = const T*;
using void_pointer = void*;
using const_void_pointer = const void*;
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using is_always_equal = std::true_type;
using propagate_on_container_copy_assignment = std::false_type;
using propagate_on_container_move_assignment = std::false_type;
using propagate_on_container_swap = std::false_type;
template<class U>
struct rebind{
using other = default_allocator<U>;
};
private:
constexpr bool has_overflow(size_type n)const{
return n > max_size();
}
public:
default_allocator(void) = default;
default_allocator(const default_allocator&) = default;
default_allocator(default_allocator&&) = default;
template<class U>
constexpr default_allocator(const default_allocator<U>&)noexcept{}
~default_allocator(void) = default;
pointer allocate(size_type n){
size_type bytes = has_overflow(n) ? std::numeric_limits<size_type>::max() : n*sizeof(T);
if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){
return reinterpret_cast<pointer>(::operator new(bytes));
}else{
return reinterpret_cast<pointer>(::operator new(bytes, static_cast<std::align_val_t>(alignof(T))));
}
}
void deallocate(pointer p, size_type n){
#if defined(__clang__) && !defined(__cpp_sized_deallocation)
//clang does not enable ::operator delete(void* ptr, std::size_t sz) by default for some reason
if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){
::operator delete(p);
}else{
::operator delete(p, static_cast<std::align_val_t>(alignof(T)));
}
#else
size_type bytes = has_overflow(n) ? std::numeric_limits<size_type>::max() : n*sizeof(T);
if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){
::operator delete(p, bytes);
}else{
::operator delete(p, bytes, static_cast<std::align_val_t>(alignof(T)));
}
#endif
}
constexpr size_type max_size(void)const{
return std::numeric_limits<size_type>::max()/sizeof(T);
}
};
template<class T, class U>
constexpr bool operator==(const default_allocator<T>&, const default_allocator<U>&){
return true;
}
template<class T, class U>
constexpr bool operator!=(const default_allocator<T>&, const default_allocator<U>&){
return false;
}
}
}
#endif

View File

@ -20,17 +20,17 @@
#define REXY_STRING_HPP
#include "string_base.hpp"
#include "detail/default_allocator.hpp"
#include "allocator.hpp"
namespace rexy{
//new allocated string
using string = basic_string<char,detail::default_allocator<char>>;
using string = basic_string<char,allocator<char>>;
extern template class basic_string<char,detail::default_allocator<char>>;
extern template class basic_string<wchar_t,detail::default_allocator<wchar_t>>;
extern template class basic_string<char16_t,detail::default_allocator<char16_t>>;
extern template class basic_string<char32_t,detail::default_allocator<char32_t>>;
extern template class basic_string<char,allocator<char>>;
extern template class basic_string<wchar_t,allocator<wchar_t>>;
extern template class basic_string<char16_t,allocator<char16_t>>;
extern template class basic_string<char32_t,allocator<char32_t>>;
}

View File

@ -49,7 +49,7 @@ namespace rexy{
using iterator = pointer;
using const_iterator = const_pointer;
protected:
private:
static constexpr size_type EXTRA_SDATA_LEN = 0;
struct ldata{
@ -80,70 +80,71 @@ namespace rexy{
}m__data;
pointer m_raw = m__data.s.data;
constexpr void set_islong_flag(bool b){
if(b)
m__data.l.islong = b;
else
m__data.s.islong = b;
}
constexpr bool islong(void)const{
//common standard layout union member subsequence, never undefined behavior
return m__data.l.islong;
}
constexpr pointer set_short_ptr(void){
set_islong_flag(false);
return m_raw = m__data.s.data;
}
constexpr pointer set_long_ptr(pointer ptr){
set_islong_flag(true);
return m_raw = ptr;
}
constexpr pointer get_long_ptr(void){
return m_raw;
}
constexpr pointer get_short_ptr(void){
return m_raw;
}
constexpr const_pointer get_long_ptr(void)const{
return m_raw;
}
constexpr const_pointer get_short_ptr(void)const{
return m_raw;
}
constexpr pointer get_pointer(void){
return m_raw;
}
constexpr const_pointer get_pointer(void)const{
return m_raw;
}
constexpr void set_long_length(size_type len){
m__data.l.length = len;
}
constexpr size_type get_long_length(void)const{
return m__data.l.length;
}
constexpr void set_short_length(size_type len){
m__data.s.length = static_cast<unsigned char>(len);
}
constexpr size_type get_short_length(void)const{
return m__data.s.length;
}
constexpr void set_long_capacity(size_type cap){
m__data.l.capacity = cap;
}
constexpr void set_short_capacity(size_type){}
constexpr size_type get_long_capacity(void)const{
return m__data.l.capacity;
}
constexpr size_type get_short_capacity(void)const{
return MAX_SHORT_LEN;
}
constexpr void set_length(size_type s){
if(islong())
set_long_length(s);
else
set_short_length(s);
}
protected:
constexpr void set_islong_flag(bool b){
if(b)
m__data.l.islong = b;
else
m__data.s.islong = b;
}
constexpr bool islong(void)const{
//common standard layout union member subsequence, never undefined behavior
return m__data.l.islong;
}
constexpr pointer set_short_ptr(void){
set_islong_flag(false);
return m_raw = m__data.s.data;
}
constexpr pointer set_long_ptr(pointer ptr){
set_islong_flag(true);
return m_raw = ptr;
}
constexpr pointer get_long_ptr(void){
return m_raw;
}
constexpr pointer get_short_ptr(void){
return m_raw;
}
constexpr const_pointer get_long_ptr(void)const{
return m_raw;
}
constexpr const_pointer get_short_ptr(void)const{
return m_raw;
}
constexpr pointer get_pointer(void){
return m_raw;
}
constexpr const_pointer get_pointer(void)const{
return m_raw;
}
constexpr void set_long_length(size_type len){
m__data.l.length = len;
}
constexpr size_type get_long_length(void)const{
return m__data.l.length;
}
constexpr void set_short_length(size_type len){
m__data.s.length = static_cast<unsigned char>(len);
}
constexpr size_type get_short_length(void)const{
return m__data.s.length;
}
constexpr void set_long_capacity(size_type cap){
m__data.l.capacity = cap;
}
constexpr void set_short_capacity(size_type){}
constexpr size_type get_long_capacity(void)const{
return m__data.l.capacity;
}
constexpr size_type get_short_capacity(void)const{
return MAX_SHORT_LEN;
}
constexpr void set_length(size_type s){
if(islong())
set_long_length(s);
else
set_short_length(s);
}
protected:
constexpr string_base(void)noexcept = default;
@ -214,6 +215,9 @@ namespace rexy{
constexpr reference operator[](size_type i)noexcept{return get_pointer()[i];}
constexpr const_reference operator[](size_type i)const noexcept{return get_pointer()[i];}
static constexpr bool uses_sso(void){return true;}
static constexpr size_type short_string_size(void){return MAX_SHORT_LEN;}
};

View File

@ -17,10 +17,10 @@
*/
#include "rexy/binary.hpp"
#include "rexy/detail/default_allocator.hpp"
#include "rexy/allocator.hpp"
namespace rexy{
template class basic_binary<detail::default_allocator<char>>;
template class basic_binary<allocator<char>>;
}

View File

@ -12,7 +12,7 @@
#include "rexy/traits.hpp"
#include "rexy/detail/binary_string_conv.hpp"
#include "rexy/detail/default_allocator.hpp"
#include "rexy/allocator.hpp"
#include "rexy/detail/string_appender.hpp"
#include "rexy/cx/algorithm.hpp"

View File

@ -17,13 +17,13 @@
*/
#include "rexy/string.hpp"
#include "rexy/detail/default_allocator.hpp"
#include "rexy/allocator.hpp"
namespace rexy{
template class basic_string<char,detail::default_allocator<char>>;
template class basic_string<wchar_t,detail::default_allocator<wchar_t>>;
template class basic_string<char16_t,detail::default_allocator<char16_t>>;
template class basic_string<char32_t,detail::default_allocator<char32_t>>;
template class basic_string<char,allocator<char>>;
template class basic_string<wchar_t,allocator<wchar_t>>;
template class basic_string<char16_t,allocator<char16_t>>;
template class basic_string<char32_t,allocator<char32_t>>;
}