// // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/url // #ifndef BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP #define BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP #include #include #include #include #include #ifdef BOOST_NO_CXX11_ALLOCATOR # include #endif #include #include #include #include namespace boost { namespace urls { namespace detail { // This is a workaround for allocator_traits // implementations which falsely claim C++11 // compatibility. #ifdef BOOST_NO_CXX11_ALLOCATOR template using allocator_traits = boost::allocator_traits; #else template using allocator_traits = std::allocator_traits; #endif template class over_allocator : private empty_value { template friend class over_allocator; std::size_t extra_; public: using is_always_equal = std::false_type; using value_type = typename allocator_traits::template rebind_alloc>::value_type; using pointer = typename allocator_traits::template rebind_alloc>::pointer; using const_pointer = typename allocator_traits::template rebind_alloc>::const_pointer; using size_type = typename allocator_traits::template rebind_alloc>::size_type; using difference_type = typename allocator_traits::template rebind_alloc>::difference_type; template struct rebind { using other = over_allocator; }; over_allocator( std::size_t extra, Allocator const& alloc) : empty_value( empty_init, alloc) , extra_(extra) { } template over_allocator(over_allocator const& other) noexcept : empty_value( empty_init, other.get()) , extra_(other.extra_) { } pointer allocate(size_type n) { BOOST_ASSERT(n == 1); using U = typename boost::type_with_alignment< alignof(value_type)>::type; auto constexpr S = sizeof(U); using A = typename allocator_traits< Allocator>::template rebind_alloc; A a(this->get()); return reinterpret_cast( std::allocator_traits::allocate(a, (n * sizeof(value_type) + extra_ + S - 1) / S)); } void deallocate(pointer p, size_type n) { BOOST_ASSERT(n == 1); using U = typename boost::type_with_alignment< alignof(value_type)>::type; auto constexpr S = sizeof(U); using A = typename allocator_traits< Allocator>::template rebind_alloc; A a{this->get()}; std::allocator_traits::deallocate(a, reinterpret_cast(p), (n * sizeof(value_type) + extra_ + S - 1) / S); } #if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000 template void construct(U* ptr, Args&&... args) { ::new((void*)ptr) U(std::forward(args)...); } template void destroy(U* ptr) { ptr->~U(); } #endif template friend bool operator==( over_allocator const& lhs, over_allocator const& rhs) { return lhs.get() == rhs.get() && lhs.extra_ == rhs.extra_; } template friend bool operator!=( over_allocator const& lhs, over_allocator const& rhs) { return ! (lhs == rhs); } }; } // detail } // urls } // boost #endif