Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cbd0ad6
commit a42432a
Showing
9 changed files
with
1,074 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// | ||
// Copyright (c) 2022 Alan Freitas (alandefreitas@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/CPPAlliance/url | ||
// | ||
|
||
#ifndef BOOST_URL_ANY_ALLOCATOR_HPP | ||
#define BOOST_URL_ANY_ALLOCATOR_HPP | ||
|
||
#include <boost/url/detail/config.hpp> | ||
#include <boost/url/detail/any_allocator.hpp> | ||
|
||
#include <memory> | ||
#include <type_traits> | ||
|
||
namespace boost { | ||
namespace urls { | ||
|
||
/** A type-erased allocator with shared ownership. | ||
This type satisfies the requirements for <em>Allocator</em> | ||
@par Specification | ||
@li <a href="https://en.cppreference.com/w/cpp/named_req/Allocator" | ||
>Allocator (cppreference.com)</a> | ||
*/ | ||
#ifdef BOOST_URL_DOCS | ||
template <class T> | ||
using any_allocator = __see_below__; | ||
#else | ||
template <class T> | ||
class any_allocator | ||
: private detail::any_allocator_base | ||
{ | ||
std::shared_ptr<base> p_; | ||
|
||
template <class U> | ||
friend class any_allocator; | ||
|
||
public: | ||
using value_type = T; | ||
|
||
template <class U> | ||
struct rebind | ||
{ | ||
using other = any_allocator<U>; | ||
}; | ||
|
||
using is_always_equal = std::false_type; | ||
|
||
#ifndef BOOST_URL_NO_GCC_4_2_WORKAROUND | ||
any_allocator() = default; | ||
#endif | ||
|
||
any_allocator(any_allocator const&) = default; | ||
|
||
template <class U> | ||
explicit any_allocator(any_allocator<U> const& other) noexcept; | ||
|
||
template <class Allocator> | ||
explicit any_allocator(Allocator const& a); | ||
|
||
any_allocator& | ||
operator=(any_allocator const&) = default; | ||
|
||
T* | ||
allocate(std::size_t n) const; | ||
|
||
void | ||
deallocate(T* p, std::size_t n); | ||
|
||
friend bool | ||
operator==(const any_allocator& a, const any_allocator& b) noexcept | ||
{ | ||
return (a.p_ == b.p_) || | ||
(a.p_ != nullptr && | ||
b.p_ != nullptr && | ||
(a.p_->type == b.p_->type && | ||
a.p_->is_equal(*b.p_))); | ||
} | ||
|
||
friend bool | ||
operator!=(const any_allocator& a, const any_allocator& b) noexcept | ||
{ | ||
return ! (a == b); | ||
} | ||
}; | ||
#endif | ||
|
||
} // urls | ||
} // boost | ||
|
||
#include <boost/url/impl/any_allocator.hpp> | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// | ||
// Copyright (c) 2022 Alan Freitas (alandefreitas@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/CPPAlliance/url | ||
// | ||
|
||
|
||
#ifndef BOOST_URL_DETAIL_ANY_ALLOCATOR_HPP | ||
#define BOOST_URL_DETAIL_ANY_ALLOCATOR_HPP | ||
|
||
#include <boost/url/detail/type_id.hpp> | ||
|
||
#include <boost/core/allocator_access.hpp> | ||
#include <boost/core/empty_value.hpp> | ||
#include <boost/type_traits/type_with_alignment.hpp> | ||
|
||
#include <cstddef> | ||
|
||
namespace boost { | ||
namespace urls { | ||
namespace detail { | ||
|
||
struct any_allocator_base | ||
{ | ||
struct base | ||
{ | ||
type_id_t type; | ||
|
||
virtual | ||
~base() = default; | ||
|
||
virtual | ||
void * | ||
allocate(std::size_t n, std::size_t size, std::size_t align) = 0; | ||
|
||
virtual | ||
void | ||
deallocate(void *p, std::size_t n, std::size_t size, std::size_t align) = 0; | ||
|
||
virtual | ||
bool | ||
is_equal(const any_allocator_base::base &p) = 0; | ||
}; | ||
|
||
template <typename Allocator> | ||
struct impl | ||
: public base, | ||
private empty_value<boost::allocator_rebind_t<Allocator, char>, 0> | ||
{ | ||
using allocator_type = boost::allocator_rebind_t<Allocator, char>; | ||
|
||
explicit | ||
impl(allocator_type const& a) | ||
: empty_value<allocator_type, 0>(empty_init_t(), a) | ||
{ | ||
type = get_type_id<allocator_type>(); | ||
} | ||
|
||
void* | ||
allocate(std::size_t n, std::size_t size, std::size_t align) override | ||
{ | ||
if (align == 1) | ||
return allocator().allocate(n); | ||
else | ||
return allocate_aligned(n, size, align); | ||
} | ||
|
||
void | ||
deallocate(void* p, std::size_t n, std::size_t size, std::size_t align) | ||
{ | ||
if (align == alignof(char)) | ||
allocator().deallocate(reinterpret_cast<char*>(p), n); | ||
else | ||
deallocate_aligned(p, n, size, align); | ||
} | ||
|
||
bool | ||
is_equal(const any_allocator_base::base& other) override | ||
{ | ||
const impl* other_impl = static_cast<const impl*>(&other); | ||
return allocator() == other_impl->allocator(); | ||
}; | ||
|
||
const allocator_type& allocator() const { | ||
return empty_value<allocator_type, 0>::get(); | ||
} | ||
|
||
allocator_type& allocator() { | ||
return empty_value<allocator_type, 0>::get(); | ||
} | ||
|
||
#if BOOST_WORKAROUND(BOOST_GCC, < 40900) | ||
using max_align_t = ::max_align_t; | ||
#else | ||
using max_align_t = std::max_align_t; | ||
#endif | ||
|
||
static | ||
std::size_t | ||
ceil_div(std::size_t n, std::size_t d) | ||
{ | ||
return (n + d - 1) / d; | ||
} | ||
|
||
template <std::size_t N> | ||
typename std::enable_if<alignof(max_align_t) <= N, void*>::type | ||
try_allocate_aligned(std::size_t n, std::size_t size, std::size_t align) | ||
{ | ||
using aligned_t = max_align_t; | ||
using aligned_allocator_t = boost::allocator_rebind_t<Allocator, aligned_t>; | ||
return aligned_allocator_t(allocator()).allocate(n * ceil_div(size, align)); | ||
} | ||
|
||
template <std::size_t N> | ||
typename std::enable_if<N < alignof(max_align_t), void*>::type | ||
try_allocate_aligned(std::size_t n, std::size_t size, std::size_t align) | ||
{ | ||
if (align <= N) | ||
{ | ||
using aligned_t = typename boost::type_with_alignment<N>::type; | ||
using aligned_allocator_t = boost::allocator_rebind_t<Allocator, aligned_t>; | ||
return aligned_allocator_t(allocator()).allocate(n * ceil_div(size, align)); | ||
} | ||
else | ||
{ | ||
return try_allocate_aligned<2*N>(n, size, align); | ||
} | ||
} | ||
|
||
void* | ||
allocate_aligned(std::size_t n, std::size_t size, std::size_t align) | ||
{ | ||
return try_allocate_aligned<2>(n, size, align); | ||
} | ||
|
||
|
||
template <std::size_t N> | ||
typename std::enable_if<alignof(max_align_t) <= N, void>::type | ||
try_deallocate_aligned(void* p, std::size_t n, std::size_t size, std::size_t align) | ||
{ | ||
using aligned_t = max_align_t; | ||
using aligned_allocator_t = boost::allocator_rebind_t<Allocator, aligned_t>; | ||
aligned_allocator_t(allocator()).deallocate(reinterpret_cast<aligned_t*>(p), n * ceil_div(size, align)); | ||
} | ||
|
||
template <std::size_t N> | ||
typename std::enable_if<N < alignof(max_align_t), void>::type | ||
try_deallocate_aligned(void* p, std::size_t n, std::size_t size, std::size_t align) | ||
{ | ||
if (align <= N) | ||
{ | ||
using aligned_t = typename boost::type_with_alignment<N>::type; | ||
using aligned_allocator_t = boost::allocator_rebind_t<Allocator, aligned_t>; | ||
aligned_allocator_t(allocator()).deallocate(reinterpret_cast<aligned_t*>(p), n * ceil_div(size, align)); | ||
} else { | ||
try_deallocate_aligned<2*N>(p, n, size, align); | ||
} | ||
} | ||
|
||
void | ||
deallocate_aligned(void* p, std::size_t n, std::size_t size, std::size_t align) | ||
{ | ||
try_deallocate_aligned<2>(p, n, size, align); | ||
} | ||
}; | ||
}; | ||
|
||
} // detail | ||
} // urls | ||
} // boost | ||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// | ||
// Copyright (c) 2022 Alan Freitas (alandefreitas@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/CPPAlliance/url | ||
// | ||
|
||
|
||
#ifndef BOOST_URL_DETAIL_TYPE_ID_HPP | ||
#define BOOST_URL_DETAIL_TYPE_ID_HPP | ||
|
||
namespace boost { | ||
namespace urls { | ||
namespace detail { | ||
|
||
using type_id_t = void const *; | ||
|
||
template <class T> | ||
type_id_t | ||
get_type_id() noexcept | ||
{ | ||
static constexpr char c{}; | ||
return &c; | ||
} | ||
|
||
} // namespace detail | ||
} // namespace urls | ||
} // namespace boost | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// | ||
// Copyright (c) 2022 Alan Freitas (alandefreitas@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/CPPAlliance/url | ||
// | ||
|
||
#ifndef BOOST_URL_IMPL_ANY_ALLOCATOR_HPP | ||
#define BOOST_URL_IMPL_ANY_ALLOCATOR_HPP | ||
|
||
#include <boost/assert.hpp> | ||
#include <boost/config/workaround.hpp> | ||
#include <boost/type_traits/make_void.hpp> | ||
|
||
#include <cstddef> | ||
|
||
namespace boost { | ||
namespace urls { | ||
|
||
template <class T> | ||
template <class Allocator> | ||
any_allocator<T>:: | ||
any_allocator(Allocator const& a) | ||
{ | ||
using char_allocator_type = boost::allocator_rebind_t<Allocator, char>; | ||
using impl_allocator_type = boost::allocator_rebind_t<Allocator, impl<char_allocator_type>>; | ||
p_ = std::allocate_shared<impl<char_allocator_type>>(impl_allocator_type(a), char_allocator_type(a)); | ||
} | ||
|
||
template <class T> | ||
template <class U> | ||
any_allocator<T>:: | ||
any_allocator( | ||
any_allocator<U> const& other) noexcept | ||
: p_(other.p_) | ||
{ | ||
} | ||
|
||
template <class T> | ||
T* | ||
any_allocator<T>:: | ||
allocate( | ||
std::size_t n) const | ||
{ | ||
if (p_) | ||
return reinterpret_cast<T*>(p_->allocate(n, sizeof(T), alignof(T))); | ||
return std::allocator<T>().allocate(n); | ||
} | ||
|
||
template <class T> | ||
void | ||
any_allocator<T>:: | ||
deallocate( | ||
T* p, | ||
std::size_t n) | ||
{ | ||
if (p_) | ||
return p_->deallocate(p, n, sizeof(T), alignof(T)); | ||
return std::allocator<T>().deallocate(p, n); | ||
} | ||
|
||
} // urls | ||
} // boost | ||
|
||
|
||
#endif |
Oops, something went wrong.