Line data Source code
1 : // 2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 3 : // 4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 : // 7 : // Official repository: https://github.com/boostorg/url 8 : // 9 : 10 : #ifndef BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP 11 : #define BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP 12 : 13 : #include <boost/config.hpp> 14 : #include <boost/core/empty_value.hpp> 15 : #include <boost/assert.hpp> 16 : #include <boost/type_traits/is_final.hpp> 17 : #include <boost/type_traits/type_with_alignment.hpp> 18 : #ifdef BOOST_NO_CXX11_ALLOCATOR 19 : # include <boost/core/allocator_traits.hpp> 20 : #endif 21 : #include <cstddef> 22 : #include <memory> 23 : #include <type_traits> 24 : #include <utility> 25 : 26 : namespace boost { 27 : namespace urls { 28 : namespace detail { 29 : 30 : // This is a workaround for allocator_traits 31 : // implementations which falsely claim C++11 32 : // compatibility. 33 : #ifdef BOOST_NO_CXX11_ALLOCATOR 34 : template<class Alloc> 35 : using allocator_traits = 36 : boost::allocator_traits<Alloc>; 37 : #else 38 : template<class Alloc> 39 : using allocator_traits = std::allocator_traits<Alloc>; 40 : #endif 41 : 42 : template<class T, class Allocator> 43 : class over_allocator 44 : : private empty_value<Allocator> 45 : { 46 : template<class U, class OtherAlloc> 47 : friend class over_allocator; 48 : 49 : std::size_t extra_; 50 : 51 : public: 52 : using is_always_equal = std::false_type; 53 : using value_type = typename 54 : allocator_traits<typename allocator_traits< 55 : Allocator>::template rebind_alloc<T>>::value_type; 56 : using pointer = typename 57 : allocator_traits<typename allocator_traits< 58 : Allocator>::template rebind_alloc<T>>::pointer; 59 : using const_pointer = typename 60 : allocator_traits<typename allocator_traits< 61 : Allocator>::template rebind_alloc<T>>::const_pointer; 62 : using size_type = typename 63 : allocator_traits<typename allocator_traits< 64 : Allocator>::template rebind_alloc<T>>::size_type; 65 : using difference_type = typename 66 : allocator_traits<typename allocator_traits< 67 : Allocator>::template rebind_alloc<T>>::difference_type; 68 : 69 : template<class U> 70 : struct rebind 71 : { 72 : using other = over_allocator<U, Allocator>; 73 : }; 74 : 75 2 : over_allocator( 76 : std::size_t extra, 77 : Allocator const& alloc) 78 : : empty_value<Allocator>( 79 : empty_init, alloc) 80 2 : , extra_(extra) 81 : { 82 2 : } 83 : 84 : template<class U> 85 4 : over_allocator(over_allocator<U, Allocator> const& other) noexcept 86 : : empty_value<Allocator>( 87 : empty_init, other.get()) 88 4 : , extra_(other.extra_) 89 : { 90 4 : } 91 : 92 : pointer 93 2 : allocate(size_type n) 94 : { 95 2 : BOOST_ASSERT(n == 1); 96 : using U = typename boost::type_with_alignment< 97 : alignof(value_type)>::type; 98 2 : auto constexpr S = sizeof(U); 99 : using A = typename allocator_traits< 100 : Allocator>::template rebind_alloc<U>; 101 4 : A a(this->get()); 102 : return reinterpret_cast<pointer>( 103 4 : std::allocator_traits<A>::allocate(a, 104 4 : (n * sizeof(value_type) + extra_ + S - 1) / S)); 105 : } 106 : 107 : void 108 2 : deallocate(pointer p, size_type n) 109 : { 110 2 : BOOST_ASSERT(n == 1); 111 : using U = typename boost::type_with_alignment< 112 : alignof(value_type)>::type; 113 2 : auto constexpr S = sizeof(U); 114 : using A = typename allocator_traits< 115 : Allocator>::template rebind_alloc<U>; 116 4 : A a{this->get()}; 117 2 : std::allocator_traits<A>::deallocate(a, 118 : reinterpret_cast<U*>(p), 119 2 : (n * sizeof(value_type) + extra_ + S - 1) / S); 120 2 : } 121 : 122 : #if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000 123 : template<class U, class... Args> 124 : void 125 : construct(U* ptr, Args&&... args) 126 : { 127 : ::new((void*)ptr) U(std::forward<Args>(args)...); 128 : } 129 : 130 : template<class U> 131 : void 132 : destroy(U* ptr) 133 : { 134 : ptr->~U(); 135 : } 136 : #endif 137 : 138 : template<class U> 139 : friend 140 : bool 141 : operator==( 142 : over_allocator const& lhs, 143 : over_allocator<U, Allocator> const& rhs) 144 : { 145 : return 146 : lhs.get() == rhs.get() && 147 : lhs.extra_ == rhs.extra_; 148 : } 149 : 150 : template<class U> 151 : friend 152 : bool 153 : operator!=( 154 : over_allocator const& lhs, 155 : over_allocator<U, Allocator> const& rhs) 156 : { 157 : return ! (lhs == rhs); 158 : } 159 : }; 160 : 161 : } // detail 162 : } // urls 163 : } // boost 164 : 165 : #endif