Add allocator to public facing api
This commit is contained in:
parent
ab52132fe1
commit
0f6866e982
101
include/rexy/allocator.hpp
Normal file
101
include/rexy/allocator.hpp
Normal 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
|
||||||
@ -20,13 +20,13 @@
|
|||||||
#define REXY_BINARY_HPP
|
#define REXY_BINARY_HPP
|
||||||
|
|
||||||
#include "binary_base.hpp"
|
#include "binary_base.hpp"
|
||||||
#include "detail/default_allocator.hpp"
|
#include "allocator.hpp"
|
||||||
|
|
||||||
namespace rexy{
|
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>>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
#include <cstring> //memcpy
|
#include <cstring> //memcpy
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include "cx/utility.hpp" //max
|
#include "cx/utility.hpp" //max
|
||||||
#include "detail/default_allocator.hpp"
|
|
||||||
#include "steal.hpp"
|
#include "steal.hpp"
|
||||||
#include "expression.hpp"
|
#include "expression.hpp"
|
||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
#include <cstring> //memcpy
|
#include <cstring> //memcpy
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include "cx/utility.hpp" //max
|
#include "cx/utility.hpp" //max
|
||||||
#include "detail/default_allocator.hpp"
|
|
||||||
#include "steal.hpp"
|
#include "steal.hpp"
|
||||||
#include "detail/string_appender.hpp"
|
#include "detail/string_appender.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -20,17 +20,17 @@
|
|||||||
#define REXY_STRING_HPP
|
#define REXY_STRING_HPP
|
||||||
|
|
||||||
#include "string_base.hpp"
|
#include "string_base.hpp"
|
||||||
#include "detail/default_allocator.hpp"
|
#include "allocator.hpp"
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
//new allocated string
|
//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<char,allocator<char>>;
|
||||||
extern template class basic_string<wchar_t,detail::default_allocator<wchar_t>>;
|
extern template class basic_string<wchar_t,allocator<wchar_t>>;
|
||||||
extern template class basic_string<char16_t,detail::default_allocator<char16_t>>;
|
extern template class basic_string<char16_t,allocator<char16_t>>;
|
||||||
extern template class basic_string<char32_t,detail::default_allocator<char32_t>>;
|
extern template class basic_string<char32_t,allocator<char32_t>>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@ namespace rexy{
|
|||||||
using iterator = pointer;
|
using iterator = pointer;
|
||||||
using const_iterator = const_pointer;
|
using const_iterator = const_pointer;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
static constexpr size_type EXTRA_SDATA_LEN = 0;
|
static constexpr size_type EXTRA_SDATA_LEN = 0;
|
||||||
|
|
||||||
struct ldata{
|
struct ldata{
|
||||||
@ -80,70 +80,71 @@ namespace rexy{
|
|||||||
}m__data;
|
}m__data;
|
||||||
pointer m_raw = m__data.s.data;
|
pointer m_raw = m__data.s.data;
|
||||||
|
|
||||||
constexpr void set_islong_flag(bool b){
|
protected:
|
||||||
if(b)
|
constexpr void set_islong_flag(bool b){
|
||||||
m__data.l.islong = b;
|
if(b)
|
||||||
else
|
m__data.l.islong = b;
|
||||||
m__data.s.islong = b;
|
else
|
||||||
}
|
m__data.s.islong = b;
|
||||||
constexpr bool islong(void)const{
|
}
|
||||||
//common standard layout union member subsequence, never undefined behavior
|
constexpr bool islong(void)const{
|
||||||
return m__data.l.islong;
|
//common standard layout union member subsequence, never undefined behavior
|
||||||
}
|
return m__data.l.islong;
|
||||||
constexpr pointer set_short_ptr(void){
|
}
|
||||||
set_islong_flag(false);
|
constexpr pointer set_short_ptr(void){
|
||||||
return m_raw = m__data.s.data;
|
set_islong_flag(false);
|
||||||
}
|
return m_raw = m__data.s.data;
|
||||||
constexpr pointer set_long_ptr(pointer ptr){
|
}
|
||||||
set_islong_flag(true);
|
constexpr pointer set_long_ptr(pointer ptr){
|
||||||
return m_raw = ptr;
|
set_islong_flag(true);
|
||||||
}
|
return m_raw = ptr;
|
||||||
constexpr pointer get_long_ptr(void){
|
}
|
||||||
return m_raw;
|
constexpr pointer get_long_ptr(void){
|
||||||
}
|
return m_raw;
|
||||||
constexpr pointer get_short_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_long_ptr(void)const{
|
||||||
}
|
return m_raw;
|
||||||
constexpr const_pointer get_short_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 pointer get_pointer(void){
|
||||||
}
|
return m_raw;
|
||||||
constexpr const_pointer get_pointer(void)const{
|
}
|
||||||
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 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 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 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 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_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{
|
constexpr void set_short_capacity(size_type){}
|
||||||
return m__data.l.capacity;
|
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 size_type get_short_capacity(void)const{
|
||||||
}
|
return MAX_SHORT_LEN;
|
||||||
constexpr void set_length(size_type s){
|
}
|
||||||
if(islong())
|
constexpr void set_length(size_type s){
|
||||||
set_long_length(s);
|
if(islong())
|
||||||
else
|
set_long_length(s);
|
||||||
set_short_length(s);
|
else
|
||||||
}
|
set_short_length(s);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
constexpr string_base(void)noexcept = default;
|
constexpr string_base(void)noexcept = default;
|
||||||
@ -214,6 +215,9 @@ namespace rexy{
|
|||||||
|
|
||||||
constexpr reference operator[](size_type i)noexcept{return get_pointer()[i];}
|
constexpr reference operator[](size_type i)noexcept{return get_pointer()[i];}
|
||||||
constexpr const_reference operator[](size_type i)const 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;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -17,10 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rexy/binary.hpp"
|
#include "rexy/binary.hpp"
|
||||||
#include "rexy/detail/default_allocator.hpp"
|
#include "rexy/allocator.hpp"
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
template class basic_binary<detail::default_allocator<char>>;
|
template class basic_binary<allocator<char>>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
#include "rexy/traits.hpp"
|
#include "rexy/traits.hpp"
|
||||||
|
|
||||||
#include "rexy/detail/binary_string_conv.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/detail/string_appender.hpp"
|
||||||
|
|
||||||
#include "rexy/cx/algorithm.hpp"
|
#include "rexy/cx/algorithm.hpp"
|
||||||
|
|||||||
@ -17,13 +17,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rexy/string.hpp"
|
#include "rexy/string.hpp"
|
||||||
#include "rexy/detail/default_allocator.hpp"
|
#include "rexy/allocator.hpp"
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
template class basic_string<char,detail::default_allocator<char>>;
|
template class basic_string<char,allocator<char>>;
|
||||||
template class basic_string<wchar_t,detail::default_allocator<wchar_t>>;
|
template class basic_string<wchar_t,allocator<wchar_t>>;
|
||||||
template class basic_string<char16_t,detail::default_allocator<char16_t>>;
|
template class basic_string<char16_t,allocator<char16_t>>;
|
||||||
template class basic_string<char32_t,detail::default_allocator<char32_t>>;
|
template class basic_string<char32_t,allocator<char32_t>>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user