summaryrefslogtreecommitdiff
path: root/boost/beast/core/detail
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:11:01 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:11:01 +0900
commit3fdc3e5ee96dca5b11d1694975a65200787eab86 (patch)
tree5c1733853892b8397d67706fa453a9bd978d2102 /boost/beast/core/detail
parent88e602c57797660ebe0f9e15dbd64c1ff16dead3 (diff)
downloadboost-3fdc3e5ee96dca5b11d1694975a65200787eab86.tar.gz
boost-3fdc3e5ee96dca5b11d1694975a65200787eab86.tar.bz2
boost-3fdc3e5ee96dca5b11d1694975a65200787eab86.zip
Imported Upstream version 1.66.0upstream/1.66.0
Diffstat (limited to 'boost/beast/core/detail')
-rw-r--r--boost/beast/core/detail/allocator.hpp42
-rw-r--r--boost/beast/core/detail/base64.hpp251
-rw-r--r--boost/beast/core/detail/bind_handler.hpp189
-rw-r--r--boost/beast/core/detail/buffers_ref.hpp67
-rw-r--r--boost/beast/core/detail/clamp.hpp59
-rw-r--r--boost/beast/core/detail/config.hpp57
-rw-r--r--boost/beast/core/detail/cpu_info.hpp99
-rw-r--r--boost/beast/core/detail/empty_base_optimization.hpp100
-rw-r--r--boost/beast/core/detail/in_place_init.hpp43
-rw-r--r--boost/beast/core/detail/integer_sequence.hpp143
-rw-r--r--boost/beast/core/detail/ostream.hpp319
-rw-r--r--boost/beast/core/detail/sha1.hpp313
-rw-r--r--boost/beast/core/detail/static_ostream.hpp142
-rw-r--r--boost/beast/core/detail/static_string.hpp135
-rw-r--r--boost/beast/core/detail/type_traits.hpp353
-rw-r--r--boost/beast/core/detail/variant.hpp195
-rw-r--r--boost/beast/core/detail/varint.hpp79
17 files changed, 2586 insertions, 0 deletions
diff --git a/boost/beast/core/detail/allocator.hpp b/boost/beast/core/detail/allocator.hpp
new file mode 100644
index 0000000000..39b2aa5f12
--- /dev/null
+++ b/boost/beast/core/detail/allocator.hpp
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2016-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_ALLOCATOR_HPP
+#define BOOST_BEAST_DETAIL_ALLOCATOR_HPP
+
+#include <boost/config.hpp>
+#if 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.
+
+#if 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
diff --git a/boost/beast/core/detail/base64.hpp b/boost/beast/core/detail/base64.hpp
new file mode 100644
index 0000000000..ece03dfa34
--- /dev/null
+++ b/boost/beast/core/detail/base64.hpp
@@ -0,0 +1,251 @@
+//
+// Copyright (c) 2016-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
+//
+
+/*
+ Portions from http://www.adp-gmbh.ch/cpp/common/base64.html
+ Copyright notice:
+
+ base64.cpp and base64.h
+
+ Copyright (C) 2004-2008 René 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.
+
+ René Nyffenegger rene.nyffenegger@adp-gmbh.ch
+
+*/
+
+#ifndef BOOST_BEAST_DETAIL_BASE64_HPP
+#define BOOST_BEAST_DETAIL_BASE64_HPP
+
+#include <cctype>
+#include <string>
+#include <utility>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+namespace base64 {
+
+inline
+char const*
+get_alphabet()
+{
+ static char constexpr tab[] = {
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+ };
+ return &tab[0];
+}
+
+inline
+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];
+}
+
+
+/// Returns max chars needed to encode a base64 string
+inline
+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
+ //return 3 * n / 4;
+}
+
+/** 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.
+*/
+template<class = void>
+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.
+*/
+template<class = void>
+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];
+ 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
+
+template<class = void>
+std::string
+base64_encode (std::uint8_t const* data,
+ std::size_t len)
+{
+ std::string dest;
+ dest.resize(base64::encoded_size(len));
+ dest.resize(base64::encode(&dest[0], data, len));
+ return dest;
+}
+
+inline
+std::string
+base64_encode(std::string const& s)
+{
+ return base64_encode (reinterpret_cast <
+ std::uint8_t const*> (s.data()), s.size());
+}
+
+template<class = void>
+std::string
+base64_decode(std::string const& data)
+{
+ std::string dest;
+ dest.resize(base64::decoded_size(data.size()));
+ auto const result = base64::decode(
+ &dest[0], data.data(), data.size());
+ dest.resize(result.first);
+ return dest;
+}
+
+} // detail
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/detail/bind_handler.hpp b/boost/beast/core/detail/bind_handler.hpp
new file mode 100644
index 0000000000..5a9059b8e3
--- /dev/null
+++ b/boost/beast/core/detail/bind_handler.hpp
@@ -0,0 +1,189 @@
+//
+// Copyright (c) 2016-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_BIND_HANDLER_HPP
+#define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
+
+#include <boost/beast/core/detail/integer_sequence.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/handler_continuation_hook.hpp>
+#include <boost/core/ignore_unused.hpp>
+#include <functional>
+#include <utility>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+/* Nullary handler that calls Handler with bound arguments.
+
+ The bound handler provides the same io_context execution
+ guarantees as the original handler.
+*/
+template<class Handler, class... Args>
+class bound_handler
+{
+ // Can't friend partial specializations,
+ // so we just friend the whole thing.
+ template<class T, class Executor>
+ friend struct boost::asio::associated_executor;
+
+ using args_type = std::tuple<
+ typename std::decay<Args>::type...>;
+
+ Handler h_;
+ args_type args_;
+
+ template<class Arg, class Vals>
+ static
+ typename std::enable_if<
+ std::is_placeholder<typename
+ std::decay<Arg>::type>::value == 0,
+ Arg&&>::type
+ extract(Arg&& arg, Vals& vals)
+ {
+ boost::ignore_unused(vals);
+ return arg;
+ }
+
+ template<class Arg, class Vals>
+ static
+ typename std::enable_if<
+ std::is_placeholder<typename
+ std::decay<Arg>::type>::value != 0,
+ typename std::tuple_element<
+ std::is_placeholder<
+ typename std::decay<Arg>::type>::value - 1,
+ Vals>::type&&>::type
+ extract(Arg&&, Vals&& vals)
+ {
+ return std::get<std::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,
+ std::tuple<>&&,
+ index_sequence<S...>)
+ {
+ boost::ignore_unused(args);
+ h(std::get<S>(args)...);
+ }
+
+ template<
+ class ArgsTuple,
+ class ValsTuple,
+ std::size_t... S>
+ static
+ void
+ invoke(
+ Handler& h,
+ ArgsTuple& args,
+ ValsTuple&& vals,
+ index_sequence<S...>)
+ {
+ boost::ignore_unused(args);
+ boost::ignore_unused(vals);
+ h(extract(std::get<S>(args),
+ std::forward<ValsTuple>(vals))...);
+ }
+
+public:
+ using result_type = void;
+
+ using allocator_type =
+ boost::asio::associated_allocator_t<Handler>;
+
+ bound_handler(bound_handler&&) = default;
+ bound_handler(bound_handler const&) = default;
+
+ template<class DeducedHandler>
+ explicit
+ bound_handler(
+ DeducedHandler&& handler, Args&&... args)
+ : h_(std::forward<DeducedHandler>(handler))
+ , args_(std::forward<Args>(args)...)
+ {
+ }
+
+ allocator_type
+ get_allocator() const noexcept
+ {
+ return boost::asio::get_associated_allocator(h_);
+ }
+
+ friend
+ bool
+ asio_handler_is_continuation(bound_handler* h)
+ {
+ using boost::asio::asio_handler_is_continuation;
+ return asio_handler_is_continuation(std::addressof(h->h_));
+ }
+
+ template<class... Values>
+ void
+ operator()(Values&&... values)
+ {
+ invoke(h_, args_,
+ std::forward_as_tuple(
+ std::forward<Values>(values)...),
+ index_sequence_for<Args...>());
+ }
+
+ template<class... Values>
+ void
+ operator()(Values&&... values) const
+ {
+ invoke(h_, args_,
+ std::forward_as_tuple(
+ std::forward<Values>(values)...),
+ index_sequence_for<Args...>());
+ }
+};
+
+} // detail
+} // beast
+
+namespace asio {
+template<class Handler, class... Args, class Executor>
+struct associated_executor<
+ beast::detail::bound_handler<Handler, Args...>, Executor>
+{
+ using type = typename
+ associated_executor<Handler, Executor>::type;
+
+ static
+ type
+ get(beast::detail::bound_handler<Handler, Args...> const& h,
+ Executor const& ex = Executor()) noexcept
+ {
+ return associated_executor<
+ Handler, Executor>::get(h.h_, ex);
+ }
+};
+} // asio
+
+} // boost
+
+namespace std {
+template<class Handler, class... Args>
+void
+bind(boost::beast::detail::bound_handler<
+ Handler, Args...>, ...) = delete;
+} // std
+
+#endif
diff --git a/boost/beast/core/detail/buffers_ref.hpp b/boost/beast/core/detail/buffers_ref.hpp
new file mode 100644
index 0000000000..e56a9764fd
--- /dev/null
+++ b/boost/beast/core/detail/buffers_ref.hpp
@@ -0,0 +1,67 @@
+//
+// Copyright (c) 2016-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_BUFFERS_REF_HPP
+#define BOOST_BEAST_DETAIL_BUFFERS_REF_HPP
+
+#include <boost/beast/core/type_traits.hpp>
+#include <iterator>
+
+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 = typename
+ buffer_sequence_iterator<BufferSequence>::type;
+
+ 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 boost::asio::buffer_sequence_begin(*buffers_);
+ }
+
+ const_iterator
+ end() const
+ {
+ return boost::asio::buffer_sequence_end(*buffers_);
+ }
+};
+
+// Return a reference to a buffer sequence
+template<class BufferSequence>
+buffers_ref<BufferSequence>
+make_buffers_ref(BufferSequence const& buffers)
+{
+ return buffers_ref<BufferSequence>(buffers);
+}
+
+} // detail
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/detail/clamp.hpp b/boost/beast/core/detail/clamp.hpp
new file mode 100644
index 0000000000..95a8fab425
--- /dev/null
+++ b/boost/beast/core/detail/clamp.hpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2016-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_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
diff --git a/boost/beast/core/detail/config.hpp b/boost/beast/core/detail/config.hpp
new file mode 100644
index 0000000000..48f97e377f
--- /dev/null
+++ b/boost/beast/core/detail/config.hpp
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2016-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_CORE_DETAIL_CONFIG_HPP
+#define BOOST_BEAST_CORE_DETAIL_CONFIG_HPP
+
+#include <boost/config.hpp>
+#include <boost/version.hpp>
+
+// Available to every header
+#include <boost/config.hpp>
+#include <boost/core/ignore_unused.hpp>
+#include <boost/static_assert.hpp>
+
+/*
+ _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 < 40801)
+# error Beast requires C++11: gcc version 4.8 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
+
+#if BOOST_VERSION >= 106500 || ! defined(BOOST_GCC) || BOOST_GCC < 70000
+# define BOOST_BEAST_FALLTHROUGH BOOST_FALLTHROUGH
+#else
+# define BOOST_BEAST_FALLTHROUGH __attribute__((fallthrough))
+#endif
+
+#endif
diff --git a/boost/beast/core/detail/cpu_info.hpp b/boost/beast/core/detail/cpu_info.hpp
new file mode 100644
index 0000000000..579589fa8e
--- /dev/null
+++ b/boost/beast/core/detail/cpu_info.hpp
@@ -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
diff --git a/boost/beast/core/detail/empty_base_optimization.hpp b/boost/beast/core/detail/empty_base_optimization.hpp
new file mode 100644
index 0000000000..b1e728b674
--- /dev/null
+++ b/boost/beast/core/detail/empty_base_optimization.hpp
@@ -0,0 +1,100 @@
+//
+// Copyright (c) 2016-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_EMPTY_BASE_OPTIMIZATION_HPP
+#define BOOST_BEAST_DETAIL_EMPTY_BASE_OPTIMIZATION_HPP
+
+#include <boost/type_traits/is_final.hpp>
+#include <type_traits>
+#include <utility>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+template<class T>
+struct is_empty_base_optimization_derived
+ : std::integral_constant<bool,
+ std::is_empty<T>::value &&
+ ! boost::is_final<T>::value>
+{
+};
+
+template<class T, int UniqueID = 0,
+ bool isDerived =
+ is_empty_base_optimization_derived<T>::value>
+class empty_base_optimization : private T
+{
+public:
+ empty_base_optimization() = default;
+ empty_base_optimization(empty_base_optimization&&) = default;
+ empty_base_optimization(empty_base_optimization const&) = default;
+ empty_base_optimization& operator=(empty_base_optimization&&) = default;
+ empty_base_optimization& operator=(empty_base_optimization const&) = default;
+
+ template<class Arg1, class... ArgN>
+ explicit
+ empty_base_optimization(Arg1&& arg1, ArgN&&... argn)
+ : T(std::forward<Arg1>(arg1),
+ std::forward<ArgN>(argn)...)
+ {
+ }
+
+ T& member() noexcept
+ {
+ return *this;
+ }
+
+ T const& member() const noexcept
+ {
+ return *this;
+ }
+};
+
+//------------------------------------------------------------------------------
+
+template<
+ class T,
+ int UniqueID
+>
+class empty_base_optimization <T, UniqueID, false>
+{
+ T t_;
+
+public:
+ empty_base_optimization() = default;
+ empty_base_optimization(empty_base_optimization&&) = default;
+ empty_base_optimization(empty_base_optimization const&) = default;
+ empty_base_optimization& operator=(empty_base_optimization&&) = default;
+ empty_base_optimization& operator=(empty_base_optimization const&) = default;
+
+ template<class Arg1, class... ArgN>
+ explicit
+ empty_base_optimization(Arg1&& arg1, ArgN&&... argn)
+ : t_(std::forward<Arg1>(arg1),
+ std::forward<ArgN>(argn)...)
+ {
+ }
+
+ T& member() noexcept
+ {
+ return t_;
+ }
+
+ T const& member() const noexcept
+ {
+ return t_;
+ }
+};
+
+} // detail
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/detail/in_place_init.hpp b/boost/beast/core/detail/in_place_init.hpp
new file mode 100644
index 0000000000..d3a33becd5
--- /dev/null
+++ b/boost/beast/core/detail/in_place_init.hpp
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2016-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_IN_PLACE_INIT_HPP
+#define BOOST_BEAST_DETAIL_IN_PLACE_INIT_HPP
+
+#include <boost/version.hpp>
+#include <boost/optional/optional.hpp>
+
+// Provide boost::in_place_init_t and boost::in_place_init
+// for Boost versions earlier than 1.63.0.
+
+#if BOOST_VERSION < 106300
+
+namespace boost {
+
+namespace optional_ns {
+
+// a tag for in-place initialization of contained value
+struct in_place_init_t
+{
+ struct init_tag{};
+ explicit in_place_init_t(init_tag){}
+};
+const in_place_init_t in_place_init ((in_place_init_t::init_tag()));
+
+} // namespace optional_ns
+
+using optional_ns::in_place_init_t;
+using optional_ns::in_place_init;
+
+}
+
+#endif
+
+#endif
+
diff --git a/boost/beast/core/detail/integer_sequence.hpp b/boost/beast/core/detail/integer_sequence.hpp
new file mode 100644
index 0000000000..71664229af
--- /dev/null
+++ b/boost/beast/core/detail/integer_sequence.hpp
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2016-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_INTEGER_SEQUENCE_HPP
+#define BOOST_BEAST_DETAIL_INTEGER_SEQUENCE_HPP
+
+#include <boost/config.hpp>
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+template<class T, T... Ints>
+struct integer_sequence
+{
+ using value_type = T;
+ BOOST_STATIC_ASSERT(std::is_integral<T>::value);
+
+ static std::size_t constexpr static_size = sizeof...(Ints);
+
+ static std::size_t constexpr size()
+ {
+ return sizeof...(Ints);
+ }
+};
+
+template<std::size_t... Ints>
+using index_sequence = integer_sequence<std::size_t, Ints...>;
+
+// This workaround is needed for broken sizeof...
+template<class... Args>
+struct sizeof_workaround
+{
+ static std::size_t constexpr size = sizeof... (Args);
+};
+
+#ifdef BOOST_MSVC
+
+// This implementation compiles on real MSVC and clang but not gcc
+
+template<class T, unsigned long long N, class Seq>
+struct make_integer_sequence_unchecked;
+
+template<class T, unsigned long long N, unsigned long long ...Indices>
+struct make_integer_sequence_unchecked<
+ T, N, integer_sequence<T, Indices...>>
+{
+ using type = typename make_integer_sequence_unchecked<
+ T, N-1, integer_sequence<T, N-1, Indices...>>::type;
+};
+
+template<class T, unsigned long long ...Indices>
+struct make_integer_sequence_unchecked<
+ T, 0, integer_sequence<T, Indices...>>
+{
+ using type = integer_sequence<T, Indices...>;
+};
+
+template<class T, T N>
+struct make_integer_sequence_checked
+{
+ BOOST_STATIC_ASSERT(std::is_integral<T>::value);
+ BOOST_STATIC_ASSERT(N >= 0);
+
+ using type = typename make_integer_sequence_unchecked<
+ T, N, integer_sequence<T>>::type;
+};
+
+template<class T, T N>
+using make_integer_sequence =
+ typename make_integer_sequence_checked<T, N>::type;
+
+template<std::size_t N>
+using make_index_sequence = make_integer_sequence<std::size_t, N>;
+
+template<class... Args>
+using index_sequence_for =
+ make_index_sequence<sizeof_workaround<Args...>::size>;
+
+#else
+
+// This implementation compiles on gcc but not MSVC
+
+template<std::size_t... Ints>
+struct index_tuple
+{
+ using next = index_tuple<Ints..., sizeof... (Ints)>;
+
+};
+
+template<std::size_t N>
+struct build_index_tuple
+{
+ using type = typename build_index_tuple<N-1>::type::next;
+};
+
+template<>
+struct build_index_tuple<0>
+{
+ using type = index_tuple<>;
+};
+
+template<class T, T N,
+ class Seq = typename build_index_tuple<N>::type
+>
+struct integer_sequence_helper;
+
+template<class T, T N, std::size_t... Ints>
+struct integer_sequence_helper<T, N, index_tuple<Ints...>>
+{
+ BOOST_STATIC_ASSERT(std::is_integral<T>::value);
+ BOOST_STATIC_ASSERT(N >= 0);
+
+ using type = integer_sequence<T, static_cast<T> (Ints)...>;
+};
+
+template<class T, T N>
+using make_integer_sequence =
+ typename integer_sequence_helper<T, N>::type;
+
+template<std::size_t N>
+using make_index_sequence = make_integer_sequence<std::size_t, N>;
+
+template<class... Args>
+using index_sequence_for =
+ make_index_sequence<sizeof_workaround<Args...>::size>;
+
+#endif
+
+} // detail
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/detail/ostream.hpp b/boost/beast/core/detail/ostream.hpp
new file mode 100644
index 0000000000..8d6eb94f51
--- /dev/null
+++ b/boost/beast/core/detail/ostream.hpp
@@ -0,0 +1,319 @@
+//
+// Copyright (c) 2016-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_OSTREAM_HPP
+#define BOOST_BEAST_DETAIL_OSTREAM_HPP
+
+#include <boost/beast/core/buffers_prefix.hpp>
+#include <boost/beast/core/read_size.hpp>
+#include <boost/beast/core/detail/type_traits.hpp>
+#include <boost/asio/buffer.hpp>
+#include <memory>
+#include <iosfwd>
+#include <streambuf>
+#include <type_traits>
+#include <utility>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+template<class Buffers>
+class buffers_helper
+{
+ Buffers b_;
+
+public:
+ explicit
+ buffers_helper(Buffers const& b)
+ : b_(b)
+ {
+ }
+
+ template<class B>
+ friend
+ std::ostream&
+ operator<<(std::ostream& os,
+ buffers_helper<B> const& v);
+};
+
+template<class Buffers>
+std::ostream&
+operator<<(std::ostream& os,
+ buffers_helper<Buffers> const& v)
+{
+ for(auto b : buffers_range(v.b_))
+ os.write(
+ reinterpret_cast<char const*>(b.data()),
+ b.size());
+ return os;
+}
+
+//------------------------------------------------------------------------------
+
+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>
+ : 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;
+
+ static std::size_t constexpr max_size = 512;
+
+ DynamicBuffer& buf_;
+
+public:
+ ostream_buffer(ostream_buffer&&) = default;
+ ostream_buffer(ostream_buffer const&) = delete;
+
+ ~ostream_buffer() noexcept
+ {
+ sync();
+ }
+
+ explicit
+ ostream_buffer(DynamicBuffer& buf)
+ : buf_(buf)
+ {
+ prepare();
+ }
+
+ 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()
+ {
+ auto bs = buf_.prepare(
+ read_size_or_throw(buf_, max_size));
+ auto const b = buffers_front(bs);
+ auto const p = reinterpret_cast<CharT*>(b.data());
+ this->setp(p,
+ p + b.size() / sizeof(CharT) - 1);
+ }
+
+ void
+ flush(int extra = 0)
+ {
+ buf_.commit(
+ (this->pptr() - this->pbase() + extra) *
+ sizeof(CharT));
+ }
+};
+
+// 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;
+
+ static std::size_t constexpr max_size = 512;
+
+ DynamicBuffer& buf_;
+
+public:
+ ostream_buffer(ostream_buffer&&) = delete;
+ ostream_buffer(ostream_buffer const&) = delete;
+
+ ~ostream_buffer() noexcept
+ {
+ sync();
+ }
+
+ explicit
+ ostream_buffer(DynamicBuffer& buf)
+ : buf_(buf)
+ {
+ prepare();
+ }
+
+ 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()
+ {
+ auto bs = buf_.prepare(
+ read_size_or_throw(buf_, max_size));
+ auto const b = buffers_front(bs);
+ auto const p = reinterpret_cast<CharT*>(b.data());
+ this->setp(p,
+ p + b.size() / sizeof(CharT) - 1);
+ }
+
+ void
+ flush(int extra = 0)
+ {
+ buf_.commit(
+ (this->pptr() - this->pbase() + extra) *
+ sizeof(CharT));
+ }
+};
+
+//------------------------------------------------------------------------------
+
+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& buf);
+
+ ostream_helper(ostream_helper&& other);
+};
+
+template<class DynamicBuffer, class CharT, class Traits>
+ostream_helper<DynamicBuffer, CharT, Traits, true>::
+ostream_helper(DynamicBuffer& buf)
+ : std::basic_ostream<CharT, Traits>(
+ &this->osb_)
+ , osb_(buf)
+{
+}
+
+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& buf)
+ : ostream_helper_base<ostream_buffer<
+ DynamicBuffer, CharT, Traits, false>>(
+ new ostream_buffer<DynamicBuffer,
+ CharT, Traits, false>(buf))
+ , 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
diff --git a/boost/beast/core/detail/sha1.hpp b/boost/beast/core/detail/sha1.hpp
new file mode 100644
index 0000000000..336da2a0f2
--- /dev/null
+++ b/boost/beast/core/detail/sha1.hpp
@@ -0,0 +1,313 @@
+//
+// Copyright (c) 2016-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_SHA1_HPP
+#define BOOST_BEAST_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 {
+
+static std::size_t constexpr BLOCK_INTS = 16;
+static std::size_t constexpr BLOCK_BYTES = 64;
+static std::size_t constexpr DIGEST_BYTES = 20;
+
+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;
+}
+
+template<class = void>
+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
+
+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];
+};
+
+template<class = void>
+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;
+}
+
+template<class = void>
+void
+update(sha1_context& ctx,
+ void const* message, std::size_t size) noexcept
+{
+ auto p = reinterpret_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;
+ }
+}
+
+template<class = void>
+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 =
+ reinterpret_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
diff --git a/boost/beast/core/detail/static_ostream.hpp b/boost/beast/core/detail/static_ostream.hpp
new file mode 100644
index 0000000000..cb5a00b3da
--- /dev/null
+++ b/boost/beast/core/detail/static_ostream.hpp
@@ -0,0 +1,142 @@
+//
+// Copyright (c) 2016-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_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
diff --git a/boost/beast/core/detail/static_string.hpp b/boost/beast/core/detail/static_string.hpp
new file mode 100644
index 0000000000..a5384591ff
--- /dev/null
+++ b/boost/beast/core/detail/static_string.hpp
@@ -0,0 +1,135 @@
+//
+// Copyright (c) 2016-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_STATIC_STRING_HPP
+#define BOOST_BEAST_DETAIL_STATIC_STRING_HPP
+
+#include <boost/beast/core/string.hpp>
+#include <boost/assert.hpp>
+#include <iterator>
+#include <type_traits>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+// Because k-ballo said so
+template<class T>
+using is_input_iterator =
+ std::integral_constant<bool,
+ ! std::is_integral<T>::value>;
+
+template<class CharT, class Traits>
+int
+lexicographical_compare(
+ CharT const* s1, std::size_t n1,
+ CharT const* s2, std::size_t n2)
+{
+ if(n1 < n2)
+ return Traits::compare(
+ s1, s2, n1) <= 0 ? -1 : 1;
+ if(n1 > n2)
+ return Traits::compare(
+ s1, s2, n2) >= 0 ? 1 : -1;
+ return Traits::compare(s1, s2, n1);
+}
+
+template<class CharT, class Traits>
+inline
+int
+lexicographical_compare(
+ basic_string_view<CharT, Traits> s1,
+ CharT const* s2, std::size_t n2)
+{
+ return lexicographical_compare<CharT, Traits>(
+ s1.data(), s1.size(), s2, n2);
+}
+
+template<class CharT, class Traits>
+inline
+int
+lexicographical_compare(
+ basic_string_view<CharT, Traits> s1,
+ basic_string_view<CharT, Traits> s2)
+{
+ return lexicographical_compare<CharT, Traits>(
+ s1.data(), s1.size(), s2.data(), s2.size());
+}
+
+// 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
diff --git a/boost/beast/core/detail/type_traits.hpp b/boost/beast/core/detail/type_traits.hpp
new file mode 100644
index 0000000000..06fbda291d
--- /dev/null
+++ b/boost/beast/core/detail/type_traits.hpp
@@ -0,0 +1,353 @@
+//
+// Copyright (c) 2016-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_TYPE_TRAITS_HPP
+#define BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP
+
+#include <boost/beast/core/error.hpp>
+#include <boost/asio/buffer.hpp>
+#include <iterator>
+#include <tuple>
+#include <type_traits>
+#include <string>
+#include <utility>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+//
+// utilities
+//
+
+template<class... Ts>
+struct make_void
+{
+ using type = void;
+};
+
+template<class... Ts>
+using void_t = typename make_void<Ts...>::type;
+
+template<class T>
+inline
+void
+accept_rv(T){}
+
+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...>();
+}
+
+template<unsigned N, class T, class... Tn>
+struct repeat_tuple_impl
+{
+ using type = typename repeat_tuple_impl<
+ N - 1, T, T, Tn...>::type;
+};
+
+template<class T, class... Tn>
+struct repeat_tuple_impl<0, T, Tn...>
+{
+ using type = std::tuple<T, Tn...>;
+};
+
+template<unsigned N, class T>
+struct repeat_tuple
+{
+ using type =
+ typename repeat_tuple_impl<N-1, T>::type;
+};
+
+template<class T>
+struct repeat_tuple<0, T>
+{
+ using type = std::tuple<>;
+};
+
+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)>
+ @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>()...))
+{
+};
+/** @} */
+
+// for span
+template<class T, class E, class = void>
+struct is_contiguous_container: std::false_type {};
+
+template<class T, class E>
+struct is_contiguous_container<T, E, void_t<
+ decltype(
+ std::declval<std::size_t&>() = std::declval<T const&>().size(),
+ std::declval<E*&>() = std::declval<T&>().data(),
+ (void)0),
+ typename std::enable_if<
+ std::is_same<
+ typename std::remove_cv<E>::type,
+ typename std::remove_cv<
+ typename std::remove_pointer<
+ decltype(std::declval<T&>().data())
+ >::type
+ >::type
+ >::value
+ >::type>>: std::true_type
+{};
+
+template<class...>
+struct unwidest_unsigned;
+
+template<class U0>
+struct unwidest_unsigned<U0>
+{
+ using type = U0;
+};
+
+template<class U0, class... UN>
+struct unwidest_unsigned<U0, UN...>
+{
+ BOOST_STATIC_ASSERT(std::is_unsigned<U0>::value);
+ using type = typename std::conditional<
+ (sizeof(U0) < sizeof(typename unwidest_unsigned<UN...>::type)),
+ U0, typename unwidest_unsigned<UN...>::type>::type;
+};
+
+template<class...>
+struct widest_unsigned;
+
+template<class U0>
+struct widest_unsigned<U0>
+{
+ using type = U0;
+};
+
+template<class U0, class... UN>
+struct widest_unsigned<U0, UN...>
+{
+ BOOST_STATIC_ASSERT(std::is_unsigned<U0>::value);
+ using type = typename std::conditional<
+ (sizeof(U0) > sizeof(typename widest_unsigned<UN...>::type)),
+ U0, typename widest_unsigned<UN...>::type>::type;
+};
+
+template<class U>
+inline
+constexpr
+U
+min_all(U u)
+{
+ BOOST_STATIC_ASSERT(std::is_unsigned<U>::value);
+ return u;
+}
+
+template<class U0, class U1, class... UN>
+inline
+constexpr
+typename unwidest_unsigned<U0, U1, UN...>::type
+min_all(U0 u0, U1 u1, UN... un)
+{
+ using type =
+ typename unwidest_unsigned<U0, U1, UN...>::type;
+ return u0 < u1 ?
+ static_cast<type>(min_all(u0, un...)) :
+ static_cast<type>(min_all(u1, un...));
+}
+
+template<class U>
+inline
+constexpr
+U
+max_all(U u)
+{
+ BOOST_STATIC_ASSERT(std::is_unsigned<U>::value);
+ return u;
+}
+
+template<class U0, class U1, class... UN>
+inline
+constexpr
+typename widest_unsigned<U0, U1, UN...>::type
+max_all(U0 u0, U1 u1, UN... un)
+{
+ return u0 > u1? max_all(u0, un...) : max_all(u1, un...);
+}
+
+//------------------------------------------------------------------------------
+
+//
+// buffer concepts
+//
+
+// 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();
+ BufferSequence(BufferSequence const&) = default;
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+};
+using ConstBufferSequence =
+ BufferSequence<boost::asio::const_buffer>;
+using MutableBufferSequence =
+ BufferSequence<boost::asio::mutable_buffer>;
+
+template<class B1, class... Bn>
+struct is_all_const_buffer_sequence
+ : std::integral_constant<bool,
+ boost::asio::is_const_buffer_sequence<B1>::value &&
+ is_all_const_buffer_sequence<Bn...>::value>
+{
+};
+
+template<class B>
+struct is_all_const_buffer_sequence<B>
+ : boost::asio::is_const_buffer_sequence<B>
+{
+};
+
+template<class... Bn>
+struct common_buffers_type
+{
+ using type = typename std::conditional<
+ std::is_convertible<std::tuple<Bn...>,
+ typename repeat_tuple<sizeof...(Bn),
+ boost::asio::mutable_buffer>::type>::value,
+ boost::asio::mutable_buffer,
+ boost::asio::const_buffer>::type;
+};
+
+template<class B>
+struct buffer_sequence_iterator
+{
+ using type = decltype(
+ boost::asio::buffer_sequence_begin(
+ std::declval<B const&>()));
+};
+
+// Types that meet the requirements,
+// for use with std::declval only.
+struct StreamHandler
+{
+ StreamHandler(StreamHandler const&) = default;
+ void operator()(error_code ec, std::size_t);
+};
+using ReadHandler = StreamHandler;
+using WriteHandler = StreamHandler;
+
+template<class Buffers>
+class buffers_range_adapter
+{
+ Buffers const& b_;
+
+public:
+ using value_type = typename std::conditional<
+ std::is_convertible<typename std::iterator_traits<
+ typename buffer_sequence_iterator<Buffers>::type>::value_type,
+ boost::asio::const_buffer>::value,
+ boost::asio::const_buffer,
+ boost::asio::mutable_buffer>::type;
+
+ /* VFALCO This isn't right, because range-for will pick up the iterator's
+ value_type which might not be const_buffer or mutable_buffer. We
+ need to declare our own iterator wrapper that converts the underlying
+ iterator's value_type to const_buffer or mutable_buffer so that
+ range-for sees one of those types.
+ */
+ using const_iterator = typename
+ buffer_sequence_iterator<Buffers>::type;
+
+ explicit
+ buffers_range_adapter(Buffers const& b)
+ : b_(b)
+ {
+ }
+
+ const_iterator
+ begin() const noexcept
+ {
+ return boost::asio::buffer_sequence_begin(b_);
+ }
+
+ const_iterator
+ end() const noexcept
+ {
+ return boost::asio::buffer_sequence_end(b_);
+ }
+};
+
+template<class Buffers>
+buffers_range_adapter<Buffers>
+buffers_range(Buffers const& buffers)
+{
+ return buffers_range_adapter<Buffers>{buffers};
+}
+
+} // detail
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/detail/variant.hpp b/boost/beast/core/detail/variant.hpp
new file mode 100644
index 0000000000..cba6ba63c0
--- /dev/null
+++ b/boost/beast/core/detail/variant.hpp
@@ -0,0 +1,195 @@
+//
+// Copyright (c) 2016-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_VARIANT_HPP
+#define BOOST_BEAST_DETAIL_VARIANT_HPP
+
+#include <boost/beast/core/detail/type_traits.hpp>
+#include <boost/assert.hpp>
+#include <cstddef>
+#include <tuple>
+#include <type_traits>
+
+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
+{
+ typename std::aligned_storage<
+ max_sizeof<TN...>(),
+ max_alignof<TN...>()
+ >::type buf_;
+ unsigned char i_ = 0;
+
+ template<std::size_t I>
+ using type = typename std::tuple_element<
+ I , std::tuple<TN...>>::type;
+
+ template<std::size_t I>
+ using C = std::integral_constant<std::size_t, I>;
+
+public:
+ variant() = default;
+
+ ~variant()
+ {
+ if(i_)
+ destroy(C<0>{});
+ }
+
+ // 0 = empty
+ unsigned char
+ index() const
+ {
+ return i_;
+ }
+
+ // moved-from object becomes empty
+ variant(variant&& other)
+ {
+ i_ = other.move(&buf_, C<0>{});
+ }
+
+ variant(variant const& other)
+ {
+ i_ = other.copy(&buf_, C<0>{});
+ }
+
+ // moved-from object becomes empty
+ variant& operator=(variant&& other)
+ {
+ if(i_ != 0)
+ destroy(C<0>{});
+ i_ = other.move(&buf_, C<0>{});
+ return *this;
+ }
+
+ variant& operator=(variant const& other)
+ {
+ if(i_ != 0)
+ destroy(C<0>{});
+ i_ = other.copy(&buf_, C<0>{});
+ return *this;
+ }
+
+ template<std::size_t I, class... Args>
+ void
+ emplace(Args&&... args)
+ {
+ if(i_ != 0)
+ destroy(C<0>{});
+ new(&buf_) type<I-1>(
+ std::forward<Args>(args)...);
+ i_ = I;
+ }
+
+ template<std::size_t I>
+ type<I-1>&
+ get()
+ {
+ BOOST_ASSERT(i_ == I);
+ return *reinterpret_cast<
+ type<I-1>*>(&buf_);
+ }
+
+ template<std::size_t I>
+ type<I-1> const&
+ get() const
+ {
+ BOOST_ASSERT(i_ == I);
+ return *reinterpret_cast<
+ type<I-1> const*>(&buf_);
+ }
+
+ void
+ reset()
+ {
+ if(i_ == 0)
+ return;
+ destroy(C<0>{});
+ }
+
+private:
+ void
+ destroy(C<sizeof...(TN)>)
+ {
+ return;
+ }
+
+ template<std::size_t I>
+ void
+ destroy(C<I>)
+ {
+ if(i_ == I+1)
+ {
+ using T = type<I>;
+ get<I+1>().~T();
+ i_ = 0;
+ return;
+ }
+ destroy(C<I+1>{});
+ }
+
+ unsigned char
+ move(void*, C<sizeof...(TN)>)
+ {
+ return 0;
+ }
+
+ template<std::size_t I>
+ unsigned char
+ move(void* dest, C<I>)
+ {
+ if(i_ == I+1)
+ {
+ using T = type<I>;
+ new(dest) T{std::move(get<I+1>())};
+ get<I+1>().~T();
+ i_ = 0;
+ return I+1;
+ }
+ return move(dest, C<I+1>{});
+ }
+
+ unsigned char
+ copy(void*, C<sizeof...(TN)>) const
+ {
+ return 0;
+ }
+
+ template<std::size_t I>
+ unsigned char
+ copy(void* dest, C<I>) const
+ {
+ if(i_ == I+1)
+ {
+ using T = type<I>;
+ auto const& t = get<I+1>();
+ new(dest) T{t};
+ return I+1;
+ }
+ return copy(dest, C<I+1>{});
+ }
+};
+
+} // detail
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/detail/varint.hpp b/boost/beast/core/detail/varint.hpp
new file mode 100644
index 0000000000..37f0b9d1c1
--- /dev/null
+++ b/boost/beast/core/detail/varint.hpp
@@ -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