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 #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>>;
} }

View File

@ -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"

View File

@ -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"

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 #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>>;
} }

View File

@ -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;}
}; };

View File

@ -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>>;
} }

View File

@ -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"

View File

@ -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>>;
} }