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