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
|
||||
|
||||
#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>>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
#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>>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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>>;
|
||||
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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>>;
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user