Use custom variant

This commit is contained in:
Vinnie Falco
2017-07-20 22:54:54 -07:00
parent b97586b318
commit 7317bd0de9
8 changed files with 275 additions and 109 deletions

View File

@ -201,7 +201,6 @@ install:
- git submodule update --init libs/typeof
- git submodule update --init libs/unordered
- git submodule update --init libs/utility
- git submodule update --init libs/variant
- git submodule update --init libs/winapi
- rm -rf libs/beast
- mkdir libs/beast

View File

@ -2,6 +2,7 @@ Version 86:
* Boost prep
* Remove use of lexical_cast
* Use custom variant
--------------------------------------------------------------------------------

View File

@ -87,7 +87,6 @@ install:
- git submodule update --init libs/typeof
- git submodule update --init libs/unordered
- git submodule update --init libs/utility
- git submodule update --init libs/variant
- git submodule update --init libs/winapi
- bootstrap
- b2 headers

View File

@ -7,8 +7,8 @@
// Official repository: https://github.com/boostorg/beast
//
#ifndef BOOST_BEAST_BIND_DETAIL_HANDLER_HPP
#define BOOST_BEAST_BIND_DETAIL_HANDLER_HPP
#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/handler_alloc_hook.hpp>

View File

@ -0,0 +1,184 @@
//
// Copyright (c) 2013-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...>()>::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>{});
}
variant(variant&& other)
{
i_ = other.move(&buf_, C<0>{});
}
variant(variant const& other)
{
i_ = other.copy(&buf_, C<0>{});
}
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>{});
i_ = 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>&
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();
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;
}
move(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;
}
copy(C<I+1>{});
}
};
} // detail
} // beast
} // boost
#endif

View File

@ -41,18 +41,16 @@ frdinit(std::false_type)
template<
bool isRequest, class Body, class Fields>
template<class T1, class T2, class Visit>
template<std::size_t I, class Visit>
inline
void
serializer<isRequest, Body, Fields>::
do_visit(error_code& ec, Visit& visit)
{
// VFALCO work-around for missing variant::emplace
pv_.~variant();
new(&pv_) decltype(pv_){
T1{limit_, boost::get<T2>(v_)}};
visit(ec, beast::detail::make_buffers_ref(
boost::get<T1>(pv_)));
pv_.template emplace<I>(limit_, v_.template get<I>());
visit(ec,
beast::detail::make_buffers_ref(
pv_.template get<I>()));
}
//------------------------------------------------------------------------------
@ -104,23 +102,23 @@ next(error_code& ec, Visit&& visit)
if(! result)
goto go_header_only;
more_ = result->second;
v_ = cb2_t{
v_.template emplace<2>(
boost::in_place_init,
frd_->get(),
result->first};
result->first);
s_ = do_header;
BOOST_BEAST_FALLTHROUGH;
}
case do_header:
do_visit<pcb2_t, cb2_t>(ec, visit);
do_visit<2>(ec, visit);
break;
go_header_only:
v_ = cb1_t{frd_->get()};
v_.template emplace<1>(frd_->get());
s_ = do_header_only;
case do_header_only:
do_visit<pcb1_t, cb1_t>(ec, visit);
do_visit<1>(ec, visit);
break;
case do_body:
@ -135,13 +133,13 @@ next(error_code& ec, Visit&& visit)
if(! result)
goto go_complete;
more_ = result->second;
v_ = cb3_t{result->first};
v_.template emplace<3>(result->first);
s_ = do_body + 2;
BOOST_BEAST_FALLTHROUGH;
}
case do_body + 2:
do_visit<pcb3_t, cb3_t>(ec, visit);
do_visit<3>(ec, visit);
break;
//----------------------------------------------------------------------
@ -163,11 +161,10 @@ next(error_code& ec, Visit&& visit)
if(! result)
goto go_header_only_c;
more_ = result->second;
#ifndef BOOST_BEAST_NO_BIG_VARIANTS
if(! more_)
{
// do it all in one buffer
v_ = cb7_t{
v_.template emplace<7>(
boost::in_place_init,
frd_->get(),
buffer_size(result->first),
@ -177,31 +174,30 @@ next(error_code& ec, Visit&& visit)
chunk_crlf{},
detail::chunk_last(),
boost::asio::const_buffers_1{nullptr, 0},
chunk_crlf{}};
chunk_crlf{});
goto go_all_c;
}
#endif
v_ = cb4_t{
v_.template emplace<4>(
boost::in_place_init,
frd_->get(),
buffer_size(result->first),
boost::asio::const_buffers_1{nullptr, 0},
chunk_crlf{},
result->first,
chunk_crlf{}};
chunk_crlf{});
s_ = do_header_c;
BOOST_BEAST_FALLTHROUGH;
}
case do_header_c:
do_visit<pcb4_t, cb4_t>(ec, visit);
do_visit<4>(ec, visit);
break;
go_header_only_c:
v_ = cb1_t{frd_->get()};
v_.template emplace<1>(frd_->get());
s_ = do_header_only_c;
case do_header_only_c:
do_visit<pcb1_t, cb1_t>(ec, visit);
do_visit<1>(ec, visit);
break;
case do_body_c:
@ -216,11 +212,10 @@ next(error_code& ec, Visit&& visit)
if(! result)
goto go_final_c;
more_ = result->second;
#ifndef BOOST_BEAST_NO_BIG_VARIANTS
if(! more_)
{
// do it all in one buffer
v_ = cb6_t{
v_.template emplace<6>(
boost::in_place_init,
buffer_size(result->first),
boost::asio::const_buffers_1{nullptr, 0},
@ -229,51 +224,48 @@ next(error_code& ec, Visit&& visit)
chunk_crlf{},
detail::chunk_last(),
boost::asio::const_buffers_1{nullptr, 0},
chunk_crlf{}};
chunk_crlf{});
goto go_body_final_c;
}
#endif
v_ = cb5_t{
v_.template emplace<5>(
boost::in_place_init,
buffer_size(result->first),
boost::asio::const_buffers_1{nullptr, 0},
chunk_crlf{},
result->first,
chunk_crlf{}};
chunk_crlf{});
s_ = do_body_c + 2;
BOOST_BEAST_FALLTHROUGH;
}
case do_body_c + 2:
do_visit<pcb5_t, cb5_t>(ec, visit);
do_visit<5>(ec, visit);
break;
#ifndef BOOST_BEAST_NO_BIG_VARIANTS
go_body_final_c:
s_ = do_body_final_c;
case do_body_final_c:
do_visit<pcb6_t, cb6_t>(ec, visit);
do_visit<6>(ec, visit);
break;
go_all_c:
s_ = do_all_c;
case do_all_c:
do_visit<pcb7_t, cb7_t>(ec, visit);
do_visit<7>(ec, visit);
break;
#endif
go_final_c:
case do_final_c:
v_ = cb8_t{
v_.template emplace<8>(
boost::in_place_init,
detail::chunk_last(),
boost::asio::const_buffers_1{nullptr, 0},
chunk_crlf{}};
chunk_crlf{});
s_ = do_final_c + 1;
BOOST_BEAST_FALLTHROUGH;
case do_final_c + 1:
do_visit<pcb8_t, cb8_t>(ec, visit);
do_visit<8>(ec, visit);
break;
//----------------------------------------------------------------------
@ -299,23 +291,23 @@ consume(std::size_t n)
switch(s_)
{
case do_header:
BOOST_ASSERT(n <= buffer_size(
boost::get<cb2_t>(v_)));
boost::get<cb2_t>(v_).consume(n);
if(buffer_size(boost::get<cb2_t>(v_)) > 0)
BOOST_ASSERT(
n <= buffer_size(v_.template get<2>()));
v_.template get<2>().consume(n);
if(buffer_size(v_.template get<2>()) > 0)
break;
header_done_ = true;
v_ = boost::blank{};
v_.reset();
if(! more_)
goto go_complete;
s_ = do_body + 1;
break;
case do_header_only:
BOOST_ASSERT(n <= buffer_size(
boost::get<cb1_t>(v_)));
boost::get<cb1_t>(v_).consume(n);
if(buffer_size(boost::get<cb1_t>(v_)) > 0)
BOOST_ASSERT(
n <= buffer_size(v_.template get<1>()));
v_.template get<1>().consume(n);
if(buffer_size(v_.template get<1>()) > 0)
break;
frd_ = boost::none;
header_done_ = true;
@ -326,12 +318,12 @@ consume(std::size_t n)
case do_body + 2:
{
BOOST_ASSERT(n <= buffer_size(
boost::get<cb3_t>(v_)));
boost::get<cb3_t>(v_).consume(n);
if(buffer_size(boost::get<cb3_t>(v_)) > 0)
BOOST_ASSERT(
n <= buffer_size(v_.template get<3>()));
v_.template get<3>().consume(n);
if(buffer_size(v_.template get<3>()) > 0)
break;
v_ = boost::blank{};
v_.reset();
if(! more_)
goto go_complete;
s_ = do_body + 1;
@ -341,13 +333,13 @@ consume(std::size_t n)
//----------------------------------------------------------------------
case do_header_c:
BOOST_ASSERT(n <= buffer_size(
boost::get<cb4_t>(v_)));
boost::get<cb4_t>(v_).consume(n);
if(buffer_size(boost::get<cb4_t>(v_)) > 0)
BOOST_ASSERT(
n <= buffer_size(v_.template get<4>()));
v_.template get<4>().consume(n);
if(buffer_size(v_.template get<4>()) > 0)
break;
header_done_ = true;
v_ = boost::blank{};
v_.reset();
if(more_)
s_ = do_body_c + 1;
else
@ -356,10 +348,10 @@ consume(std::size_t n)
case do_header_only_c:
{
BOOST_ASSERT(n <= buffer_size(
boost::get<cb1_t>(v_)));
boost::get<cb1_t>(v_).consume(n);
if(buffer_size(boost::get<cb1_t>(v_)) > 0)
BOOST_ASSERT(
n <= buffer_size(v_.template get<1>()));
v_.template get<1>().consume(n);
if(buffer_size(v_.template get<1>()) > 0)
break;
frd_ = boost::none;
header_done_ = true;
@ -373,52 +365,49 @@ consume(std::size_t n)
}
case do_body_c + 2:
BOOST_ASSERT(n <= buffer_size(
boost::get<cb5_t>(v_)));
boost::get<cb5_t>(v_).consume(n);
if(buffer_size(boost::get<cb5_t>(v_)) > 0)
BOOST_ASSERT(
n <= buffer_size(v_.template get<5>()));
v_.template get<5>().consume(n);
if(buffer_size(v_.template get<5>()) > 0)
break;
v_ = boost::blank{};
v_.reset();
if(more_)
s_ = do_body_c + 1;
else
s_ = do_final_c;
break;
#ifndef BOOST_BEAST_NO_BIG_VARIANTS
case do_body_final_c:
{
auto& b = boost::get<cb6_t>(v_);
BOOST_ASSERT(n <= buffer_size(b));
b.consume(n);
if(buffer_size(b) > 0)
BOOST_ASSERT(
n <= buffer_size(v_.template get<6>()));
v_.template get<6>().consume(n);
if(buffer_size(v_.template get<6>()) > 0)
break;
v_ = boost::blank{};
v_.reset();
s_ = do_complete;
break;
}
case do_all_c:
{
auto& b = boost::get<cb7_t>(v_);
BOOST_ASSERT(n <= buffer_size(b));
b.consume(n);
if(buffer_size(b) > 0)
BOOST_ASSERT(
n <= buffer_size(v_.template get<7>()));
v_.template get<7>().consume(n);
if(buffer_size(v_.template get<7>()) > 0)
break;
header_done_ = true;
v_ = boost::blank{};
v_.reset();
s_ = do_complete;
break;
}
#endif
case do_final_c + 1:
BOOST_ASSERT(buffer_size(
boost::get<cb8_t>(v_)));
boost::get<cb8_t>(v_).consume(n);
if(buffer_size(boost::get<cb8_t>(v_)) > 0)
BOOST_ASSERT(buffer_size(v_.template get<8>()));
v_.template get<8>().consume(n);
if(buffer_size(v_.template get<8>()) > 0)
break;
v_ = boost::blank{};
v_.reset();
goto go_complete;
//----------------------------------------------------------------------

View File

@ -16,17 +16,11 @@
#include <boost/beast/core/consuming_buffers.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/core/detail/variant.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/chunk_encode.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
#include <boost/variant.hpp>
#ifndef BOOST_BEAST_NO_BIG_VARIANTS
# if defined(BOOST_GCC) && BOOST_GCC < 50000 && BOOST_VERSION < 106600
# define BOOST_BEAST_NO_BIG_VARIANTS
# endif
#endif
namespace boost {
namespace beast {
@ -116,7 +110,7 @@ private:
void frdinit(std::true_type);
void frdinit(std::false_type);
template<class T1, class T2, class Visit>
template<std::size_t, class Visit>
void
do_visit(error_code& ec, Visit& visit);
@ -152,7 +146,6 @@ private:
chunk_crlf>>; // crlf
using pcb5_t = buffer_prefix_view<cb5_t const&>;
#ifndef BOOST_BEAST_NO_BIG_VARIANTS
using cb6_t = consuming_buffers<buffer_cat_view<
detail::chunk_size, // chunk-header
boost::asio::const_buffers_1, // chunk-size
@ -175,7 +168,6 @@ private:
boost::asio::const_buffers_1, // trailers
chunk_crlf>>; // crlf
using pcb7_t = buffer_prefix_view<cb7_t const&>;
#endif
using cb8_t = consuming_buffers<buffer_cat_view<
boost::asio::const_buffers_1, // chunk-final
@ -186,18 +178,12 @@ private:
value_type& m_;
reader rd_;
boost::optional<typename Fields::reader> frd_;
boost::variant<boost::blank,
cb1_t, cb2_t, cb3_t, cb4_t, cb5_t
#ifndef BOOST_BEAST_NO_BIG_VARIANTS
,cb6_t, cb7_t
#endif
, cb8_t> v_;
boost::variant<boost::blank,
pcb1_t, pcb2_t, pcb3_t, pcb4_t, pcb5_t
#ifndef BOOST_BEAST_NO_BIG_VARIANTS
,pcb6_t, pcb7_t
#endif
, pcb8_t> pv_;
beast::detail::variant<
cb1_t, cb2_t, cb3_t, cb4_t,
cb5_t ,cb6_t, cb7_t, cb8_t> v_;
beast::detail::variant<
pcb1_t, pcb2_t, pcb3_t, pcb4_t,
pcb5_t ,pcb6_t, pcb7_t, pcb8_t> pv_;
std::size_t limit_ =
(std::numeric_limits<std::size_t>::max)();
int s_ = do_construct;
@ -208,6 +194,15 @@ private:
bool more_;
public:
/// Constructor
serializer(serializer&&) = default;
/// Constructor
serializer(serializer const&) = default;
/// Assignment
serializer& operator=(serializer const&) = delete;
/** Constructor
The implementation guarantees that the message passed on

View File

@ -20,7 +20,6 @@
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/async_result.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/variant.hpp>
#include <iosfwd>
#include <limits>
#include <memory>