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 2 : 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 2 : }
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 2 : 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
|