diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2019-12-05 15:11:01 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2019-12-05 15:11:01 +0900 |
commit | 3fdc3e5ee96dca5b11d1694975a65200787eab86 (patch) | |
tree | 5c1733853892b8397d67706fa453a9bd978d2102 /boost/beast/core/detail | |
parent | 88e602c57797660ebe0f9e15dbd64c1ff16dead3 (diff) | |
download | boost-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.hpp | 42 | ||||
-rw-r--r-- | boost/beast/core/detail/base64.hpp | 251 | ||||
-rw-r--r-- | boost/beast/core/detail/bind_handler.hpp | 189 | ||||
-rw-r--r-- | boost/beast/core/detail/buffers_ref.hpp | 67 | ||||
-rw-r--r-- | boost/beast/core/detail/clamp.hpp | 59 | ||||
-rw-r--r-- | boost/beast/core/detail/config.hpp | 57 | ||||
-rw-r--r-- | boost/beast/core/detail/cpu_info.hpp | 99 | ||||
-rw-r--r-- | boost/beast/core/detail/empty_base_optimization.hpp | 100 | ||||
-rw-r--r-- | boost/beast/core/detail/in_place_init.hpp | 43 | ||||
-rw-r--r-- | boost/beast/core/detail/integer_sequence.hpp | 143 | ||||
-rw-r--r-- | boost/beast/core/detail/ostream.hpp | 319 | ||||
-rw-r--r-- | boost/beast/core/detail/sha1.hpp | 313 | ||||
-rw-r--r-- | boost/beast/core/detail/static_ostream.hpp | 142 | ||||
-rw-r--r-- | boost/beast/core/detail/static_string.hpp | 135 | ||||
-rw-r--r-- | boost/beast/core/detail/type_traits.hpp | 353 | ||||
-rw-r--r-- | boost/beast/core/detail/variant.hpp | 195 | ||||
-rw-r--r-- | boost/beast/core/detail/varint.hpp | 79 |
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 |