diff --git a/include/rexy/allocator.hpp b/include/rexy/allocator.hpp new file mode 100644 index 0000000..4196519 --- /dev/null +++ b/include/rexy/allocator.hpp @@ -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 . +*/ + +#ifndef REXY_DEFAULT_ALLOCATOR_HPP +#define REXY_DEFAULT_ALLOCATOR_HPP + +#include //size_t +#include //true_type, false_type +#include +#include //numeric_limits + +namespace rexy{ + + template + 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 + struct rebind{ + using other = allocator; + }; + + 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 + constexpr allocator(const allocator&)noexcept{} + ~allocator(void) = default; + + pointer allocate(size_type n){ + size_type bytes = has_overflow(n) ? std::numeric_limits::max() : n*sizeof(T); + if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){ + return reinterpret_cast(::operator new(bytes)); + }else{ + return reinterpret_cast(::operator new(bytes, static_cast(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(alignof(T))); + } +#else + size_type bytes = has_overflow(n) ? std::numeric_limits::max() : n*sizeof(T); + if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){ + ::operator delete(p, bytes); + }else{ + ::operator delete(p, bytes, static_cast(alignof(T))); + } +#endif + } + constexpr size_type max_size(void)const{ + return std::numeric_limits::max()/sizeof(T); + } + }; + template + constexpr bool operator==(const allocator&, const allocator&){ + return true; + } + template + constexpr bool operator!=(const allocator&, const allocator&){ + return false; + } +} + +#endif diff --git a/include/rexy/binary.hpp b/include/rexy/binary.hpp index a7b4310..07949df 100644 --- a/include/rexy/binary.hpp +++ b/include/rexy/binary.hpp @@ -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>; + using binary = basic_binary>; - extern template class basic_binary>; + extern template class basic_binary>; } diff --git a/include/rexy/binary_base.hpp b/include/rexy/binary_base.hpp index 669462f..e580f64 100644 --- a/include/rexy/binary_base.hpp +++ b/include/rexy/binary_base.hpp @@ -24,7 +24,6 @@ #include //memcpy #include #include "cx/utility.hpp" //max -#include "detail/default_allocator.hpp" #include "steal.hpp" #include "expression.hpp" #include "traits.hpp" diff --git a/include/rexy/binary_base.tpp b/include/rexy/binary_base.tpp index 3b71ce4..d36e860 100644 --- a/include/rexy/binary_base.tpp +++ b/include/rexy/binary_base.tpp @@ -24,7 +24,6 @@ #include //memcpy #include #include "cx/utility.hpp" //max -#include "detail/default_allocator.hpp" #include "steal.hpp" #include "detail/string_appender.hpp" diff --git a/include/rexy/detail/default_allocator.hpp b/include/rexy/detail/default_allocator.hpp deleted file mode 100644 index 08470ba..0000000 --- a/include/rexy/detail/default_allocator.hpp +++ /dev/null @@ -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 . -*/ - -#ifndef REXY_DEFAULT_ALLOCATOR_HPP -#define REXY_DEFAULT_ALLOCATOR_HPP - -#include //size_t -#include //true_type, false_type -#include -#include //numeric_limits - -namespace rexy{ - - namespace detail{ - - template - 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 - struct rebind{ - using other = default_allocator; - }; - - 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 - constexpr default_allocator(const default_allocator&)noexcept{} - ~default_allocator(void) = default; - - pointer allocate(size_type n){ - size_type bytes = has_overflow(n) ? std::numeric_limits::max() : n*sizeof(T); - if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){ - return reinterpret_cast(::operator new(bytes)); - }else{ - return reinterpret_cast(::operator new(bytes, static_cast(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(alignof(T))); - } -#else - size_type bytes = has_overflow(n) ? std::numeric_limits::max() : n*sizeof(T); - if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){ - ::operator delete(p, bytes); - }else{ - ::operator delete(p, bytes, static_cast(alignof(T))); - } -#endif - } - constexpr size_type max_size(void)const{ - return std::numeric_limits::max()/sizeof(T); - } - }; - template - constexpr bool operator==(const default_allocator&, const default_allocator&){ - return true; - } - template - constexpr bool operator!=(const default_allocator&, const default_allocator&){ - return false; - } - } -} - -#endif diff --git a/include/rexy/string.hpp b/include/rexy/string.hpp index 572e94e..1760b4e 100644 --- a/include/rexy/string.hpp +++ b/include/rexy/string.hpp @@ -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>; + using string = basic_string>; - extern template class basic_string>; - extern template class basic_string>; - extern template class basic_string>; - extern template class basic_string>; + extern template class basic_string>; + extern template class basic_string>; + extern template class basic_string>; + extern template class basic_string>; } diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index f7cd07c..0343edd 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -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(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(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;} }; diff --git a/src/binary.cpp b/src/binary.cpp index c7da6d6..eafd5fd 100644 --- a/src/binary.cpp +++ b/src/binary.cpp @@ -17,10 +17,10 @@ */ #include "rexy/binary.hpp" -#include "rexy/detail/default_allocator.hpp" +#include "rexy/allocator.hpp" namespace rexy{ - template class basic_binary>; + template class basic_binary>; } diff --git a/src/ensure.cpp b/src/ensure.cpp index 7204ec3..fb21de5 100644 --- a/src/ensure.cpp +++ b/src/ensure.cpp @@ -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" diff --git a/src/string.cpp b/src/string.cpp index 8a3f0e9..62fb6bb 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -17,13 +17,13 @@ */ #include "rexy/string.hpp" -#include "rexy/detail/default_allocator.hpp" +#include "rexy/allocator.hpp" namespace rexy{ - template class basic_string>; - template class basic_string>; - template class basic_string>; - template class basic_string>; + template class basic_string>; + template class basic_string>; + template class basic_string>; + template class basic_string>; }