1  
 //
1  
 //
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/url
7  
// Official repository: https://github.com/boostorg/url
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP
10  
#ifndef BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP
11  
#define BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP
11  
#define BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP
12  

12  

13  
#include <boost/config.hpp>
13  
#include <boost/config.hpp>
14  
#include <boost/core/empty_value.hpp>
14  
#include <boost/core/empty_value.hpp>
15  
#include <boost/assert.hpp>
15  
#include <boost/assert.hpp>
16  
#include <boost/type_traits/is_final.hpp>
16  
#include <boost/type_traits/is_final.hpp>
17  
#include <boost/type_traits/type_with_alignment.hpp>
17  
#include <boost/type_traits/type_with_alignment.hpp>
18  
#ifdef BOOST_NO_CXX11_ALLOCATOR
18  
#ifdef BOOST_NO_CXX11_ALLOCATOR
19  
# include <boost/core/allocator_traits.hpp>
19  
# include <boost/core/allocator_traits.hpp>
20  
#endif
20  
#endif
21  
#include <cstddef>
21  
#include <cstddef>
22  
#include <memory>
22  
#include <memory>
23  
#include <type_traits>
23  
#include <type_traits>
24  
#include <utility>
24  
#include <utility>
25  

25  

26  
namespace boost {
26  
namespace boost {
27  
namespace urls {
27  
namespace urls {
28  
namespace detail {
28  
namespace detail {
29  

29  

30  
// This is a workaround for allocator_traits
30  
// This is a workaround for allocator_traits
31  
// implementations which falsely claim C++11
31  
// implementations which falsely claim C++11
32  
// compatibility.
32  
// compatibility.
33  
#ifdef BOOST_NO_CXX11_ALLOCATOR
33  
#ifdef BOOST_NO_CXX11_ALLOCATOR
34  
template<class Alloc>
34  
template<class Alloc>
35  
using allocator_traits =
35  
using allocator_traits =
36  
    boost::allocator_traits<Alloc>;
36  
    boost::allocator_traits<Alloc>;
37  
#else
37  
#else
38  
template<class Alloc>
38  
template<class Alloc>
39  
using allocator_traits = std::allocator_traits<Alloc>;
39  
using allocator_traits = std::allocator_traits<Alloc>;
40  
#endif
40  
#endif
41  

41  

42  
template<class T, class Allocator>
42  
template<class T, class Allocator>
43  
class over_allocator
43  
class over_allocator
44  
    : private empty_value<Allocator>
44  
    : private empty_value<Allocator>
45  
{
45  
{
46  
    template<class U, class OtherAlloc>
46  
    template<class U, class OtherAlloc>
47  
    friend class over_allocator;
47  
    friend class over_allocator;
48  

48  

49  
    std::size_t extra_;
49  
    std::size_t extra_;
50  

50  

51  
public:
51  
public:
52  
    using is_always_equal = std::false_type;
52  
    using is_always_equal = std::false_type;
53  
    using value_type = typename
53  
    using value_type = typename
54  
        allocator_traits<typename allocator_traits<
54  
        allocator_traits<typename allocator_traits<
55  
            Allocator>::template rebind_alloc<T>>::value_type;
55  
            Allocator>::template rebind_alloc<T>>::value_type;
56  
    using pointer = typename
56  
    using pointer = typename
57  
        allocator_traits<typename allocator_traits<
57  
        allocator_traits<typename allocator_traits<
58  
            Allocator>::template rebind_alloc<T>>::pointer;
58  
            Allocator>::template rebind_alloc<T>>::pointer;
59  
    using const_pointer = typename
59  
    using const_pointer = typename
60  
        allocator_traits<typename allocator_traits<
60  
        allocator_traits<typename allocator_traits<
61  
            Allocator>::template rebind_alloc<T>>::const_pointer;
61  
            Allocator>::template rebind_alloc<T>>::const_pointer;
62  
    using size_type = typename
62  
    using size_type = typename
63  
        allocator_traits<typename allocator_traits<
63  
        allocator_traits<typename allocator_traits<
64  
            Allocator>::template rebind_alloc<T>>::size_type;
64  
            Allocator>::template rebind_alloc<T>>::size_type;
65  
    using difference_type = typename
65  
    using difference_type = typename
66  
        allocator_traits<typename allocator_traits<
66  
        allocator_traits<typename allocator_traits<
67  
            Allocator>::template rebind_alloc<T>>::difference_type;
67  
            Allocator>::template rebind_alloc<T>>::difference_type;
68  

68  

69  
    template<class U>
69  
    template<class U>
70  
    struct rebind
70  
    struct rebind
71  
    {
71  
    {
72  
        using other = over_allocator<U, Allocator>;
72  
        using other = over_allocator<U, Allocator>;
73  
    };
73  
    };
74  

74  

75  
    over_allocator(
75  
    over_allocator(
76  
        std::size_t extra,
76  
        std::size_t extra,
77  
        Allocator const& alloc)
77  
        Allocator const& alloc)
78  
        : empty_value<Allocator>(
78  
        : empty_value<Allocator>(
79  
            empty_init, alloc)
79  
            empty_init, alloc)
80  
        , extra_(extra)
80  
        , extra_(extra)
81  
    {
81  
    {
82  
    }
82  
    }
83  

83  

84  
    template<class U>
84  
    template<class U>
85  
    over_allocator(over_allocator<U, Allocator> const& other) noexcept
85  
    over_allocator(over_allocator<U, Allocator> const& other) noexcept
86  
        : empty_value<Allocator>(
86  
        : empty_value<Allocator>(
87  
            empty_init, other.get())
87  
            empty_init, other.get())
88  
        , extra_(other.extra_)
88  
        , extra_(other.extra_)
89  
    {
89  
    {
90  
    }
90  
    }
91  

91  

92  
    pointer
92  
    pointer
93  
    allocate(size_type n)
93  
    allocate(size_type n)
94  
    {
94  
    {
95  
        BOOST_ASSERT(n == 1);
95  
        BOOST_ASSERT(n == 1);
96  
        using U = typename boost::type_with_alignment<
96  
        using U = typename boost::type_with_alignment<
97  
            alignof(value_type)>::type;
97  
            alignof(value_type)>::type;
98  
        auto constexpr S = sizeof(U);
98  
        auto constexpr S = sizeof(U);
99  
        using A = typename allocator_traits<
99  
        using A = typename allocator_traits<
100  
            Allocator>::template rebind_alloc<U>;
100  
            Allocator>::template rebind_alloc<U>;
101  
        A a(this->get());
101  
        A a(this->get());
102  
        return reinterpret_cast<pointer>(
102  
        return reinterpret_cast<pointer>(
103  
            std::allocator_traits<A>::allocate(a,
103  
            std::allocator_traits<A>::allocate(a,
104  
                (n * sizeof(value_type) + extra_ + S - 1) / S));
104  
                (n * sizeof(value_type) + extra_ + S - 1) / S));
105  
    }
105  
    }
106  

106  

107  
    void
107  
    void
108  
    deallocate(pointer p, size_type n)
108  
    deallocate(pointer p, size_type n)
109  
    {
109  
    {
110  
        BOOST_ASSERT(n == 1);
110  
        BOOST_ASSERT(n == 1);
111  
        using U = typename boost::type_with_alignment<
111  
        using U = typename boost::type_with_alignment<
112  
            alignof(value_type)>::type;
112  
            alignof(value_type)>::type;
113  
        auto constexpr S = sizeof(U);
113  
        auto constexpr S = sizeof(U);
114  
        using A = typename allocator_traits<
114  
        using A = typename allocator_traits<
115  
            Allocator>::template rebind_alloc<U>;
115  
            Allocator>::template rebind_alloc<U>;
116  
        A a{this->get()};
116  
        A a{this->get()};
117  
        std::allocator_traits<A>::deallocate(a,
117  
        std::allocator_traits<A>::deallocate(a,
118  
            reinterpret_cast<U*>(p),
118  
            reinterpret_cast<U*>(p),
119  
                (n * sizeof(value_type) + extra_ + S - 1) / S);
119  
                (n * sizeof(value_type) + extra_ + S - 1) / S);
120  
    }
120  
    }
121  

121  

122  
#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
122  
#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
123  
    template<class U, class... Args>
123  
    template<class U, class... Args>
124  
    void
124  
    void
125  
    construct(U* ptr, Args&&... args)
125  
    construct(U* ptr, Args&&... args)
126  
    {
126  
    {
127  
        ::new((void*)ptr) U(std::forward<Args>(args)...);
127  
        ::new((void*)ptr) U(std::forward<Args>(args)...);
128  
    }
128  
    }
129  

129  

130  
    template<class U>
130  
    template<class U>
131  
    void
131  
    void
132  
    destroy(U* ptr)
132  
    destroy(U* ptr)
133  
    {
133  
    {
134  
        ptr->~U();
134  
        ptr->~U();
135  
    }
135  
    }
136  
#endif
136  
#endif
137  

137  

138  
    template<class U>
138  
    template<class U>
139  
    friend
139  
    friend
140  
    bool
140  
    bool
141  
    operator==(
141  
    operator==(
142  
        over_allocator const& lhs,
142  
        over_allocator const& lhs,
143  
        over_allocator<U, Allocator> const& rhs)
143  
        over_allocator<U, Allocator> const& rhs)
144  
    {
144  
    {
145  
        return
145  
        return
146  
            lhs.get() == rhs.get() &&
146  
            lhs.get() == rhs.get() &&
147  
            lhs.extra_ == rhs.extra_;
147  
            lhs.extra_ == rhs.extra_;
148  
    }
148  
    }
149  

149  

150  
    template<class U>
150  
    template<class U>
151  
    friend
151  
    friend
152  
    bool
152  
    bool
153  
    operator!=(
153  
    operator!=(
154  
        over_allocator const& lhs,
154  
        over_allocator const& lhs,
155  
        over_allocator<U, Allocator> const& rhs)
155  
        over_allocator<U, Allocator> const& rhs)
156  
    {
156  
    {
157  
        return ! (lhs == rhs);
157  
        return ! (lhs == rhs);
158  
    }
158  
    }
159  
};
159  
};
160  

160  

161  
} // detail
161  
} // detail
162  
} // urls
162  
} // urls
163  
} // boost
163  
} // boost
164  

164  

165  
#endif
165  
#endif