Make decorator copyable

This commit is contained in:
Vinnie Falco
2017-01-25 09:38:29 -05:00
parent c594bbac3f
commit 99706347cd
4 changed files with 62 additions and 9 deletions

View File

@@ -3,6 +3,7 @@
* bjam use clang on MACOSX * bjam use clang on MACOSX
* Simplify Travis package install specification * Simplify Travis package install specification
* Add optional yield_to arguments * Add optional yield_to arguments
* Make decorator copyable
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@@ -12,6 +12,7 @@
#include <beast/http/message.hpp> #include <beast/http/message.hpp>
#include <beast/http/string_body.hpp> #include <beast/http/string_body.hpp>
#include <beast/version.hpp> #include <beast/version.hpp>
#include <type_traits>
#include <utility> #include <utility>
namespace beast { namespace beast {
@@ -27,13 +28,17 @@ struct abstract_decorator
virtual virtual
~abstract_decorator() = default; ~abstract_decorator() = default;
virtual
abstract_decorator*
copy() = 0;
virtual virtual
void void
operator()(request_type& req) = 0; operator()(request_type& req) = 0;
virtual virtual
void void
operator()(response_type& resp) = 0; operator()(response_type& res) = 0;
}; };
template<class T> template<class T>
@@ -69,6 +74,7 @@ class decorator : public abstract_decorator
public: public:
decorator() = default; decorator() = default;
decorator(decorator const&) = default;
decorator(T&& t) decorator(T&& t)
: t_(std::move(t)) : t_(std::move(t))
@@ -80,6 +86,12 @@ public:
{ {
} }
abstract_decorator*
copy() override
{
return new decorator(*this);
}
void void
operator()(request_type& req) override operator()(request_type& req) override
{ {
@@ -87,9 +99,9 @@ public:
} }
void void
operator()(response_type& resp) override operator()(response_type& res) override
{ {
(*this)(resp, typename call_res_possible::type{}); (*this)(res, typename call_res_possible::type{});
} }
private: private:
@@ -124,8 +136,48 @@ struct default_decorator
{ {
}; };
using decorator_type = class decorator_type
std::unique_ptr<abstract_decorator>; {
std::unique_ptr<abstract_decorator> p_;
public:
decorator_type(decorator_type&&) = default;
decorator_type& operator=(decorator_type&&) = default;
decorator_type(decorator_type const& other)
: p_(other.p_->copy())
{
}
decorator_type&
operator=(decorator_type const& other)
{
p_ = std::unique_ptr<
abstract_decorator>{other.p_->copy()};
return *this;
}
template<class T, class =
typename std::enable_if<! std::is_same<
typename std::decay<T>::type,
decorator_type>::value>>
decorator_type(T&& t)
: p_(new decorator<T>{std::forward<T>(t)})
{
}
void
operator()(request_type& req)
{
(*p_)(req);
}
void
operator()(response_type& res)
{
(*p_)(res);
}
};
} // detail } // detail
} // websocket } // websocket

View File

@@ -128,7 +128,7 @@ protected:
stream_base& operator=(stream_base const&) = delete; stream_base& operator=(stream_base const&) = delete;
stream_base() stream_base()
: d_(new decorator<default_decorator>{}) : d_(detail::default_decorator{})
{ {
} }

View File

@@ -72,7 +72,7 @@ build_request(boost::string_ref const& host,
key = detail::make_sec_ws_key(maskgen_); key = detail::make_sec_ws_key(maskgen_);
req.fields.insert("Sec-WebSocket-Key", key); req.fields.insert("Sec-WebSocket-Key", key);
req.fields.insert("Sec-WebSocket-Version", "13"); req.fields.insert("Sec-WebSocket-Version", "13");
(*d_)(req); d_(req);
http::prepare(req, http::connection::upgrade); http::prepare(req, http::connection::upgrade);
return req; return req;
} }
@@ -91,7 +91,7 @@ build_response(http::request<Body, Fields> const& req)
res.reason = http::reason_string(res.status); res.reason = http::reason_string(res.status);
res.version = req.version; res.version = req.version;
res.body = text; res.body = text;
(*d_)(res); d_(res);
prepare(res, prepare(res,
(is_keep_alive(req) && keep_alive_) ? (is_keep_alive(req) && keep_alive_) ?
http::connection::keep_alive : http::connection::keep_alive :
@@ -141,7 +141,7 @@ build_response(http::request<Body, Fields> const& req)
detail::make_sec_ws_accept(key)); detail::make_sec_ws_accept(key));
} }
res.fields.replace("Server", "Beast.WSProto"); res.fields.replace("Server", "Beast.WSProto");
(*d_)(res); d_(res);
http::prepare(res, http::connection::upgrade); http::prepare(res, http::connection::upgrade);
return res; return res;
} }