Added thirdparty: boost library

This commit is contained in:
Viacheslav Demydiuk
2024-01-06 19:55:56 +02:00
parent bf49f439e1
commit bccd1e7051
15683 changed files with 3239840 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_ALLOCATOR_HPP
#define BOOST_BEAST_DETAIL_ALLOCATOR_HPP
#include <boost/config.hpp>
#ifdef BOOST_NO_CXX11_ALLOCATOR
#include <boost/container/allocator_traits.hpp>
#else
#include <memory>
#endif
namespace boost {
namespace beast {
namespace detail {
// This is a workaround for allocator_traits
// implementations which falsely claim C++11
// compatibility.
#ifdef BOOST_NO_CXX11_ALLOCATOR
template<class Alloc>
using allocator_traits = boost::container::allocator_traits<Alloc>;
#else
template<class Alloc>
using allocator_traits = std::allocator_traits<Alloc>;
#endif
} // detail
} // beast
} // boost
#endif
+46
View File
@@ -0,0 +1,46 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_ASYNC_BASE_HPP
#define BOOST_BEAST_CORE_DETAIL_ASYNC_BASE_HPP
#include <boost/core/exchange.hpp>
namespace boost {
namespace beast {
namespace detail {
struct stable_base
{
static
void
destroy_list(stable_base*& list)
{
while(list)
{
auto next = list->next_;
list->destroy();
list = next;
}
}
stable_base* next_ = nullptr;
protected:
stable_base() = default;
virtual ~stable_base() = default;
virtual void destroy() = 0;
};
} // detail
} // beast
} // boost
#endif
+88
View File
@@ -0,0 +1,88 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_BASE64_HPP
#define BOOST_BEAST_DETAIL_BASE64_HPP
#include <boost/beast/core/string.hpp>
#include <cctype>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
namespace base64 {
BOOST_BEAST_DECL
char const*
get_alphabet();
BOOST_BEAST_DECL
signed char const*
get_inverse();
/// Returns max chars needed to encode a base64 string
BOOST_BEAST_DECL
std::size_t constexpr
encoded_size(std::size_t n)
{
return 4 * ((n + 2) / 3);
}
/// Returns max bytes needed to decode a base64 string
inline
std::size_t constexpr
decoded_size(std::size_t n)
{
return n / 4 * 3; // requires n&3==0, smaller
}
/** Encode a series of octets as a padded, base64 string.
The resulting string will not be null terminated.
@par Requires
The memory pointed to by `out` points to valid memory
of at least `encoded_size(len)` bytes.
@return The number of characters written to `out`. This
will exclude any null termination.
*/
BOOST_BEAST_DECL
std::size_t
encode(void* dest, void const* src, std::size_t len);
/** Decode a padded base64 string into a series of octets.
@par Requires
The memory pointed to by `out` points to valid memory
of at least `decoded_size(len)` bytes.
@return The number of octets written to `out`, and
the number of characters read from the input string,
expressed as a pair.
*/
BOOST_BEAST_DECL
std::pair<std::size_t, std::size_t>
decode(void* dest, char const* src, std::size_t len);
} // base64
} // detail
} // beast
} // boost
#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/core/detail/base64.ipp>
#endif
#endif
+202
View File
@@ -0,0 +1,202 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
/*
Portions from http://www.adp-gmbh.ch/cpp/common/base64.html
Copyright notice:
base64.cpp and base64.h
Copyright (C) 2004-2008 Rene Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
Rene Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/
#ifndef BOOST_BEAST_DETAIL_BASE64_IPP
#define BOOST_BEAST_DETAIL_BASE64_IPP
#include <boost/beast/core/detail/base64.hpp>
#include <boost/beast/core/string.hpp>
#include <cctype>
#include <string>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
namespace base64 {
char const*
get_alphabet()
{
static char constexpr tab[] = {
"ABCDEFGHIJKLMNOP"
"QRSTUVWXYZabcdef"
"ghijklmnopqrstuv"
"wxyz0123456789+/"
};
return &tab[0];
}
signed char const*
get_inverse()
{
static signed char constexpr tab[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32-47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48-63
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80-95
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112-127
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240-255
};
return &tab[0];
}
/** Encode a series of octets as a padded, base64 string.
The resulting string will not be null terminated.
@par Requires
The memory pointed to by `out` points to valid memory
of at least `encoded_size(len)` bytes.
@return The number of characters written to `out`. This
will exclude any null termination.
*/
std::size_t
encode(void* dest, void const* src, std::size_t len)
{
char* out = static_cast<char*>(dest);
char const* in = static_cast<char const*>(src);
auto const tab = base64::get_alphabet();
for(auto n = len / 3; n--;)
{
*out++ = tab[ (in[0] & 0xfc) >> 2];
*out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
*out++ = tab[((in[2] & 0xc0) >> 6) + ((in[1] & 0x0f) << 2)];
*out++ = tab[ in[2] & 0x3f];
in += 3;
}
switch(len % 3)
{
case 2:
*out++ = tab[ (in[0] & 0xfc) >> 2];
*out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
*out++ = tab[ (in[1] & 0x0f) << 2];
*out++ = '=';
break;
case 1:
*out++ = tab[ (in[0] & 0xfc) >> 2];
*out++ = tab[((in[0] & 0x03) << 4)];
*out++ = '=';
*out++ = '=';
break;
case 0:
break;
}
return out - static_cast<char*>(dest);
}
/** Decode a padded base64 string into a series of octets.
@par Requires
The memory pointed to by `out` points to valid memory
of at least `decoded_size(len)` bytes.
@return The number of octets written to `out`, and
the number of characters read from the input string,
expressed as a pair.
*/
std::pair<std::size_t, std::size_t>
decode(void* dest, char const* src, std::size_t len)
{
char* out = static_cast<char*>(dest);
auto in = reinterpret_cast<unsigned char const*>(src);
unsigned char c3[3], c4[4] = {0,0,0,0};
int i = 0;
int j = 0;
auto const inverse = base64::get_inverse();
while(len-- && *in != '=')
{
auto const v = inverse[*in];
if(v == -1)
break;
++in;
c4[i] = v;
if(++i == 4)
{
c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4);
c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
for(i = 0; i < 3; i++)
*out++ = c3[i];
i = 0;
}
}
if(i)
{
c3[0] = ( c4[0] << 2) + ((c4[1] & 0x30) >> 4);
c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
for(j = 0; j < i - 1; j++)
*out++ = c3[j];
}
return {out - static_cast<char*>(dest),
in - reinterpret_cast<unsigned char const*>(src)};
}
} // base64
} // detail
} // beast
} // boost
#endif
+110
View File
@@ -0,0 +1,110 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_BIND_CONTINUATION_HPP
#define BOOST_BEAST_DETAIL_BIND_CONTINUATION_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/detail/remap_post_to_defer.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/core/empty_value.hpp>
#include <type_traits>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
#if 0
/** Mark a completion handler as a continuation.
This function wraps a completion handler to associate it with an
executor whose `post` operation is remapped to the `defer` operation.
It is used by composed asynchronous operation implementations to
indicate that a completion handler submitted to an initiating
function represents a continuation of the current asynchronous
flow of control.
@param handler The handler to wrap.
The implementation takes ownership of the handler by performing a decay-copy.
@see
@li <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4242.html">[N4242] Executors and Asynchronous Operations, Revision 1</a>
*/
template<class CompletionHandler>
#if BOOST_BEAST_DOXYGEN
__implementation_defined__
#else
net::executor_binder<
typename std::decay<CompletionHandler>::type,
detail::remap_post_to_defer<
net::associated_executor_t<CompletionHandler>>>
#endif
bind_continuation(CompletionHandler&& handler)
{
return net::bind_executor(
detail::remap_post_to_defer<
net::associated_executor_t<CompletionHandler>>(
net::get_associated_executor(handler)),
std::forward<CompletionHandler>(handler));
}
/** Mark a completion handler as a continuation.
This function wraps a completion handler to associate it with an
executor whose `post` operation is remapped to the `defer` operation.
It is used by composed asynchronous operation implementations to
indicate that a completion handler submitted to an initiating
function represents a continuation of the current asynchronous
flow of control.
@param ex The executor to use
@param handler The handler to wrap
The implementation takes ownership of the handler by performing a decay-copy.
@see
@li <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4242.html">[N4242] Executors and Asynchronous Operations, Revision 1</a>
*/
template<class Executor, class CompletionHandler>
#if BOOST_BEAST_DOXYGEN
__implementation_defined__
#else
net::executor_binder<typename
std::decay<CompletionHandler>::type,
detail::remap_post_to_defer<Executor>>
#endif
bind_continuation(
Executor const& ex, CompletionHandler&& handler)
{
return net::bind_executor(
detail::remap_post_to_defer<Executor>(ex),
std::forward<CompletionHandler>(handler));
}
#else
// VFALCO I turned these off at the last minute because they cause
// the completion handler to be moved before the initiating
// function is invoked rather than after, which is a foot-gun.
//
// REMINDER: Uncomment the tests when this is put back
template<class F>
F&&
bind_continuation(F&& f)
{
return std::forward<F>(f);
}
#endif
} // detail
} // beast
} // boost
#endif
+401
View File
@@ -0,0 +1,401 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
#define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/detail/tuple.hpp>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_cancellation_slot.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/handler_continuation_hook.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/mp11/integer_sequence.hpp>
#include <boost/bind/std_placeholders.hpp>
#include <boost/is_placeholder.hpp>
#include <functional>
#include <type_traits>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
//------------------------------------------------------------------------------
//
// bind_handler
//
//------------------------------------------------------------------------------
template<class Handler, class... Args>
class bind_wrapper
{
using args_type = detail::tuple<Args...>;
Handler h_;
args_type args_;
template<class T, class Executor>
friend struct net::associated_executor;
template<class T, class Allocator>
friend struct net::associated_allocator;
template<class T, class CancellationSlot>
friend struct net::associated_cancellation_slot;
template<class Arg, class Vals>
static
typename std::enable_if<
std::is_placeholder<typename
std::decay<Arg>::type>::value == 0 &&
boost::is_placeholder<typename
std::decay<Arg>::type>::value == 0,
Arg&&>::type
extract(Arg&& arg, Vals&& vals)
{
boost::ignore_unused(vals);
return std::forward<Arg>(arg);
}
template<class Arg, class Vals>
static
typename std::enable_if<
std::is_placeholder<typename
std::decay<Arg>::type>::value != 0,
tuple_element<std::is_placeholder<
typename std::decay<Arg>::type>::value - 1,
Vals>>::type&&
extract(Arg&&, Vals&& vals)
{
return detail::get<std::is_placeholder<
typename std::decay<Arg>::type>::value - 1>(
std::forward<Vals>(vals));
}
template<class Arg, class Vals>
static
typename std::enable_if<
boost::is_placeholder<typename
std::decay<Arg>::type>::value != 0 &&
std::is_placeholder<typename
std::decay<Arg>::type>::value == 0,
tuple_element<boost::is_placeholder<
typename std::decay<Arg>::type>::value - 1,
Vals>>::type&&
extract(Arg&&, Vals&& vals)
{
return detail::get<boost::is_placeholder<
typename std::decay<Arg>::type>::value - 1>(
std::forward<Vals>(vals));
}
template<class ArgsTuple, std::size_t... S>
static
void
invoke(
Handler& h,
ArgsTuple& args,
tuple<>&&,
mp11::index_sequence<S...>)
{
boost::ignore_unused(args);
h(detail::get<S>(std::move(args))...);
}
template<
class ArgsTuple,
class ValsTuple,
std::size_t... S>
static
void
invoke(
Handler& h,
ArgsTuple& args,
ValsTuple&& vals,
mp11::index_sequence<S...>)
{
boost::ignore_unused(args);
boost::ignore_unused(vals);
h(extract(detail::get<S>(std::move(args)),
std::forward<ValsTuple>(vals))...);
}
public:
using result_type = void; // asio needs this
bind_wrapper(bind_wrapper&&) = default;
bind_wrapper(bind_wrapper const&) = default;
template<
class DeducedHandler,
class... Args_>
explicit
bind_wrapper(
DeducedHandler&& handler,
Args_&&... args)
: h_(std::forward<DeducedHandler>(handler))
, args_(std::forward<Args_>(args)...)
{
}
template<class... Values>
void
operator()(Values&&... values)
{
invoke(h_, args_,
tuple<Values&&...>(
std::forward<Values>(values)...),
mp11::index_sequence_for<Args...>());
}
//
friend
bool asio_handler_is_continuation(
bind_wrapper* op)
{
using boost::asio::asio_handler_is_continuation;
return asio_handler_is_continuation(
std::addressof(op->h_));
}
};
template<class Handler, class... Args>
class bind_back_wrapper;
template<class Handler, class... Args>
class bind_front_wrapper;
//------------------------------------------------------------------------------
//
// bind_front
//
//------------------------------------------------------------------------------
template<class Handler, class... Args>
class bind_front_wrapper
{
Handler h_;
detail::tuple<Args...> args_;
template<class T, class Executor>
friend struct net::associated_executor;
template<class T, class Allocator>
friend struct net::associated_allocator;
template<class T, class CancellationSlot>
friend struct net::associated_cancellation_slot;
template<std::size_t... I, class... Ts>
void
invoke(
std::false_type,
mp11::index_sequence<I...>,
Ts&&... ts)
{
h_( detail::get<I>(std::move(args_))...,
std::forward<Ts>(ts)...);
}
template<std::size_t... I, class... Ts>
void
invoke(
std::true_type,
mp11::index_sequence<I...>,
Ts&&... ts)
{
std::mem_fn(h_)(
detail::get<I>(std::move(args_))...,
std::forward<Ts>(ts)...);
}
public:
using result_type = void; // asio needs this
bind_front_wrapper(bind_front_wrapper&&) = default;
bind_front_wrapper(bind_front_wrapper const&) = default;
template<class Handler_, class... Args_>
bind_front_wrapper(
Handler_&& handler,
Args_&&... args)
: h_(std::forward<Handler_>(handler))
, args_(std::forward<Args_>(args)...)
{
}
template<class... Ts>
void operator()(Ts&&... ts)
{
invoke(
std::is_member_function_pointer<Handler>{},
mp11::index_sequence_for<Args...>{},
std::forward<Ts>(ts)...);
}
//
friend
bool asio_handler_is_continuation(
bind_front_wrapper* op)
{
using boost::asio::asio_handler_is_continuation;
return asio_handler_is_continuation(
std::addressof(op->h_));
}
};
} // detail
} // beast
} // boost
//------------------------------------------------------------------------------
namespace boost {
namespace asio {
template<class Handler, class... Args, class Executor>
struct associated_executor<
beast::detail::bind_wrapper<Handler, Args...>, Executor>
{
using type = typename
associated_executor<Handler, Executor>::type;
static
type
get(beast::detail::bind_wrapper<Handler, Args...> const& op,
Executor const& ex = Executor{}) noexcept
{
return associated_executor<
Handler, Executor>::get(op.h_, ex);
}
};
template<class Handler, class... Args, class Executor>
struct associated_executor<
beast::detail::bind_front_wrapper<Handler, Args...>, Executor>
{
using type = typename
associated_executor<Handler, Executor>::type;
static
type
get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
Executor const& ex = Executor{}) noexcept
{
return associated_executor<
Handler, Executor>::get(op.h_, ex);
}
};
//
template<class Handler, class... Args, class Allocator>
struct associated_allocator<
beast::detail::bind_wrapper<Handler, Args...>, Allocator>
{
using type = typename
associated_allocator<Handler, Allocator>::type;
static
type
get(beast::detail::bind_wrapper<Handler, Args...> const& op,
Allocator const& alloc = Allocator{}) noexcept
{
return associated_allocator<
Handler, Allocator>::get(op.h_, alloc);
}
};
template<class Handler, class... Args, class Allocator>
struct associated_allocator<
beast::detail::bind_front_wrapper<Handler, Args...>, Allocator>
{
using type = typename
associated_allocator<Handler, Allocator>::type;
static
type
get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
Allocator const& alloc = Allocator{}) noexcept
{
return associated_allocator<
Handler, Allocator>::get(op.h_, alloc);
}
};
template<class Handler, class... Args, class CancellationSlot>
struct associated_cancellation_slot<
beast::detail::bind_wrapper<Handler, Args...>, CancellationSlot>
{
using type = typename
associated_cancellation_slot<Handler>::type;
static
type
get(beast::detail::bind_wrapper<Handler, Args...> const& op,
CancellationSlot const& slot = CancellationSlot{}) noexcept
{
return associated_cancellation_slot<
Handler, CancellationSlot>::get(op.h_, slot);
}
};
template<class Handler, class... Args, class CancellationSlot>
struct associated_cancellation_slot<
beast::detail::bind_front_wrapper<Handler, Args...>, CancellationSlot>
{
using type = typename
associated_cancellation_slot<Handler>::type;
static
type
get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
CancellationSlot const& slot = CancellationSlot{}) noexcept
{
return associated_cancellation_slot<
Handler, CancellationSlot>::get(op.h_, slot);
}
};
} // asio
} // boost
//------------------------------------------------------------------------------
namespace std {
// VFALCO Using std::bind on a completion handler will
// cause undefined behavior later, because the executor
// associated with the handler is not propagated to the
// wrapper returned by std::bind; these overloads are
// deleted to prevent mistakes. If this creates a problem
// please contact me.
template<class Handler, class... Args>
void
bind(boost::beast::detail::bind_wrapper<
Handler, Args...>, ...) = delete;
template<class Handler, class... Args>
void
bind(boost::beast::detail::bind_front_wrapper<
Handler, Args...>, ...) = delete;
} // std
//------------------------------------------------------------------------------
#endif
+84
View File
@@ -0,0 +1,84 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_BUFFER_HPP
#define BOOST_BEAST_CORE_DETAIL_BUFFER_HPP
#include <boost/beast/core/error.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
#include <stdexcept>
namespace boost {
namespace beast {
namespace detail {
template<
class DynamicBuffer,
class ErrorValue>
auto
dynamic_buffer_prepare_noexcept(
DynamicBuffer& buffer,
std::size_t size,
error_code& ec,
ErrorValue ev) ->
boost::optional<typename
DynamicBuffer::mutable_buffers_type>
{
if(buffer.max_size() - buffer.size() < size)
{
// length error
BOOST_BEAST_ASSIGN_EC(ec, ev);
return boost::none;
}
boost::optional<typename
DynamicBuffer::mutable_buffers_type> result;
result.emplace(buffer.prepare(size));
ec = {};
return result;
}
template<
class DynamicBuffer,
class ErrorValue>
auto
dynamic_buffer_prepare(
DynamicBuffer& buffer,
std::size_t size,
error_code& ec,
ErrorValue ev) ->
boost::optional<typename
DynamicBuffer::mutable_buffers_type>
{
#ifndef BOOST_NO_EXCEPTIONS
try
{
boost::optional<typename
DynamicBuffer::mutable_buffers_type> result;
result.emplace(buffer.prepare(size));
ec = {};
return result;
}
catch(std::length_error const&)
{
BOOST_BEAST_ASSIGN_EC(ec, ev);
}
return boost::none;
#else
return dynamic_buffer_prepare_noexcept(
buffer, size, ec, ev);
#endif
}
} // detail
} // beast
} // boost
#endif
+98
View File
@@ -0,0 +1,98 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_BUFFER_TRAITS_HPP
#define BOOST_BEAST_DETAIL_BUFFER_TRAITS_HPP
#include <boost/asio/buffer.hpp>
#include <boost/config/workaround.hpp>
#include <boost/type_traits/make_void.hpp>
#include <cstdint>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
template<class T>
struct buffers_iterator_type_helper
{
using type = decltype(
net::buffer_sequence_begin(
std::declval<T const&>()));
};
template<>
struct buffers_iterator_type_helper<
net::const_buffer>
{
using type = net::const_buffer const*;
};
template<>
struct buffers_iterator_type_helper<
net::mutable_buffer>
{
using type = net::mutable_buffer const*;
};
#endif
struct buffer_bytes_impl
{
std::size_t
operator()(net::const_buffer b) const noexcept
{
return net::const_buffer(b).size();
}
std::size_t
operator()(net::mutable_buffer b) const noexcept
{
return net::mutable_buffer(b).size();
}
template<
class B,
class = typename std::enable_if<
net::is_const_buffer_sequence<B>::value>::type>
std::size_t
operator()(B const& b) const noexcept
{
using net::buffer_size;
return buffer_size(b);
}
};
/** Return `true` if a buffer sequence is empty
This is sometimes faster than using @ref buffer_bytes
*/
template<class ConstBufferSequence>
bool
buffers_empty(ConstBufferSequence const& buffers)
{
auto it = net::buffer_sequence_begin(buffers);
auto end = net::buffer_sequence_end(buffers);
while(it != end)
{
if(net::const_buffer(*it).size() > 0)
return false;
++it;
}
return true;
}
} // detail
} // beast
} // boost
#endif
+115
View File
@@ -0,0 +1,115 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_BUFFERS_PAIR_HPP
#define BOOST_BEAST_DETAIL_BUFFERS_PAIR_HPP
#include <boost/asio/buffer.hpp>
#include <boost/assert.hpp>
#include <boost/config/workaround.hpp>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
# pragma warning (push)
# pragma warning (disable: 4521) // multiple copy constructors specified
# pragma warning (disable: 4522) // multiple assignment operators specified
#endif
template<bool isMutable>
class buffers_pair
{
public:
// VFALCO: This type is public otherwise
// asio::buffers_iterator won't compile.
using value_type = typename
std::conditional<isMutable,
net::mutable_buffer,
net::const_buffer>::type;
using const_iterator = value_type const*;
buffers_pair() = default;
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
buffers_pair(buffers_pair const& other)
: buffers_pair(
*other.begin(), *(other.begin() + 1))
{
}
buffers_pair&
operator=(buffers_pair const& other)
{
b_[0] = *other.begin();
b_[1] = *(other.begin() + 1);
return *this;
}
#else
buffers_pair(buffers_pair const& other) = default;
buffers_pair& operator=(buffers_pair const& other) = default;
#endif
template<
bool isMutable_ = isMutable,
class = typename std::enable_if<
! isMutable_>::type>
buffers_pair(buffers_pair<true> const& other)
: buffers_pair(
*other.begin(), *(other.begin() + 1))
{
}
template<
bool isMutable_ = isMutable,
class = typename std::enable_if<
! isMutable_>::type>
buffers_pair&
operator=(buffers_pair<true> const& other)
{
b_[0] = *other.begin();
b_[1] = *(other.begin() + 1);
return *this;
}
buffers_pair(value_type b0, value_type b1)
: b_{b0, b1}
{
}
const_iterator
begin() const noexcept
{
return &b_[0];
}
const_iterator
end() const noexcept
{
if(b_[1].size() > 0)
return &b_[2];
return &b_[1];
}
private:
value_type b_[2];
};
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
# pragma warning (pop)
#endif
} // detail
} // beast
} // boost
#endif
+133
View File
@@ -0,0 +1,133 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_BUFFERS_RANGE_ADAPTOR_HPP
#define BOOST_BEAST_DETAIL_BUFFERS_RANGE_ADAPTOR_HPP
#include <boost/beast/core/buffer_traits.hpp>
#include <iterator>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
template<class BufferSequence>
class buffers_range_adaptor
{
BufferSequence b_;
public:
#if BOOST_BEAST_DOXYGEN
using value_type = __see_below__;
#else
using value_type = buffers_type<BufferSequence>;
#endif
class const_iterator
{
friend class buffers_range_adaptor;
using iter_type =
buffers_iterator_type<BufferSequence>;
iter_type it_{};
const_iterator(iter_type const& it)
: it_(it)
{
}
public:
using value_type = typename
buffers_range_adaptor::value_type;
using pointer = value_type const*;
using reference = value_type;
using difference_type = std::ptrdiff_t;
using iterator_category =
std::bidirectional_iterator_tag;
const_iterator() = default;
bool
operator==(const_iterator const& other) const
{
return it_ == other.it_;
}
bool
operator!=(const_iterator const& other) const
{
return !(*this == other);
}
reference
operator*() const
{
return *it_;
}
pointer
operator->() const = delete;
const_iterator&
operator++()
{
++it_;
return *this;
}
const_iterator
operator++(int)
{
auto temp = *this;
++(*this);
return temp;
}
const_iterator&
operator--()
{
--it_;
return *this;
}
const_iterator
operator--(int)
{
auto temp = *this;
--(*this);
return temp;
}
};
explicit
buffers_range_adaptor(BufferSequence const& b)
: b_(b)
{
}
const_iterator
begin() const noexcept
{
return {net::buffer_sequence_begin(b_)};
}
const_iterator
end() const noexcept
{
return {net::buffer_sequence_end(b_)};
}
};
} // detail
} // beast
} // boost
#endif
+71
View File
@@ -0,0 +1,71 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_BUFFERS_REF_HPP
#define BOOST_BEAST_DETAIL_BUFFERS_REF_HPP
#include <boost/beast/core/buffer_traits.hpp>
#include <iterator>
#include <memory>
namespace boost {
namespace beast {
namespace detail {
// A very lightweight reference to a buffer sequence
template<class BufferSequence>
class buffers_ref
{
BufferSequence const* buffers_;
public:
using const_iterator =
buffers_iterator_type<BufferSequence>;
using value_type = typename
std::iterator_traits<const_iterator>::value_type;
buffers_ref(buffers_ref const&) = default;
buffers_ref& operator=(buffers_ref const&) = default;
explicit
buffers_ref(BufferSequence const& buffers)
: buffers_(std::addressof(buffers))
{
}
const_iterator
begin() const
{
return net::buffer_sequence_begin(*buffers_);
}
const_iterator
end() const
{
return net::buffer_sequence_end(*buffers_);
}
};
// Return a reference to a buffer sequence
template<class BufferSequence>
buffers_ref<BufferSequence>
make_buffers_ref(BufferSequence const& buffers)
{
static_assert(
is_const_buffer_sequence<BufferSequence>::value,
"BufferSequence type requirements not met");
return buffers_ref<BufferSequence>(buffers);
}
} // detail
} // beast
} // boost
#endif
+126
View File
@@ -0,0 +1,126 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
//
// This is a derivative work, original copyright follows:
//
/*
Copyright (c) 2015 Orson Peters <orsonpeters@gmail.com>
This software is provided 'as-is', without any express or implied warranty. In no event will the
authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial
applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the
original software. If you use this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as
being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BOOST_BEAST_CORE_DETAIL_CHACHA_HPP
#define BOOST_BEAST_CORE_DETAIL_CHACHA_HPP
#include <cstdint>
#include <limits>
namespace boost {
namespace beast {
namespace detail {
template<std::size_t R>
class chacha
{
alignas(16) std::uint32_t block_[16];
std::uint32_t keysetup_[8];
std::uint64_t ctr_ = 0;
int idx_ = 16;
void generate_block()
{
std::uint32_t constexpr constants[4] = {
0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 };
std::uint32_t input[16];
for (int i = 0; i < 4; ++i)
input[i] = constants[i];
for (int i = 0; i < 8; ++i)
input[4 + i] = keysetup_[i];
input[12] = (ctr_ / 16) & 0xffffffffu;
input[13] = (ctr_ / 16) >> 32;
input[14] = input[15] = 0xdeadbeef; // Could use 128-bit counter.
for (int i = 0; i < 16; ++i)
block_[i] = input[i];
chacha_core();
for (int i = 0; i < 16; ++i)
block_[i] += input[i];
}
void chacha_core()
{
#define BOOST_BEAST_CHACHA_ROTL32(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
#define BOOST_BEAST_CHACHA_QUARTERROUND(x, a, b, c, d) \
x[a] = x[a] + x[b]; x[d] ^= x[a]; x[d] = BOOST_BEAST_CHACHA_ROTL32(x[d], 16); \
x[c] = x[c] + x[d]; x[b] ^= x[c]; x[b] = BOOST_BEAST_CHACHA_ROTL32(x[b], 12); \
x[a] = x[a] + x[b]; x[d] ^= x[a]; x[d] = BOOST_BEAST_CHACHA_ROTL32(x[d], 8); \
x[c] = x[c] + x[d]; x[b] ^= x[c]; x[b] = BOOST_BEAST_CHACHA_ROTL32(x[b], 7)
for (unsigned i = 0; i < R; i += 2)
{
BOOST_BEAST_CHACHA_QUARTERROUND(block_, 0, 4, 8, 12);
BOOST_BEAST_CHACHA_QUARTERROUND(block_, 1, 5, 9, 13);
BOOST_BEAST_CHACHA_QUARTERROUND(block_, 2, 6, 10, 14);
BOOST_BEAST_CHACHA_QUARTERROUND(block_, 3, 7, 11, 15);
BOOST_BEAST_CHACHA_QUARTERROUND(block_, 0, 5, 10, 15);
BOOST_BEAST_CHACHA_QUARTERROUND(block_, 1, 6, 11, 12);
BOOST_BEAST_CHACHA_QUARTERROUND(block_, 2, 7, 8, 13);
BOOST_BEAST_CHACHA_QUARTERROUND(block_, 3, 4, 9, 14);
}
#undef BOOST_BEAST_CHACHA_QUARTERROUND
#undef BOOST_BEAST_CHACHA_ROTL32
}
public:
static constexpr std::size_t state_size = sizeof(chacha::keysetup_);
using result_type = std::uint32_t;
chacha(std::uint32_t const* v, std::uint64_t stream)
{
for (int i = 0; i < 6; ++i)
keysetup_[i] = v[i];
keysetup_[6] = v[6] + (stream & 0xffffffff);
keysetup_[7] = v[7] + ((stream >> 32) & 0xffffffff);
}
std::uint32_t
operator()()
{
if(idx_ == 16)
{
idx_ = 0;
++ctr_;
generate_block();
}
return block_[idx_++];
}
};
} // detail
} // beast
} // boost
#endif
+78
View File
@@ -0,0 +1,78 @@
//
// Copyright (c) 2019 Damian Jarek(damian.jarek93@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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_CHAR_BUFFER_HPP
#define BOOST_BEAST_CORE_DETAIL_CHAR_BUFFER_HPP
#include <boost/config.hpp>
#include <cstddef>
#include <cstring>
#include <cstdint>
namespace boost {
namespace beast {
namespace detail {
template <std::size_t N>
class char_buffer
{
public:
bool try_push_back(char c)
{
if (size_ == N)
return false;
buf_[size_++] = c;
return true;
}
bool try_append(char const* first, char const* last)
{
std::size_t const n = last - first;
if (n > N - size_)
return false;
std::memmove(&buf_[size_], first, n);
size_ += n;
return true;
}
void clear() noexcept
{
size_ = 0;
}
char* data() noexcept
{
return buf_;
}
char const* data() const noexcept
{
return buf_;
}
std::size_t size() const noexcept
{
return size_;
}
bool empty() const noexcept
{
return size_ == 0;
}
private:
std::size_t size_= 0;
char buf_[N];
};
} // detail
} // beast
} // boost
#endif
+59
View File
@@ -0,0 +1,59 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_CLAMP_HPP
#define BOOST_BEAST_CORE_DETAIL_CLAMP_HPP
#include <cstdlib>
#include <limits>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
template<class UInt>
static
std::size_t
clamp(UInt x)
{
if(x >= (std::numeric_limits<std::size_t>::max)())
return (std::numeric_limits<std::size_t>::max)();
return static_cast<std::size_t>(x);
}
template<class UInt>
static
std::size_t
clamp(UInt x, std::size_t limit)
{
if(x >= limit)
return limit;
return static_cast<std::size_t>(x);
}
// return `true` if x + y > z, which are unsigned
template<
class U1, class U2, class U3>
constexpr
bool
sum_exceeds(U1 x, U2 y, U3 z)
{
static_assert(
std::is_unsigned<U1>::value &&
std::is_unsigned<U2>::value &&
std::is_unsigned<U3>::value, "");
return y > z || x > z - y;
}
} // detail
} // beast
} // boost
#endif
+120
View File
@@ -0,0 +1,120 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_CONFIG_HPP
#define BOOST_BEAST_CORE_DETAIL_CONFIG_HPP
// Available to every header
#include <boost/config.hpp>
#include <boost/version.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/static_assert.hpp>
#include <boost/preprocessor/cat.hpp>
namespace boost {
namespace asio
{
} // asio
namespace beast {
namespace net = boost::asio;
} // beast
} // boost
/*
_MSC_VER and _MSC_FULL_VER by version:
14.0 (2015) 1900 190023026
14.0 (2015 Update 1) 1900 190023506
14.0 (2015 Update 2) 1900 190023918
14.0 (2015 Update 3) 1900 190024210
*/
#if defined(BOOST_MSVC)
# if BOOST_MSVC_FULL_VER < 190024210
# error Beast requires C++11: Visual Studio 2015 Update 3 or later needed
# endif
#elif defined(BOOST_GCC)
# if(BOOST_GCC < 50000)
# error Beast requires C++11: gcc version 5 or later needed
# endif
#else
# if \
defined(BOOST_NO_CXX11_DECLTYPE) || \
defined(BOOST_NO_CXX11_HDR_TUPLE) || \
defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || \
defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
# error Beast requires C++11: a conforming compiler is needed
# endif
#endif
#define BOOST_BEAST_DEPRECATION_STRING \
"This is a deprecated interface, #define BOOST_BEAST_ALLOW_DEPRECATED to allow it"
#ifndef BOOST_BEAST_ASSUME
# ifdef BOOST_GCC
# define BOOST_BEAST_ASSUME(cond) \
do { if (!(cond)) __builtin_unreachable(); } while (0)
# else
# define BOOST_BEAST_ASSUME(cond) do { } while(0)
# endif
#endif
// Default to a header-only implementation. The user must specifically
// request separate compilation by defining BOOST_BEAST_SEPARATE_COMPILATION
#ifndef BOOST_BEAST_HEADER_ONLY
# ifndef BOOST_BEAST_SEPARATE_COMPILATION
# define BOOST_BEAST_HEADER_ONLY 1
# endif
#endif
#if BOOST_BEAST_DOXYGEN
# define BOOST_BEAST_DECL
#elif defined(BOOST_BEAST_HEADER_ONLY)
# define BOOST_BEAST_DECL inline
#else
# define BOOST_BEAST_DECL
#endif
#ifndef BOOST_BEAST_ASYNC_RESULT1
#define BOOST_BEAST_ASYNC_RESULT1(type) \
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(type, void(::boost::beast::error_code))
#endif
#ifndef BOOST_BEAST_ASYNC_RESULT2
#define BOOST_BEAST_ASYNC_RESULT2(type) \
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(type, void(::boost::beast::error_code, ::std::size_t))
#endif
#ifndef BOOST_BEAST_ASYNC_TPARAM1
#define BOOST_BEAST_ASYNC_TPARAM1 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::beast::error_code))
#endif
#ifndef BOOST_BEAST_ASYNC_TPARAM2
#define BOOST_BEAST_ASYNC_TPARAM2 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::beast::error_code, ::std::size_t))
#endif
#ifdef BOOST_BEAST_NO_SOURCE_LOCATION
#define BOOST_BEAST_ASSIGN_EC(ec, error) ec = error
#else
#define BOOST_BEAST_ASSIGN_EC(ec, error) \
static constexpr auto BOOST_PP_CAT(loc_, __LINE__) ((BOOST_CURRENT_LOCATION)); \
ec.assign(error, & BOOST_PP_CAT(loc_, __LINE__) )
#endif
#ifndef BOOST_BEAST_FILE_BUFFER_SIZE
#define BOOST_BEAST_FILE_BUFFER_SIZE 4096
#endif
#endif
+99
View File
@@ -0,0 +1,99 @@
//
// Copyright (c) 2017 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_CPU_INFO_HPP
#define BOOST_BEAST_DETAIL_CPU_INFO_HPP
#include <boost/config.hpp>
#ifndef BOOST_BEAST_NO_INTRINSICS
# if defined(BOOST_MSVC) || ((defined(BOOST_GCC) || defined(BOOST_CLANG)) && defined(__SSE4_2__))
# define BOOST_BEAST_NO_INTRINSICS 0
# else
# define BOOST_BEAST_NO_INTRINSICS 1
# endif
#endif
#if ! BOOST_BEAST_NO_INTRINSICS
#ifdef BOOST_MSVC
#include <intrin.h> // __cpuid
#else
#include <cpuid.h> // __get_cpuid
#endif
namespace boost {
namespace beast {
namespace detail {
/* Portions from Boost,
Copyright Andrey Semashev 2007 - 2015.
*/
template<class = void>
void
cpuid(
std::uint32_t id,
std::uint32_t& eax,
std::uint32_t& ebx,
std::uint32_t& ecx,
std::uint32_t& edx)
{
#ifdef BOOST_MSVC
int regs[4];
__cpuid(regs, id);
eax = regs[0];
ebx = regs[1];
ecx = regs[2];
edx = regs[3];
#else
__get_cpuid(id, &eax, &ebx, &ecx, &edx);
#endif
}
struct cpu_info
{
bool sse42 = false;
cpu_info();
};
inline
cpu_info::
cpu_info()
{
constexpr std::uint32_t SSE42 = 1 << 20;
std::uint32_t eax = 0;
std::uint32_t ebx = 0;
std::uint32_t ecx = 0;
std::uint32_t edx = 0;
cpuid(0, eax, ebx, ecx, edx);
if(eax >= 1)
{
cpuid(1, eax, ebx, ecx, edx);
sse42 = (ecx & SSE42) != 0;
}
}
template<class = void>
cpu_info const&
get_cpu_info()
{
static cpu_info const ci;
return ci;
}
} // detail
} // beast
} // boost
#endif
#endif
@@ -0,0 +1,65 @@
//
// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
//
// 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)
//
#ifndef BOOST_BEAST_CORE_DETAIL_FILTERING_CANCELLATION_SLOT_HPP
#define BOOST_BEAST_CORE_DETAIL_FILTERING_CANCELLATION_SLOT_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/asio/cancellation_signal.hpp>
namespace boost {
namespace beast {
namespace detail {
template<typename CancellationSlot = net::cancellation_slot>
struct filtering_cancellation_slot : CancellationSlot
{
template<typename ... Args>
filtering_cancellation_slot(net::cancellation_type type, Args && ... args)
: CancellationSlot(std::forward<Args>(args)...), type(type) {}
net::cancellation_type type = net::cancellation_type::terminal;
using CancellationSlot::operator=;
template<typename Handler>
struct handler_wrapper
{
Handler handler;
const net::cancellation_type type;
template<typename ... Args>
handler_wrapper(net::cancellation_type type, Args && ... args)
: handler(std::forward<Args>(args)...),
type(type) {}
void operator()(net::cancellation_type tp)
{
if ((tp & type) != net::cancellation_type::none)
handler(tp);
}
};
template <typename CancellationHandler, typename ... Args>
CancellationHandler& emplace(Args && ... args)
{
return CancellationSlot::template emplace<handler_wrapper<CancellationHandler>>(
type, std::forward<Args>(args)...).handler;
}
template <typename CancellationHandler>
CancellationHandler& assign(CancellationHandler && ch)
{
return CancellationSlot::template emplace<handler_wrapper<CancellationHandler>>(
type, std::forward<CancellationHandler>(ch)).handler;
}
};
}
}
}
#endif //BOOST_BEAST_CORE_DETAIL_FILTERING_CANCELLATION_SLOT_HPP
+73
View File
@@ -0,0 +1,73 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_FLAT_STREAM_HPP
#define BOOST_BEAST_CORE_DETAIL_FLAT_STREAM_HPP
#include <boost/beast/core/buffer_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <cstdlib>
namespace boost {
namespace beast {
namespace detail {
class flat_stream_base
{
public:
// Largest buffer size we will flatten.
// 16KB is the upper limit on reasonably sized HTTP messages.
static std::size_t constexpr max_size = 16 * 1024;
// Largest stack we will use to flatten
static std::size_t constexpr max_stack = 8 * 1024;
struct flatten_result
{
std::size_t size;
bool flatten;
};
// calculates the flatten settings for a buffer sequence
template<class BufferSequence>
static
flatten_result
flatten(
BufferSequence const& buffers, std::size_t limit)
{
flatten_result result{0, false};
auto first = net::buffer_sequence_begin(buffers);
auto last = net::buffer_sequence_end(buffers);
if(first != last)
{
result.size = buffer_bytes(*first);
if(result.size < limit)
{
auto it = first;
auto prev = first;
while(++it != last)
{
auto const n = buffer_bytes(*it);
if(result.size + n > limit)
break;
result.size += n;
prev = it;
}
result.flatten = prev != first;
}
}
return result;
}
};
} // detail
} // beast
} // boost
#endif
+109
View File
@@ -0,0 +1,109 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_GET_IO_CONTEXT_HPP
#define BOOST_BEAST_DETAIL_GET_IO_CONTEXT_HPP
#include <boost/beast/core/stream_traits.hpp>
#ifdef BOOST_ASIO_NO_TS_EXECUTORS
#include <boost/asio/execution.hpp>
#endif
#include <boost/asio/executor.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/strand.hpp>
#include <memory>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
//------------------------------------------------------------------------------
inline
net::io_context*
get_io_context(net::io_context& ioc)
{
return std::addressof(ioc);
}
inline
net::io_context*
get_io_context(net::io_context::executor_type const& ex)
{
return std::addressof(net::query(ex, net::execution::context));
}
inline
net::io_context*
get_io_context(net::strand<
net::io_context::executor_type> const& ex)
{
return get_io_context(ex.get_inner_executor());
}
template<class Executor>
net::io_context*
get_io_context(net::strand<Executor> const& ex)
{
return get_io_context(ex.get_inner_executor());
}
template<
class T,
class = typename std::enable_if<
std::is_same<T, net::executor>::value || std::is_same<T, net::any_io_executor>::value>::type>
net::io_context*
get_io_context(T const& ex)
{
auto p = ex.template target<typename
net::io_context::executor_type>();
if(! p)
return nullptr;
return get_io_context(*p);
}
inline
net::io_context*
get_io_context(...)
{
return nullptr;
}
//------------------------------------------------------------------------------
template<class T>
net::io_context*
get_io_context_impl(T& t, std::true_type)
{
return get_io_context(
t.get_executor());
}
template<class T>
net::io_context*
get_io_context_impl(T const&, std::false_type)
{
return nullptr;
}
// Returns the io_context*, or nullptr, for any object.
template<class T>
net::io_context*
get_io_context(T& t)
{
return get_io_context_impl(t,
has_get_executor<T>{});
}
} // detail
} // beast
} // boost
#endif
+249
View File
@@ -0,0 +1,249 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_IMPL_READ_HPP
#define BOOST_BEAST_DETAIL_IMPL_READ_HPP
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/async_base.hpp>
#include <boost/beast/core/flat_static_buffer.hpp>
#include <boost/beast/core/read_size.hpp>
#include <boost/asio/basic_stream_socket.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/throw_exception.hpp>
namespace boost {
namespace beast {
namespace detail {
// The number of bytes in the stack buffer when using non-blocking.
static std::size_t constexpr default_max_stack_buffer = 16384;
//------------------------------------------------------------------------------
struct dynamic_read_ops
{
// read into a dynamic buffer until the
// condition is met or an error occurs
template<
class Stream,
class DynamicBuffer,
class Condition,
class Handler>
class read_op
: public asio::coroutine
, public async_base<
Handler, beast::executor_type<Stream>>
{
Stream& s_;
DynamicBuffer& b_;
Condition cond_;
error_code ec_;
std::size_t total_ = 0;
public:
read_op(read_op&&) = default;
template<class Handler_, class Condition_>
read_op(
Handler_&& h,
Stream& s,
DynamicBuffer& b,
Condition_&& cond)
: async_base<Handler,
beast::executor_type<Stream>>(
std::forward<Handler_>(h),
s.get_executor())
, s_(s)
, b_(b)
, cond_(std::forward<Condition_>(cond))
{
(*this)({}, 0, false);
}
void
operator()(
error_code ec,
std::size_t bytes_transferred,
bool cont = true)
{
std::size_t max_prepare;
BOOST_ASIO_CORO_REENTER(*this)
{
for(;;)
{
max_prepare = beast::read_size(b_, cond_(ec, total_, b_));
if(max_prepare == 0)
break;
BOOST_ASIO_CORO_YIELD
s_.async_read_some(
b_.prepare(max_prepare), std::move(*this));
b_.commit(bytes_transferred);
total_ += bytes_transferred;
}
if(! cont)
{
// run this handler "as-if" using net::post
// to reduce template instantiations
ec_ = ec;
BOOST_ASIO_CORO_YIELD
s_.async_read_some(
b_.prepare(0), std::move(*this));
BOOST_BEAST_ASSIGN_EC(ec, ec_);
}
this->complete_now(ec, total_);
}
}
};
//------------------------------------------------------------------------------
struct run_read_op
{
template<
class AsyncReadStream,
class DynamicBuffer,
class Condition,
class ReadHandler>
void
operator()(
ReadHandler&& h,
AsyncReadStream* s,
DynamicBuffer* b,
Condition&& c)
{
// If you get an error on the following line it means
// that your handler does not meet the documented type
// requirements for the handler.
static_assert(
beast::detail::is_invocable<ReadHandler,
void(error_code, std::size_t)>::value,
"ReadHandler type requirements not met");
read_op<
AsyncReadStream,
DynamicBuffer,
typename std::decay<Condition>::type,
typename std::decay<ReadHandler>::type>(
std::forward<ReadHandler>(h),
*s,
*b,
std::forward<Condition>(c));
}
};
};
//------------------------------------------------------------------------------
template<
class SyncReadStream,
class DynamicBuffer,
class CompletionCondition,
class>
std::size_t
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
CompletionCondition cond)
{
static_assert(is_sync_read_stream<SyncReadStream>::value,
"SyncReadStream type requirements not met");
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
static_assert(
detail::is_invocable<CompletionCondition,
void(error_code&, std::size_t, DynamicBuffer&)>::value,
"CompletionCondition type requirements not met");
error_code ec;
auto const bytes_transferred = detail::read(
stream, buffer, std::move(cond), ec);
if(ec)
BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_transferred;
}
template<
class SyncReadStream,
class DynamicBuffer,
class CompletionCondition,
class>
std::size_t
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
CompletionCondition cond,
error_code& ec)
{
static_assert(is_sync_read_stream<SyncReadStream>::value,
"SyncReadStream type requirements not met");
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
static_assert(
detail::is_invocable<CompletionCondition,
void(error_code&, std::size_t, DynamicBuffer&)>::value,
"CompletionCondition type requirements not met");
ec = {};
std::size_t total = 0;
std::size_t max_prepare;
for(;;)
{
max_prepare = beast::read_size(buffer, cond(ec, total, buffer));
if(max_prepare == 0)
break;
std::size_t const bytes_transferred =
stream.read_some(buffer.prepare(max_prepare), ec);
buffer.commit(bytes_transferred);
total += bytes_transferred;
}
return total;
}
template<
class AsyncReadStream,
class DynamicBuffer,
class CompletionCondition,
BOOST_BEAST_ASYNC_TPARAM2 ReadHandler,
class>
BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
async_read(
AsyncReadStream& stream,
DynamicBuffer& buffer,
CompletionCondition&& cond,
ReadHandler&& handler)
{
static_assert(is_async_read_stream<AsyncReadStream>::value,
"AsyncReadStream type requirements not met");
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
static_assert(
detail::is_invocable<CompletionCondition,
void(error_code&, std::size_t, DynamicBuffer&)>::value,
"CompletionCondition type requirements not met");
return net::async_initiate<
ReadHandler,
void(error_code, std::size_t)>(
typename dynamic_read_ops::run_read_op{},
handler,
&stream,
&buffer,
std::forward<CompletionCondition>(cond));
}
} // detail
} // beast
} // boost
#endif
+69
View File
@@ -0,0 +1,69 @@
//
// Copyright (c) 2019 Damian Jarek(damian.jarek93@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/beast
//
#ifndef BOOST_BEAST_DETAIL_IMPL_TEMPORARY_BUFFER_IPP
#define BOOST_BEAST_DETAIL_IMPL_TEMPORARY_BUFFER_IPP
#include <boost/beast/core/detail/temporary_buffer.hpp>
#include <boost/beast/core/detail/clamp.hpp>
#include <boost/core/exchange.hpp>
#include <boost/assert.hpp>
#include <memory>
#include <cstring>
namespace boost {
namespace beast {
namespace detail {
void
temporary_buffer::
append(string_view s)
{
grow(s.size());
unchecked_append(s);
}
void
temporary_buffer::
append(string_view s1, string_view s2)
{
grow(s1.size() + s2.size());
unchecked_append(s1);
unchecked_append(s2);
}
void
temporary_buffer::
unchecked_append(string_view s)
{
auto n = s.size();
std::memcpy(&data_[size_], s.data(), n);
size_ += n;
}
void
temporary_buffer::
grow(std::size_t n)
{
if (capacity_ - size_ >= n)
return;
auto const capacity = (n + size_) * 2u;
BOOST_ASSERT(! detail::sum_exceeds(
n, size_, capacity));
char* const p = new char[capacity];
std::memcpy(p, data_, size_);
deallocate(boost::exchange(data_, p));
capacity_ = capacity;
}
} // detail
} // beast
} // boost
#endif
+80
View File
@@ -0,0 +1,80 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_IS_INVOCABLE_HPP
#define BOOST_BEAST_DETAIL_IS_INVOCABLE_HPP
#include <boost/asio/async_result.hpp>
#include <boost/type_traits/make_void.hpp>
#include <type_traits>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
template<class R, class C, class ...A>
auto
is_invocable_test(C&& c, int, A&& ...a)
-> decltype(std::is_convertible<
decltype(c(std::forward<A>(a)...)), R>::value ||
std::is_same<R, void>::value,
std::true_type());
template<class R, class C, class ...A>
std::false_type
is_invocable_test(C&& c, long, A&& ...a);
/** Metafunction returns `true` if F callable as R(A...)
Example:
@code
is_invocable<T, void(std::string)>::value
@endcode
*/
/** @{ */
template<class C, class F>
struct is_invocable : std::false_type
{
};
template<class C, class R, class ...A>
struct is_invocable<C, R(A...)>
: decltype(is_invocable_test<R>(
std::declval<C>(), 1, std::declval<A>()...))
{
};
/** @} */
template<class CompletionToken, class Signature, class = void>
struct is_completion_token_for : std::false_type
{
};
struct any_initiation
{
template<class...AnyArgs>
void operator()(AnyArgs&&...);
};
template<class CompletionToken, class R, class...Args>
struct is_completion_token_for<
CompletionToken, R(Args...), boost::void_t<decltype(
boost::asio::async_initiate<CompletionToken, R(Args...)>(
any_initiation(), std::declval<CompletionToken&>())
)>> : std::true_type
{
};
} // detail
} // beast
} // boost
#endif
+267
View File
@@ -0,0 +1,267 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
#define BOOST_BEAST_DETAIL_OSTREAM_HPP
#include <boost/beast/core/buffers_prefix.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/throw_exception.hpp>
#include <boost/asio/buffer.hpp>
#include <memory>
#include <ostream>
#include <streambuf>
#include <type_traits>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
struct basic_streambuf_movable_helper :
std::basic_streambuf<char, std::char_traits<char>>
{
basic_streambuf_movable_helper(
basic_streambuf_movable_helper&&) = default;
};
using basic_streambuf_movable =
std::is_move_constructible<basic_streambuf_movable_helper>;
template<class DynamicBuffer,
class CharT, class Traits, bool isMovable>
class ostream_buffer;
//------------------------------------------------------------------------------
template<class DynamicBuffer, class CharT, class Traits>
class ostream_buffer
<DynamicBuffer, CharT, Traits, true> final
: public std::basic_streambuf<CharT, Traits>
{
using int_type = typename
std::basic_streambuf<CharT, Traits>::int_type;
using traits_type = typename
std::basic_streambuf<CharT, Traits>::traits_type;
DynamicBuffer& b_;
public:
ostream_buffer(ostream_buffer&&) = default;
ostream_buffer(ostream_buffer const&) = delete;
~ostream_buffer() noexcept
{
sync();
}
explicit
ostream_buffer(DynamicBuffer& b)
: b_(b)
{
b_.prepare(0);
}
int_type
overflow(int_type ch) override
{
BOOST_ASSERT(! Traits::eq_int_type(
ch, Traits::eof()));
sync();
static std::size_t constexpr max_size = 65536;
auto const max_prepare = std::min<std::size_t>(
std::max<std::size_t>(
512, b_.capacity() - b_.size()),
std::min<std::size_t>(
max_size, b_.max_size() - b_.size()));
if(max_prepare == 0)
return Traits::eof();
auto const bs = b_.prepare(max_prepare);
auto const b = buffers_front(bs);
auto const p = static_cast<CharT*>(b.data());
this->setp(p, p + b.size() / sizeof(CharT));
BOOST_ASSERT(b_.capacity() > b_.size());
return this->sputc(
Traits::to_char_type(ch));
}
int
sync() override
{
b_.commit(
(this->pptr() - this->pbase()) *
sizeof(CharT));
this->setp(nullptr, nullptr);
return 0;
}
};
//------------------------------------------------------------------------------
// This nonsense is all to work around a glitch in libstdc++
// where std::basic_streambuf copy constructor is private:
// https://github.com/gcc-mirror/gcc/blob/gcc-4_8-branch/libstdc%2B%2B-v3/include/std/streambuf#L799
template<class DynamicBuffer, class CharT, class Traits>
class ostream_buffer
<DynamicBuffer, CharT, Traits, false>
: public std::basic_streambuf<CharT, Traits>
{
using int_type = typename
std::basic_streambuf<CharT, Traits>::int_type;
using traits_type = typename
std::basic_streambuf<CharT, Traits>::traits_type;
DynamicBuffer& b_;
public:
ostream_buffer(ostream_buffer&&) = delete;
ostream_buffer(ostream_buffer const&) = delete;
~ostream_buffer() noexcept
{
sync();
}
explicit
ostream_buffer(DynamicBuffer& b)
: b_(b)
{
}
int_type
overflow(int_type ch) override
{
BOOST_ASSERT(! Traits::eq_int_type(
ch, Traits::eof()));
sync();
static std::size_t constexpr max_size = 65536;
auto const max_prepare = std::min<std::size_t>(
std::max<std::size_t>(
512, b_.capacity() - b_.size()),
std::min<std::size_t>(
max_size, b_.max_size() - b_.size()));
if(max_prepare == 0)
return Traits::eof();
auto const bs = b_.prepare(max_prepare);
auto const b = buffers_front(bs);
auto const p = static_cast<CharT*>(b.data());
this->setp(p, p + b.size() / sizeof(CharT));
BOOST_ASSERT(b_.capacity() > b_.size());
return this->sputc(
Traits::to_char_type(ch));
}
int
sync() override
{
b_.commit(
(this->pptr() - this->pbase()) *
sizeof(CharT));
this->setp(nullptr, nullptr);
return 0;
}
};
//------------------------------------------------------------------------------
template<class DynamicBuffer,
class CharT, class Traits, bool isMovable>
class ostream_helper;
template<class DynamicBuffer, class CharT, class Traits>
class ostream_helper<
DynamicBuffer, CharT, Traits, true>
: public std::basic_ostream<CharT, Traits>
{
ostream_buffer<
DynamicBuffer, CharT, Traits, true> osb_;
public:
explicit
ostream_helper(DynamicBuffer& b);
ostream_helper(ostream_helper&& other);
};
template<class DynamicBuffer, class CharT, class Traits>
ostream_helper<DynamicBuffer, CharT, Traits, true>::
ostream_helper(DynamicBuffer& b)
: std::basic_ostream<CharT, Traits>(&this->osb_)
, osb_(b)
{
}
template<class DynamicBuffer, class CharT, class Traits>
ostream_helper<DynamicBuffer, CharT, Traits, true>::
ostream_helper(ostream_helper&& other)
: std::basic_ostream<CharT, Traits>(&osb_)
, osb_(std::move(other.osb_))
{
}
// This work-around is for libstdc++ versions that
// don't have a movable std::basic_streambuf
template<class T>
class ostream_helper_base
{
protected:
std::unique_ptr<T> member;
ostream_helper_base(
ostream_helper_base&&) = default;
explicit
ostream_helper_base(T* t)
: member(t)
{
}
};
template<class DynamicBuffer, class CharT, class Traits>
class ostream_helper<
DynamicBuffer, CharT, Traits, false>
: private ostream_helper_base<ostream_buffer<
DynamicBuffer, CharT, Traits, false>>
, public std::basic_ostream<CharT, Traits>
{
public:
explicit
ostream_helper(DynamicBuffer& b)
: ostream_helper_base<ostream_buffer<
DynamicBuffer, CharT, Traits, false>>(
new ostream_buffer<DynamicBuffer,
CharT, Traits, false>(b))
, std::basic_ostream<CharT, Traits>(
this->member.get())
{
}
ostream_helper(ostream_helper&& other)
: ostream_helper_base<ostream_buffer<
DynamicBuffer, CharT, Traits, false>>(
std::move(other))
, std::basic_ostream<CharT, Traits>(
this->member.get())
{
}
};
} // detail
} // beast
} // boost
#endif
+65
View File
@@ -0,0 +1,65 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_PCG_HPP
#define BOOST_BEAST_CORE_DETAIL_PCG_HPP
#include <boost/core/ignore_unused.hpp>
#include <cstdint>
#include <random>
namespace boost {
namespace beast {
namespace detail {
class pcg
{
std::uint64_t state_ = 0;
std::uint64_t increment_;
public:
using result_type = std::uint32_t;
// Initialize the generator.
// There are no restrictions on the input values.
pcg(
std::uint64_t seed,
std::uint64_t stream)
{
// increment must be odd
increment_ = 2 * stream + 1;
boost::ignore_unused((*this)());
state_ += seed;
boost::ignore_unused((*this)());
}
std::uint32_t
operator()()
{
std::uint64_t const p = state_;
state_ = p *
6364136223846793005ULL +
increment_;
std::uint32_t const x =
static_cast<std::uint32_t>(
((p >> 18) ^ p) >> 27);
std::uint32_t const r = p >> 59;
#ifdef BOOST_MSVC
return _rotr(x, r);
#else
return (x >> r) | (x << ((1 + ~r) & 31));
#endif
}
};
} // detail
} // beast
} // boost
#endif
+246
View File
@@ -0,0 +1,246 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_READ_HPP
#define BOOST_BEAST_DETAIL_READ_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/core/detail/is_invocable.hpp>
#include <boost/asio/async_result.hpp>
#include <cstdlib>
namespace boost {
namespace beast {
namespace detail {
//------------------------------------------------------------------------------
/** Read data into a dynamic buffer from a stream until a condition is met.
This function is used to read from a stream into a dynamic buffer until
a condition is met. The call will block until one of the following is true:
@li The specified dynamic buffer sequence is full (that is, it has
reached its currently configured maximum size).
@li The `completion_condition` function object returns 0.
This operation is implemented in terms of zero or more calls to the
stream's `read_some` function.
@param stream The stream from which the data is to be read. The type
must support the <em>SyncReadStream</em> requirements.
@param buffer The dynamic buffer sequence into which the data will be read.
@param completion_condition The function object to be called to determine
whether the read operation is complete. The function object must be invocable
with this signature:
@code
std::size_t
completion_condition(
// Modifiable result of latest read_some operation.
error_code& ec,
// Number of bytes transferred so far.
std::size_t bytes_transferred
// The dynamic buffer used to store the bytes read
DynamicBuffer& buffer
);
@endcode
A non-zero return value indicates the maximum number of bytes to be read on
the next call to the stream's `read_some` function. A return value of 0
from the completion condition indicates that the read operation is complete;
in this case the optionally modifiable error passed to the completion
condition will be delivered to the caller as an exception.
@returns The number of bytes transferred from the stream.
@throws net::system_error Thrown on failure.
*/
template<
class SyncReadStream,
class DynamicBuffer,
class CompletionCondition
#if ! BOOST_BEAST_DOXYGEN
, class = typename std::enable_if<
is_sync_read_stream<SyncReadStream>::value &&
net::is_dynamic_buffer<DynamicBuffer>::value &&
detail::is_invocable<CompletionCondition,
void(error_code&, std::size_t, DynamicBuffer&)>::value
>::type
#endif
>
std::size_t
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
CompletionCondition completion_condition);
/** Read data into a dynamic buffer from a stream until a condition is met.
This function is used to read from a stream into a dynamic buffer until
a condition is met. The call will block until one of the following is true:
@li The specified dynamic buffer sequence is full (that is, it has
reached its currently configured maximum size).
@li The `completion_condition` function object returns 0.
This operation is implemented in terms of zero or more calls to the
stream's `read_some` function.
@param stream The stream from which the data is to be read. The type
must support the <em>SyncReadStream</em> requirements.
@param buffer The dynamic buffer sequence into which the data will be read.
@param completion_condition The function object to be called to determine
whether the read operation is complete. The function object must be invocable
with this signature:
@code
std::size_t
completion_condition(
// Modifiable result of latest read_some operation.
error_code& ec,
// Number of bytes transferred so far.
std::size_t bytes_transferred
// The dynamic buffer used to store the bytes read
DynamicBuffer& buffer
);
@endcode
A non-zero return value indicates the maximum number of bytes to be read on
the next call to the stream's `read_some` function. A return value of 0
from the completion condition indicates that the read operation is complete;
in this case the optionally modifiable error passed to the completion
condition will be delivered to the caller.
@returns The number of bytes transferred from the stream.
*/
template<
class SyncReadStream,
class DynamicBuffer,
class CompletionCondition
#if ! BOOST_BEAST_DOXYGEN
, class = typename std::enable_if<
is_sync_read_stream<SyncReadStream>::value &&
net::is_dynamic_buffer<DynamicBuffer>::value &&
detail::is_invocable<CompletionCondition,
void(error_code&, std::size_t, DynamicBuffer&)>::value
>::type
#endif
>
std::size_t
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
CompletionCondition completion_condition,
error_code& ec);
/** Asynchronously read data into a dynamic buffer from a stream until a condition is met.
This function is used to asynchronously read from a stream into a dynamic
buffer until a condition is met. The function call always returns immediately.
The asynchronous operation will continue until one of the following is true:
@li The specified dynamic buffer sequence is full (that is, it has
reached its currently configured maximum size).
@li The `completion_condition` function object returns 0.
This operation is implemented in terms of zero or more calls to the stream's
`async_read_some` function, and is known as a <em>composed operation</em>. The
program must ensure that the stream performs no other read operations (such
as `async_read`, the stream's `async_read_some` function, or any other composed
operations that perform reads) until this operation completes.
@param stream The stream from which the data is to be read. The type must
support the <em>AsyncReadStream</em> requirements.
@param buffer The dynamic buffer sequence into which the data will be read.
Ownership of the object is retained by the caller, which must guarantee
that it remains valid until the handler is called.
@param completion_condition The function object to be called to determine
whether the read operation is complete. The function object must be invocable
with this signature:
@code
std::size_t
completion_condition(
// Modifiable result of latest async_read_some operation.
error_code& ec,
// Number of bytes transferred so far.
std::size_t bytes_transferred,
// The dynamic buffer used to store the bytes read
DynamicBuffer& buffer
);
@endcode
A non-zero return value indicates the maximum number of bytes to be read on
the next call to the stream's `async_read_some` function. A return value of 0
from the completion condition indicates that the read operation is complete;
in this case the optionally modifiable error passed to the completion
condition will be delivered to the completion handler.
@param handler The completion handler to invoke when the operation
completes. The implementation takes ownership of the handler by
performing a decay-copy. The equivalent function signature of
the handler must be:
@code
void
handler(
error_code const& ec, // Result of operation.
std::size_t bytes_transferred // Number of bytes copied into
// the dynamic buffer. If an error
// occurred, this will be the number
// of bytes successfully transferred
// prior to the error.
);
@endcode
If the handler has an associated immediate executor,
an immediate completion will be dispatched to it.
Otherwise, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
*/
template<
class AsyncReadStream,
class DynamicBuffer,
class CompletionCondition,
BOOST_BEAST_ASYNC_TPARAM2 ReadHandler
#if ! BOOST_BEAST_DOXYGEN
, class = typename std::enable_if<
is_async_read_stream<AsyncReadStream>::value &&
net::is_dynamic_buffer<DynamicBuffer>::value &&
detail::is_invocable<CompletionCondition,
void(error_code&, std::size_t, DynamicBuffer&)>::value
>::type
#endif
>
BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
async_read(
AsyncReadStream& stream,
DynamicBuffer& buffer,
CompletionCondition&& completion_condition,
ReadHandler&& handler);
} // detail
} // beast
} // boost
#include <boost/beast/core/detail/impl/read.hpp>
#endif
+108
View File
@@ -0,0 +1,108 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_REMAP_POST_TO_DEFER_HPP
#define BOOST_BEAST_DETAIL_REMAP_POST_TO_DEFER_HPP
#include <boost/asio/is_executor.hpp>
#include <boost/core/empty_value.hpp>
#include <type_traits>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
template<class Executor>
class remap_post_to_defer
: private boost::empty_value<Executor>
{
BOOST_STATIC_ASSERT(
net::is_executor<Executor>::value);
Executor const&
ex() const noexcept
{
return this->get();
}
public:
remap_post_to_defer(
remap_post_to_defer&&) = default;
remap_post_to_defer(
remap_post_to_defer const&) = default;
explicit
remap_post_to_defer(
Executor const& ex)
: boost::empty_value<Executor>(
boost::empty_init_t{}, ex)
{
}
bool
operator==(
remap_post_to_defer const& other) const noexcept
{
return ex() == other.ex();
}
bool
operator!=(
remap_post_to_defer const& other) const noexcept
{
return ex() != other.ex();
}
decltype(std::declval<Executor const&>().context())
context() const noexcept
{
return ex().context();
}
void
on_work_started() const noexcept
{
ex().on_work_started();
}
void
on_work_finished() const noexcept
{
ex().on_work_finished();
}
template<class F, class A>
void
dispatch(F&& f, A const& a) const
{
ex().dispatch(std::forward<F>(f), a);
}
template<class F, class A>
void
post(F&& f, A const& a) const
{
ex().defer(std::forward<F>(f), a);
}
template<class F, class A>
void
defer(F&& f, A const& a) const
{
ex().defer(std::forward<F>(f), a);
}
};
} // detail
} // beast
} // boost
#endif
+38
View File
@@ -0,0 +1,38 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_SERVICE_BASE_HPP
#define BOOST_BEAST_DETAIL_SERVICE_BASE_HPP
#include <boost/asio/execution_context.hpp>
namespace boost {
namespace beast {
namespace detail {
template<class T>
struct service_base : net::execution_context::service
{
static net::execution_context::id const id;
explicit
service_base(net::execution_context& ctx)
: net::execution_context::service(ctx)
{
}
};
template<class T>
net::execution_context::id const service_base<T>::id;
} // detail
} // beast
} // boost
#endif
+75
View File
@@ -0,0 +1,75 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_SHA1_HPP
#define BOOST_BEAST_DETAIL_SHA1_HPP
#include <boost/beast/core/detail/config.hpp>
#include <cstdint>
#include <cstddef>
// Based on https://github.com/vog/sha1
/*
Original authors:
Steve Reid (Original C Code)
Bruce Guenter (Small changes to fit into bglibs)
Volker Grabsch (Translation to simpler C++ Code)
Eugene Hopkinson (Safety improvements)
Vincent Falco (beast adaptation)
*/
namespace boost {
namespace beast {
namespace detail {
namespace sha1 {
static std::size_t constexpr BLOCK_INTS = 16;
static std::size_t constexpr BLOCK_BYTES = 64;
static std::size_t constexpr DIGEST_BYTES = 20;
} // sha1
struct sha1_context
{
static unsigned int constexpr block_size = sha1::BLOCK_BYTES;
static unsigned int constexpr digest_size = 20;
std::size_t buflen;
std::size_t blocks;
std::uint32_t digest[5];
std::uint8_t buf[block_size];
};
BOOST_BEAST_DECL
void
init(sha1_context& ctx) noexcept;
BOOST_BEAST_DECL
void
update(
sha1_context& ctx,
void const* message,
std::size_t size) noexcept;
BOOST_BEAST_DECL
void
finish(
sha1_context& ctx,
void* digest) noexcept;
} // detail
} // beast
} // boost
#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/core/detail/sha1.ipp>
#endif
#endif
+301
View File
@@ -0,0 +1,301 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_SHA1_IPP
#define BOOST_BEAST_DETAIL_SHA1_IPP
#include <boost/beast/core/detail/sha1.hpp>
#include <algorithm>
#include <cstdint>
#include <cstring>
// Based on https://github.com/vog/sha1
/*
Original authors:
Steve Reid (Original C Code)
Bruce Guenter (Small changes to fit into bglibs)
Volker Grabsch (Translation to simpler C++ Code)
Eugene Hopkinson (Safety improvements)
Vincent Falco (beast adaptation)
*/
namespace boost {
namespace beast {
namespace detail {
namespace sha1 {
inline
std::uint32_t
rol(std::uint32_t value, std::size_t bits)
{
return (value << bits) | (value >> (32 - bits));
}
inline
std::uint32_t
blk(std::uint32_t block[BLOCK_INTS], std::size_t i)
{
return rol(
block[(i+13)&15] ^ block[(i+8)&15] ^
block[(i+2)&15] ^ block[i], 1);
}
inline
void
R0(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
std::uint32_t &w, std::uint32_t x, std::uint32_t y,
std::uint32_t &z, std::size_t i)
{
z += ((w&(x^y))^y) + block[i] + 0x5a827999 + rol(v, 5);
w = rol(w, 30);
}
inline
void
R1(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
std::uint32_t &w, std::uint32_t x, std::uint32_t y,
std::uint32_t &z, std::size_t i)
{
block[i] = blk(block, i);
z += ((w&(x^y))^y) + block[i] + 0x5a827999 + rol(v, 5);
w = rol(w, 30);
}
inline
void
R2(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
std::uint32_t &w, std::uint32_t x, std::uint32_t y,
std::uint32_t &z, std::size_t i)
{
block[i] = blk(block, i);
z += (w^x^y) + block[i] + 0x6ed9eba1 + rol(v, 5);
w = rol(w, 30);
}
inline
void
R3(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
std::uint32_t &w, std::uint32_t x, std::uint32_t y,
std::uint32_t &z, std::size_t i)
{
block[i] = blk(block, i);
z += (((w|x)&y)|(w&x)) + block[i] + 0x8f1bbcdc + rol(v, 5);
w = rol(w, 30);
}
inline
void
R4(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
std::uint32_t &w, std::uint32_t x, std::uint32_t y,
std::uint32_t &z, std::size_t i)
{
block[i] = blk(block, i);
z += (w^x^y) + block[i] + 0xca62c1d6 + rol(v, 5);
w = rol(w, 30);
}
inline
void
make_block(std::uint8_t const* p,
std::uint32_t block[BLOCK_INTS])
{
for(std::size_t i = 0; i < BLOCK_INTS; i++)
block[i] =
(static_cast<std::uint32_t>(p[4*i+3])) |
(static_cast<std::uint32_t>(p[4*i+2]))<< 8 |
(static_cast<std::uint32_t>(p[4*i+1]))<<16 |
(static_cast<std::uint32_t>(p[4*i+0]))<<24;
}
inline
void
transform(
std::uint32_t digest[], std::uint32_t block[BLOCK_INTS])
{
std::uint32_t a = digest[0];
std::uint32_t b = digest[1];
std::uint32_t c = digest[2];
std::uint32_t d = digest[3];
std::uint32_t e = digest[4];
R0(block, a, b, c, d, e, 0);
R0(block, e, a, b, c, d, 1);
R0(block, d, e, a, b, c, 2);
R0(block, c, d, e, a, b, 3);
R0(block, b, c, d, e, a, 4);
R0(block, a, b, c, d, e, 5);
R0(block, e, a, b, c, d, 6);
R0(block, d, e, a, b, c, 7);
R0(block, c, d, e, a, b, 8);
R0(block, b, c, d, e, a, 9);
R0(block, a, b, c, d, e, 10);
R0(block, e, a, b, c, d, 11);
R0(block, d, e, a, b, c, 12);
R0(block, c, d, e, a, b, 13);
R0(block, b, c, d, e, a, 14);
R0(block, a, b, c, d, e, 15);
R1(block, e, a, b, c, d, 0);
R1(block, d, e, a, b, c, 1);
R1(block, c, d, e, a, b, 2);
R1(block, b, c, d, e, a, 3);
R2(block, a, b, c, d, e, 4);
R2(block, e, a, b, c, d, 5);
R2(block, d, e, a, b, c, 6);
R2(block, c, d, e, a, b, 7);
R2(block, b, c, d, e, a, 8);
R2(block, a, b, c, d, e, 9);
R2(block, e, a, b, c, d, 10);
R2(block, d, e, a, b, c, 11);
R2(block, c, d, e, a, b, 12);
R2(block, b, c, d, e, a, 13);
R2(block, a, b, c, d, e, 14);
R2(block, e, a, b, c, d, 15);
R2(block, d, e, a, b, c, 0);
R2(block, c, d, e, a, b, 1);
R2(block, b, c, d, e, a, 2);
R2(block, a, b, c, d, e, 3);
R2(block, e, a, b, c, d, 4);
R2(block, d, e, a, b, c, 5);
R2(block, c, d, e, a, b, 6);
R2(block, b, c, d, e, a, 7);
R3(block, a, b, c, d, e, 8);
R3(block, e, a, b, c, d, 9);
R3(block, d, e, a, b, c, 10);
R3(block, c, d, e, a, b, 11);
R3(block, b, c, d, e, a, 12);
R3(block, a, b, c, d, e, 13);
R3(block, e, a, b, c, d, 14);
R3(block, d, e, a, b, c, 15);
R3(block, c, d, e, a, b, 0);
R3(block, b, c, d, e, a, 1);
R3(block, a, b, c, d, e, 2);
R3(block, e, a, b, c, d, 3);
R3(block, d, e, a, b, c, 4);
R3(block, c, d, e, a, b, 5);
R3(block, b, c, d, e, a, 6);
R3(block, a, b, c, d, e, 7);
R3(block, e, a, b, c, d, 8);
R3(block, d, e, a, b, c, 9);
R3(block, c, d, e, a, b, 10);
R3(block, b, c, d, e, a, 11);
R4(block, a, b, c, d, e, 12);
R4(block, e, a, b, c, d, 13);
R4(block, d, e, a, b, c, 14);
R4(block, c, d, e, a, b, 15);
R4(block, b, c, d, e, a, 0);
R4(block, a, b, c, d, e, 1);
R4(block, e, a, b, c, d, 2);
R4(block, d, e, a, b, c, 3);
R4(block, c, d, e, a, b, 4);
R4(block, b, c, d, e, a, 5);
R4(block, a, b, c, d, e, 6);
R4(block, e, a, b, c, d, 7);
R4(block, d, e, a, b, c, 8);
R4(block, c, d, e, a, b, 9);
R4(block, b, c, d, e, a, 10);
R4(block, a, b, c, d, e, 11);
R4(block, e, a, b, c, d, 12);
R4(block, d, e, a, b, c, 13);
R4(block, c, d, e, a, b, 14);
R4(block, b, c, d, e, a, 15);
digest[0] += a;
digest[1] += b;
digest[2] += c;
digest[3] += d;
digest[4] += e;
}
} // sha1
void
init(sha1_context& ctx) noexcept
{
ctx.buflen = 0;
ctx.blocks = 0;
ctx.digest[0] = 0x67452301;
ctx.digest[1] = 0xefcdab89;
ctx.digest[2] = 0x98badcfe;
ctx.digest[3] = 0x10325476;
ctx.digest[4] = 0xc3d2e1f0;
}
void
update(
sha1_context& ctx,
void const* message,
std::size_t size) noexcept
{
auto p = static_cast<
std::uint8_t const*>(message);
for(;;)
{
auto const n = (std::min)(
size, sizeof(ctx.buf) - ctx.buflen);
std::memcpy(ctx.buf + ctx.buflen, p, n);
ctx.buflen += n;
if(ctx.buflen != 64)
return;
p += n;
size -= n;
ctx.buflen = 0;
std::uint32_t block[sha1::BLOCK_INTS];
sha1::make_block(ctx.buf, block);
sha1::transform(ctx.digest, block);
++ctx.blocks;
}
}
void
finish(
sha1_context& ctx,
void* digest) noexcept
{
using sha1::BLOCK_INTS;
using sha1::BLOCK_BYTES;
std::uint64_t total_bits =
(ctx.blocks*64 + ctx.buflen) * 8;
// pad
ctx.buf[ctx.buflen++] = 0x80;
auto const buflen = ctx.buflen;
while(ctx.buflen < 64)
ctx.buf[ctx.buflen++] = 0x00;
std::uint32_t block[BLOCK_INTS];
sha1::make_block(ctx.buf, block);
if(buflen > BLOCK_BYTES - 8)
{
sha1::transform(ctx.digest, block);
for(size_t i = 0; i < BLOCK_INTS - 2; i++)
block[i] = 0;
}
/* Append total_bits, split this uint64_t into two uint32_t */
block[BLOCK_INTS - 1] = total_bits & 0xffffffff;
block[BLOCK_INTS - 2] = (total_bits >> 32);
sha1::transform(ctx.digest, block);
for(std::size_t i = 0; i < sha1::DIGEST_BYTES/4; i++)
{
std::uint8_t* d =
static_cast<std::uint8_t*>(digest) + 4 * i;
d[3] = ctx.digest[i] & 0xff;
d[2] = (ctx.digest[i] >> 8) & 0xff;
d[1] = (ctx.digest[i] >> 16) & 0xff;
d[0] = (ctx.digest[i] >> 24) & 0xff;
}
}
} // detail
} // beast
} // boost
#endif
+49
View File
@@ -0,0 +1,49 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_STATIC_CONST_HPP
#define BOOST_BEAST_DETAIL_STATIC_CONST_HPP
/* This is a derivative work, original copyright:
Copyright Eric Niebler 2013-present
Use, modification and distribution is subject to 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)
Project home: https://github.com/ericniebler/range-v3
*/
namespace boost {
namespace beast {
namespace detail {
template<typename T>
struct static_const
{
static constexpr T value {};
};
template<typename T>
constexpr T static_const<T>::value;
#define BOOST_BEAST_INLINE_VARIABLE(name, type) \
namespace \
{ \
constexpr auto& name = \
::boost::beast::detail::static_const<type>::value; \
}
} // detail
} // beast
} // boost
#endif
+142
View File
@@ -0,0 +1,142 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_STATIC_OSTREAM_HPP
#define BOOST_BEAST_DETAIL_STATIC_OSTREAM_HPP
#include <locale>
#include <ostream>
#include <streambuf>
namespace boost {
namespace beast {
namespace detail {
// http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
class static_ostream_buffer
: public std::basic_streambuf<char>
{
using CharT = char;
using Traits = std::char_traits<CharT>;
using int_type = typename
std::basic_streambuf<CharT, Traits>::int_type;
using traits_type = typename
std::basic_streambuf<CharT, Traits>::traits_type;
char* data_;
std::size_t size_;
std::size_t len_ = 0;
std::string s_;
public:
static_ostream_buffer(static_ostream_buffer&&) = delete;
static_ostream_buffer(static_ostream_buffer const&) = delete;
static_ostream_buffer(char* data, std::size_t size)
: data_(data)
, size_(size)
{
this->setp(data_, data_ + size - 1);
}
~static_ostream_buffer() noexcept
{
}
string_view
str() const
{
if(! s_.empty())
return {s_.data(), len_};
return {data_, len_};
}
int_type
overflow(int_type ch) override
{
if(! Traits::eq_int_type(ch, Traits::eof()))
{
Traits::assign(*this->pptr(),
static_cast<CharT>(ch));
flush(1);
prepare();
return ch;
}
flush();
return traits_type::eof();
}
int
sync() override
{
flush();
prepare();
return 0;
}
private:
void
prepare()
{
static auto const growth_factor = 1.5;
if(len_ < size_ - 1)
{
this->setp(
data_ + len_, data_ + size_ - 2);
return;
}
if(s_.empty())
{
s_.resize(static_cast<std::size_t>(
growth_factor * len_));
Traits::copy(&s_[0], data_, len_);
}
else
{
s_.resize(static_cast<std::size_t>(
growth_factor * len_));
}
this->setp(&s_[len_], &s_[len_] +
s_.size() - len_ - 1);
}
void
flush(int extra = 0)
{
len_ += static_cast<std::size_t>(
this->pptr() - this->pbase() + extra);
}
};
class static_ostream : public std::basic_ostream<char>
{
static_ostream_buffer osb_;
public:
static_ostream(char* data, std::size_t size)
: std::basic_ostream<char>(&this->osb_)
, osb_(data, size)
{
imbue(std::locale::classic());
}
string_view
str() const
{
return osb_.str();
}
};
} // detail
} // beast
} // boost
#endif
+92
View File
@@ -0,0 +1,92 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_STATIC_STRING_HPP
#define BOOST_BEAST_DETAIL_STATIC_STRING_HPP
#include <boost/assert.hpp>
#include <boost/core/ignore_unused.hpp>
#include <string>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
// Maximum number of characters in the decimal
// representation of a binary number. This includes
// the potential minus sign.
//
inline
std::size_t constexpr
max_digits(std::size_t bytes)
{
return static_cast<std::size_t>(
bytes * 2.41) + 1 + 1;
}
template<class CharT, class Integer, class Traits>
CharT*
raw_to_string(
CharT* buf, Integer x, std::true_type)
{
if(x == 0)
{
Traits::assign(*--buf, '0');
return buf;
}
if(x < 0)
{
x = -x;
for(;x > 0; x /= 10)
Traits::assign(*--buf ,
"0123456789"[x % 10]);
Traits::assign(*--buf, '-');
return buf;
}
for(;x > 0; x /= 10)
Traits::assign(*--buf ,
"0123456789"[x % 10]);
return buf;
}
template<class CharT, class Integer, class Traits>
CharT*
raw_to_string(
CharT* buf, Integer x, std::false_type)
{
if(x == 0)
{
*--buf = '0';
return buf;
}
for(;x > 0; x /= 10)
Traits::assign(*--buf ,
"0123456789"[x % 10]);
return buf;
}
template<
class CharT,
class Integer,
class Traits = std::char_traits<CharT>>
CharT*
raw_to_string(CharT* last, std::size_t size, Integer i)
{
boost::ignore_unused(size);
BOOST_ASSERT(size >= max_digits(sizeof(Integer)));
return raw_to_string<CharT, Integer, Traits>(
last, i, std::is_signed<Integer>{});
}
} // detail
} // beast
} // boost
#endif
+143
View File
@@ -0,0 +1,143 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_STREAM_BASE_HPP
#define BOOST_BEAST_CORE_DETAIL_STREAM_BASE_HPP
#include <boost/asio/steady_timer.hpp>
#include <boost/assert.hpp>
#include <boost/core/exchange.hpp>
#include <chrono>
#include <cstdint>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
struct any_endpoint
{
template<class Error, class Endpoint>
bool
operator()(
Error const&, Endpoint const&) const noexcept
{
return true;
}
};
struct stream_base
{
using clock_type = std::chrono::steady_clock;
using time_point = typename
std::chrono::steady_clock::time_point;
using tick_type = std::uint64_t;
template<typename Executor>
struct basic_op_state
{
net::basic_waitable_timer<
std::chrono::steady_clock,
net::wait_traits<
std::chrono::steady_clock>,
Executor> timer; // for timing out
tick_type tick = 0; // counts waits
bool pending = false; // if op is pending
bool timeout = false; // if timed out
template<class... Args>
explicit
basic_op_state(Args&&... args)
: timer(std::forward<Args>(args)...)
{
}
};
class pending_guard
{
bool* b_ = nullptr;
bool clear_ = true;
public:
~pending_guard()
{
if(clear_ && b_)
*b_ = false;
}
pending_guard()
: b_(nullptr)
, clear_(true)
{
}
explicit
pending_guard(bool& b)
: b_(&b)
{
// If this assert goes off, it means you are attempting
// to issue two of the same asynchronous I/O operation
// at the same time, without waiting for the first one
// to complete. For example, attempting two simultaneous
// calls to async_read_some. Only one pending call of
// each I/O type (read and write) is permitted.
//
BOOST_ASSERT(! *b_);
*b_ = true;
}
pending_guard(
pending_guard&& other) noexcept
: b_(other.b_)
, clear_(boost::exchange(
other.clear_, false))
{
}
void assign(bool& b)
{
BOOST_ASSERT(!b_);
BOOST_ASSERT(clear_);
b_ = &b;
// If this assert goes off, it means you are attempting
// to issue two of the same asynchronous I/O operation
// at the same time, without waiting for the first one
// to complete. For example, attempting two simultaneous
// calls to async_read_some. Only one pending call of
// each I/O type (read and write) is permitted.
//
BOOST_ASSERT(! *b_);
*b_ = true;
}
void
reset()
{
BOOST_ASSERT(clear_);
if (b_)
*b_ = false;
clear_ = false;
}
};
static time_point never() noexcept
{
return (time_point::max)();
}
static std::size_t constexpr no_limit =
(std::numeric_limits<std::size_t>::max)();
};
} // detail
} // beast
} // boost
#endif
+111
View File
@@ -0,0 +1,111 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_STREAM_TRAITS_HPP
#define BOOST_BEAST_DETAIL_STREAM_TRAITS_HPP
#include <boost/beast/core/error.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/type_traits/make_void.hpp>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
//------------------------------------------------------------------------------
//
// get_lowest_layer
// lowest_layer_type
// detail::has_next_layer
//
template <class T>
std::false_type has_next_layer_impl(void*);
template <class T>
auto has_next_layer_impl(decltype(nullptr)) ->
decltype(std::declval<T&>().next_layer(), std::true_type{});
template <class T>
using has_next_layer = decltype(has_next_layer_impl<T>(nullptr));
template<class T, bool = has_next_layer<T>::value>
struct lowest_layer_type_impl
{
using type = typename std::remove_reference<T>::type;
};
template<class T>
struct lowest_layer_type_impl<T, true>
{
using type = typename lowest_layer_type_impl<
decltype(std::declval<T&>().next_layer())>::type;
};
template<class T>
using lowest_layer_type = typename
lowest_layer_type_impl<T>::type;
template<class T>
T&
get_lowest_layer_impl(
T& t, std::false_type) noexcept
{
return t;
}
template<class T>
lowest_layer_type<T>&
get_lowest_layer_impl(
T& t, std::true_type) noexcept
{
return get_lowest_layer_impl(t.next_layer(),
has_next_layer<typename std::decay<
decltype(t.next_layer())>::type>{});
}
//------------------------------------------------------------------------------
// Types that meet the requirements,
// for use with std::declval only.
template<class BufferType>
struct BufferSequence
{
using value_type = BufferType;
using const_iterator = BufferType const*;
~BufferSequence() = default;
BufferSequence(BufferSequence const&) = default;
const_iterator begin() const noexcept { return {}; }
const_iterator end() const noexcept { return {}; }
};
using ConstBufferSequence =
BufferSequence<net::const_buffer>;
using MutableBufferSequence =
BufferSequence<net::mutable_buffer>;
//
// Types that meet the requirements,
// for use with std::declval only.
struct StreamHandler
{
StreamHandler(StreamHandler const&) = default;
void operator()(error_code, std::size_t) {}
};
using ReadHandler = StreamHandler;
using WriteHandler = StreamHandler;
//------------------------------------------------------------------------------
} // detail
} // beast
} // boost
#endif
+44
View File
@@ -0,0 +1,44 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_STRING_HPP
#define BOOST_BEAST_DETAIL_STRING_HPP
#include <boost/beast/core/string_type.hpp>
namespace boost {
namespace beast {
namespace detail {
// Pulling in the UDL directly breaks in some places on MSVC,
// so introduce a namespace for this purprose.
namespace string_literals {
inline
string_view
operator"" _sv(char const* p, std::size_t n)
{
return string_view{p, n};
}
} // string_literals
inline
char
ascii_tolower(char c)
{
return ((static_cast<unsigned>(c) - 65U) < 26) ?
c + 'a' - 'A' : c;
}
} // detail
} // beast
} // boost
#endif
+83
View File
@@ -0,0 +1,83 @@
//
// Copyright (c) 2019 Damian Jarek(damian.jarek93@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/beast
//
#ifndef BOOST_BEAST_DETAIL_TEMPORARY_BUFFER_HPP
#define BOOST_BEAST_DETAIL_TEMPORARY_BUFFER_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/string.hpp>
#include <memory>
namespace boost {
namespace beast {
namespace detail {
struct temporary_buffer
{
temporary_buffer() = default;
temporary_buffer(temporary_buffer const&) = delete;
temporary_buffer& operator=(temporary_buffer const&) = delete;
~temporary_buffer() noexcept
{
deallocate(data_);
}
BOOST_BEAST_DECL
void
append(string_view s);
BOOST_BEAST_DECL
void
append(string_view s1, string_view s2);
string_view
view() const noexcept
{
return {data_, size_};
}
bool
empty() const noexcept
{
return size_ == 0;
}
private:
BOOST_BEAST_DECL
void
unchecked_append(string_view s);
BOOST_BEAST_DECL
void
grow(std::size_t n);
void
deallocate(char* data) noexcept
{
if (data != buffer_)
delete[] data;
}
char buffer_[4096];
char* data_ = buffer_;
std::size_t capacity_ = sizeof(buffer_);
std::size_t size_ = 0;
};
} // detail
} // beast
} // boost
#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/core/detail/impl/temporary_buffer.ipp>
#endif
#endif
+116
View File
@@ -0,0 +1,116 @@
//
// Copyright (c) 2016-2019 Damian Jarek (damian dot jarek93 at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_TUPLE_HPP
#define BOOST_BEAST_DETAIL_TUPLE_HPP
#include <boost/mp11/integer_sequence.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/copy_cv.hpp>
#include <cstdlib>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
template<std::size_t I, class T>
struct tuple_element_impl
{
T t;
tuple_element_impl(T const& t_)
: t(t_)
{
}
tuple_element_impl(T&& t_)
: t(std::move(t_))
{
}
};
template<std::size_t I, class T>
struct tuple_element_impl<I, T&>
{
T& t;
tuple_element_impl(T& t_)
: t(t_)
{
}
};
template<class... Ts>
struct tuple_impl;
template<class... Ts, std::size_t... Is>
struct tuple_impl<
boost::mp11::index_sequence<Is...>, Ts...>
: tuple_element_impl<Is, Ts>...
{
template<class... Us>
explicit tuple_impl(Us&&... us)
: tuple_element_impl<Is, Ts>(
std::forward<Us>(us))...
{
}
};
template<class... Ts>
struct tuple : tuple_impl<
boost::mp11::index_sequence_for<Ts...>, Ts...>
{
template<class... Us>
explicit tuple(Us&&... us)
: tuple_impl<
boost::mp11::index_sequence_for<Ts...>, Ts...>{
std::forward<Us>(us)...}
{
}
};
template<std::size_t I, class T>
T&
get(tuple_element_impl<I, T>& te)
{
return te.t;
}
template<std::size_t I, class T>
T const&
get(tuple_element_impl<I, T> const& te)
{
return te.t;
}
template<std::size_t I, class T>
T&&
get(tuple_element_impl<I, T>&& te)
{
return std::move(te.t);
}
template<std::size_t I, class T>
T&
get(tuple_element_impl<I, T&>&& te)
{
return te.t;
}
template <std::size_t I, class T>
using tuple_element = typename boost::copy_cv<
mp11::mp_at_c<typename remove_cv<T>::type, I>, T>::type;
} // detail
} // beast
} // boost
#endif
+95
View File
@@ -0,0 +1,95 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP
#define BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/make_void.hpp>
#include <type_traits>
#include <new>
namespace boost {
namespace beast {
namespace detail {
template<class U>
std::size_t constexpr
max_sizeof()
{
return sizeof(U);
}
template<class U0, class U1, class... Us>
std::size_t constexpr
max_sizeof()
{
return
max_sizeof<U0>() > max_sizeof<U1, Us...>() ?
max_sizeof<U0>() : max_sizeof<U1, Us...>();
}
template<class U>
std::size_t constexpr
max_alignof()
{
return alignof(U);
}
template<class U0, class U1, class... Us>
std::size_t constexpr
max_alignof()
{
return
max_alignof<U0>() > max_alignof<U1, Us...>() ?
max_alignof<U0>() : max_alignof<U1, Us...>();
}
// (since C++17)
template<class... Ts>
using make_void = boost::make_void<Ts...>;
template<class... Ts>
using void_t = boost::void_t<Ts...>;
// (since C++11) missing from g++4.8
template<std::size_t Len, class... Ts>
struct aligned_union
{
static
std::size_t constexpr alignment_value =
max_alignof<Ts...>();
using type = typename boost::aligned_storage<
(Len > max_sizeof<Ts...>()) ? Len : (max_sizeof<Ts...>()),
alignment_value>::type;
};
template<std::size_t Len, class... Ts>
using aligned_union_t =
typename aligned_union<Len, Ts...>::type;
//------------------------------------------------------------------------------
template <class T, class U>
T launder_cast(U* u)
{
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
return std::launder(reinterpret_cast<T>(u));
#elif defined(BOOST_GCC) && BOOST_GCC_VERSION > 80000
return __builtin_launder(reinterpret_cast<T>(u));
#else
return reinterpret_cast<T>(u);
#endif
}
} // detail
} // beast
} // boost
#endif
+235
View File
@@ -0,0 +1,235 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_VARIANT_HPP
#define BOOST_BEAST_DETAIL_VARIANT_HPP
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/assert.hpp>
#include <boost/mp11/algorithm.hpp>
namespace boost {
namespace beast {
namespace detail {
// This simple variant gets the job done without
// causing too much trouble with template depth:
//
// * Always allows an empty state I==0
// * emplace() and get() support 1-based indexes only
// * Basic exception guarantee
// * Max 255 types
//
template<class... TN>
class variant
{
detail::aligned_union_t<1, TN...> buf_;
unsigned char i_ = 0;
struct destroy
{
variant& self;
void operator()(mp11::mp_size_t<0>)
{
}
template<class I>
void operator()(I) noexcept
{
using T =
mp11::mp_at_c<variant, I::value - 1>;
detail::launder_cast<T*>(&self.buf_)->~T();
}
};
struct copy
{
variant& self;
variant const& other;
void operator()(mp11::mp_size_t<0>)
{
}
template<class I>
void operator()(I)
{
using T =
mp11::mp_at_c<variant, I::value - 1>;
::new(&self.buf_) T(
*detail::launder_cast<T const*>(&other.buf_));
self.i_ = I::value;
}
};
struct move
{
variant& self;
variant& other;
void operator()(mp11::mp_size_t<0>)
{
}
template<class I>
void operator()(I)
{
using T =
mp11::mp_at_c<variant, I::value - 1>;
::new(&self.buf_) T(std::move(
*detail::launder_cast<T*>(&other.buf_)));
detail::launder_cast<T*>(&other.buf_)->~T();
self.i_ = I::value;
}
};
struct equals
{
variant const& self;
variant const& other;
bool operator()(mp11::mp_size_t<0>)
{
return true;
}
template<class I>
bool operator()(I)
{
using T =
mp11::mp_at_c<variant, I::value - 1>;
return
*detail::launder_cast<T const*>(&self.buf_) ==
*detail::launder_cast<T const*>(&other.buf_);
}
};
void destruct()
{
mp11::mp_with_index<
sizeof...(TN) + 1>(
i_, destroy{*this});
i_ = 0;
}
void copy_construct(variant const& other)
{
mp11::mp_with_index<
sizeof...(TN) + 1>(
other.i_, copy{*this, other});
}
void move_construct(variant& other)
{
mp11::mp_with_index<
sizeof...(TN) + 1>(
other.i_, move{*this, other});
other.i_ = 0;
}
public:
variant() = default;
~variant()
{
destruct();
}
bool
operator==(variant const& other) const
{
if(i_ != other.i_)
return false;
return mp11::mp_with_index<
sizeof...(TN) + 1>(
i_, equals{*this, other});
}
// 0 = empty
unsigned char
index() const
{
return i_;
}
// moved-from object becomes empty
variant(variant&& other) noexcept
{
move_construct(other);
}
variant(variant const& other)
{
copy_construct(other);
}
// moved-from object becomes empty
variant& operator=(variant&& other)
{
if(this != &other)
{
destruct();
move_construct(other);
}
return *this;
}
variant& operator=(variant const& other)
{
if(this != &other)
{
destruct();
copy_construct(other);
}
return *this;
}
template<std::size_t I, class... Args>
void
emplace(Args&&... args) noexcept
{
destruct();
::new(&buf_) mp11::mp_at_c<variant, I - 1>(
std::forward<Args>(args)...);
i_ = I;
}
template<std::size_t I>
mp11::mp_at_c<variant, I - 1>&
get()
{
BOOST_ASSERT(i_ == I);
return *detail::launder_cast<
mp11::mp_at_c<variant, I - 1>*>(&buf_);
}
template<std::size_t I>
mp11::mp_at_c<variant, I - 1> const&
get() const
{
BOOST_ASSERT(i_ == I);
return *detail::launder_cast<
mp11::mp_at_c<variant, I - 1> const*>(&buf_);
}
void
reset()
{
destruct();
}
};
} // detail
} // beast
} // boost
#endif
+79
View File
@@ -0,0 +1,79 @@
//
// Copyright (c) 2017 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
//
#ifndef BOOST_BEAST_DETAIL_VARINT_HPP
#define BOOST_BEAST_DETAIL_VARINT_HPP
#include <boost/static_assert.hpp>
#include <cstdlib>
#include <iterator>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
// https://developers.google.com/protocol-buffers/docs/encoding#varints
inline
std::size_t
varint_size(std::size_t value)
{
std::size_t n = 1;
while(value > 127)
{
++n;
value /= 128;
}
return n;
}
template<class FwdIt>
std::size_t
varint_read(FwdIt& first)
{
using value_type = typename
std::iterator_traits<FwdIt>::value_type;
BOOST_STATIC_ASSERT(
std::is_integral<value_type>::value &&
sizeof(value_type) == 1);
std::size_t value = 0;
std::size_t factor = 1;
while((*first & 0x80) != 0)
{
value += (*first++ & 0x7f) * factor;
factor *= 128;
}
value += *first++ * factor;
return value;
}
template<class FwdIt>
void
varint_write(FwdIt& first, std::size_t value)
{
using value_type = typename
std::iterator_traits<FwdIt>::value_type;
BOOST_STATIC_ASSERT(
std::is_integral<value_type>::value &&
sizeof(value_type) == 1);
while(value > 127)
{
*first++ = static_cast<value_type>(
0x80 | value);
value /= 128;
}
*first++ = static_cast<value_type>(value);
}
} // detail
} // beast
} // boost
#endif
+82
View File
@@ -0,0 +1,82 @@
//
// Copyright (c) 2019 Mika Fischer (mika.fischer@zoopnet.de)
//
// 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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_WIN32_UNICODE_PATH_HPP
#define BOOST_BEAST_CORE_DETAIL_WIN32_UNICODE_PATH_HPP
#ifdef _WIN32
#include <boost/config.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/winapi/character_code_conversion.hpp>
#include <boost/winapi/file_management.hpp>
#include <boost/winapi/get_last_error.hpp>
#include <array>
#include <vector>
namespace boost {
namespace beast {
namespace detail {
class win32_unicode_path
{
using WCHAR_ = boost::winapi::WCHAR_;
public:
win32_unicode_path(const char* utf8_path, error_code& ec) {
int ret = mb2wide(utf8_path, static_buf_.data(),
static_buf_.size());
if (ret == 0)
{
int sz = mb2wide(utf8_path, nullptr, 0);
if (sz == 0)
{
ec.assign(boost::winapi::GetLastError(),
system_category());
return;
}
dynamic_buf_.resize(sz);
int ret2 = mb2wide(utf8_path,
dynamic_buf_.data(),
dynamic_buf_.size());
if (ret2 == 0)
{
ec.assign(boost::winapi::GetLastError(),
system_category());
return;
}
}
}
WCHAR_ const* c_str() const noexcept
{
return dynamic_buf_.empty()
? static_buf_.data()
: dynamic_buf_.data();
}
private:
int mb2wide(const char* utf8_path, WCHAR_* buf, size_t sz)
{
return boost::winapi::MultiByteToWideChar(
boost::winapi::CP_UTF8_,
boost::winapi::MB_ERR_INVALID_CHARS_,
utf8_path, -1,
buf, static_cast<int>(sz));
}
std::array<WCHAR_, boost::winapi::MAX_PATH_> static_buf_;
std::vector<WCHAR_> dynamic_buf_;
};
} // detail
} // beast
} // boost
#endif
#endif
+102
View File
@@ -0,0 +1,102 @@
//
// Copyright (c) 2020 Richard Hodges (hodges.r@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/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_WORK_GUARD_HPP
#define BOOST_BEAST_CORE_DETAIL_WORK_GUARD_HPP
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/execution.hpp>
#include <boost/optional.hpp>
namespace boost {
namespace beast {
namespace detail {
template<class Executor, class Enable = void>
struct select_work_guard;
template<class Executor>
using select_work_guard_t = typename
select_work_guard<Executor>::type;
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
template<class Executor>
struct select_work_guard
<
Executor,
typename std::enable_if
<
net::is_executor<Executor>::value
>::type
>
{
using type = net::executor_work_guard<Executor>;
};
#endif
template<class Executor>
struct execution_work_guard
{
using executor_type = typename std::decay<decltype(
net::prefer(std::declval<Executor const&>(),
net::execution::outstanding_work.tracked))>::type;
execution_work_guard(Executor const& exec)
: ex_(net::prefer(exec, net::execution::outstanding_work.tracked))
{
}
executor_type
get_executor() const noexcept
{
BOOST_ASSERT(ex_.has_value());
return *ex_;
}
void reset() noexcept
{
ex_.reset();
}
private:
boost::optional<executor_type> ex_;
};
template<class Executor>
struct select_work_guard
<
Executor,
typename std::enable_if
<
net::execution::is_executor<Executor>::value
#if defined(BOOST_ASIO_NO_TS_EXECUTORS)
|| net::is_executor<Executor>::value
#else
&& !net::is_executor<Executor>::value
#endif
>::type
>
{
using type = execution_work_guard<Executor>;
};
template<class Executor>
select_work_guard_t<Executor>
make_work_guard(Executor const& exec) noexcept
{
return select_work_guard_t<Executor>(exec);
}
}
}
}
#endif // BOOST_BEAST_CORE_DETAIL_WORK_GUARD_HPP