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
26namespace boost {
27namespace urls {
28namespace 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
34template<class Alloc>
35using allocator_traits =
36 boost::allocator_traits<Alloc>;
37#else
38template<class Alloc>
39using allocator_traits = std::allocator_traits<Alloc>;
40#endif
41
42template<class T, class Allocator>
43class 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
51public:
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 over_allocator(
76 std::size_t extra,
77 Allocator const& alloc)
78 : empty_value<Allocator>(
79 empty_init, alloc)
80 , extra_(extra)
81 {
82 }
83
84 template<class U>
85 over_allocator(over_allocator<U, Allocator> const& other) noexcept
86 : empty_value<Allocator>(
87 empty_init, other.get())
88 , extra_(other.extra_)
89 {
90 }
91
92 pointer
93 allocate(size_type n)
94 {
95 BOOST_ASSERT(n == 1);
96 using U = typename boost::type_with_alignment<
97 alignof(value_type)>::type;
98 auto constexpr S = sizeof(U);
99 using A = typename allocator_traits<
100 Allocator>::template rebind_alloc<U>;
101 A a(this->get());
102 return reinterpret_cast<pointer>(
103 std::allocator_traits<A>::allocate(a,
104 (n * sizeof(value_type) + extra_ + S - 1) / S));
105 }
106
107 void
108 deallocate(pointer p, size_type n)
109 {
110 BOOST_ASSERT(n == 1);
111 using U = typename boost::type_with_alignment<
112 alignof(value_type)>::type;
113 auto constexpr S = sizeof(U);
114 using A = typename allocator_traits<
115 Allocator>::template rebind_alloc<U>;
116 A a{this->get()};
117 std::allocator_traits<A>::deallocate(a,
118 reinterpret_cast<U*>(p),
119 (n * sizeof(value_type) + extra_ + S - 1) / S);
120 }
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
166

source code of boost/libs/url/src/detail/over_allocator.hpp