over_allocator.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. #ifndef BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP
  10. #define BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP
  11. #include <boost/config.hpp>
  12. #include <boost/core/empty_value.hpp>
  13. #include <boost/assert.hpp>
  14. #include <boost/type_traits/is_final.hpp>
  15. #include <boost/type_traits/type_with_alignment.hpp>
  16. #ifdef BOOST_NO_CXX11_ALLOCATOR
  17. # include <boost/core/allocator_traits.hpp>
  18. #endif
  19. #include <cstddef>
  20. #include <memory>
  21. #include <type_traits>
  22. #include <utility>
  23. namespace boost {
  24. namespace urls {
  25. namespace detail {
  26. // This is a workaround for allocator_traits
  27. // implementations which falsely claim C++11
  28. // compatibility.
  29. #ifdef BOOST_NO_CXX11_ALLOCATOR
  30. template<class Alloc>
  31. using allocator_traits =
  32. boost::allocator_traits<Alloc>;
  33. #else
  34. template<class Alloc>
  35. using allocator_traits = std::allocator_traits<Alloc>;
  36. #endif
  37. template<class T, class Allocator>
  38. class over_allocator
  39. : private empty_value<Allocator>
  40. {
  41. template<class U, class OtherAlloc>
  42. friend class over_allocator;
  43. std::size_t extra_;
  44. public:
  45. using is_always_equal = std::false_type;
  46. using value_type = typename
  47. allocator_traits<typename allocator_traits<
  48. Allocator>::template rebind_alloc<T>>::value_type;
  49. using pointer = typename
  50. allocator_traits<typename allocator_traits<
  51. Allocator>::template rebind_alloc<T>>::pointer;
  52. using const_pointer = typename
  53. allocator_traits<typename allocator_traits<
  54. Allocator>::template rebind_alloc<T>>::const_pointer;
  55. using size_type = typename
  56. allocator_traits<typename allocator_traits<
  57. Allocator>::template rebind_alloc<T>>::size_type;
  58. using difference_type = typename
  59. allocator_traits<typename allocator_traits<
  60. Allocator>::template rebind_alloc<T>>::difference_type;
  61. template<class U>
  62. struct rebind
  63. {
  64. using other = over_allocator<U, Allocator>;
  65. };
  66. over_allocator(
  67. std::size_t extra,
  68. Allocator const& alloc)
  69. : empty_value<Allocator>(
  70. empty_init, alloc)
  71. , extra_(extra)
  72. {
  73. }
  74. template<class U>
  75. over_allocator(over_allocator<U, Allocator> const& other) noexcept
  76. : empty_value<Allocator>(
  77. empty_init, other.get())
  78. , extra_(other.extra_)
  79. {
  80. }
  81. pointer
  82. allocate(size_type n)
  83. {
  84. BOOST_ASSERT(n == 1);
  85. using U = typename boost::type_with_alignment<
  86. alignof(value_type)>::type;
  87. auto constexpr S = sizeof(U);
  88. using A = typename allocator_traits<
  89. Allocator>::template rebind_alloc<U>;
  90. A a(this->get());
  91. return reinterpret_cast<pointer>(
  92. std::allocator_traits<A>::allocate(a,
  93. (n * sizeof(value_type) + extra_ + S - 1) / S));
  94. }
  95. void
  96. deallocate(pointer p, size_type n)
  97. {
  98. BOOST_ASSERT(n == 1);
  99. using U = typename boost::type_with_alignment<
  100. alignof(value_type)>::type;
  101. auto constexpr S = sizeof(U);
  102. using A = typename allocator_traits<
  103. Allocator>::template rebind_alloc<U>;
  104. A a{this->get()};
  105. std::allocator_traits<A>::deallocate(a,
  106. reinterpret_cast<U*>(p),
  107. (n * sizeof(value_type) + extra_ + S - 1) / S);
  108. }
  109. #if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
  110. template<class U, class... Args>
  111. void
  112. construct(U* ptr, Args&&... args)
  113. {
  114. ::new((void*)ptr) U(std::forward<Args>(args)...);
  115. }
  116. template<class U>
  117. void
  118. destroy(U* ptr)
  119. {
  120. ptr->~U();
  121. }
  122. #endif
  123. template<class U>
  124. friend
  125. bool
  126. operator==(
  127. over_allocator const& lhs,
  128. over_allocator<U, Allocator> const& rhs)
  129. {
  130. return
  131. lhs.get() == rhs.get() &&
  132. lhs.extra_ == rhs.extra_;
  133. }
  134. template<class U>
  135. friend
  136. bool
  137. operator!=(
  138. over_allocator const& lhs,
  139. over_allocator<U, Allocator> const& rhs)
  140. {
  141. return ! (lhs == rhs);
  142. }
  143. };
  144. } // detail
  145. } // urls
  146. } // boost
  147. #endif