]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | ||
8 | #ifndef BEAST_DETAIL_WRITE_DYNABUF_HPP | |
9 | #define BEAST_DETAIL_WRITE_DYNABUF_HPP | |
10 | ||
11 | #include <beast/core/buffer_concepts.hpp> | |
12 | #include <boost/asio/buffer.hpp> | |
13 | #include <boost/lexical_cast.hpp> | |
14 | #include <utility> | |
15 | ||
16 | namespace beast { | |
17 | namespace detail { | |
18 | ||
19 | // detects string literals. | |
20 | template<class T> | |
21 | struct is_string_literal : std::integral_constant<bool, | |
22 | ! std::is_same<T, typename std::remove_extent<T>::type>::value && | |
23 | std::is_same<char, typename std::remove_extent<T>::type>::value> | |
24 | { | |
25 | }; | |
26 | ||
27 | // `true` if a call to boost::asio::buffer(T const&) is possible | |
28 | // note: we exclude string literals because boost::asio::buffer() | |
29 | // will include the null terminator, which we don't want. | |
30 | template<class T> | |
31 | class is_BufferConvertible | |
32 | { | |
33 | template<class U, class R = decltype( | |
34 | boost::asio::buffer(std::declval<U const&>()), | |
35 | std::true_type{})> | |
36 | static R check(int); | |
37 | template<class> | |
38 | static std::false_type check(...); | |
39 | using type = decltype(check<T>(0)); | |
40 | public: | |
41 | static bool const value = type::value && | |
42 | ! is_string_literal<T>::value; | |
43 | }; | |
44 | ||
45 | template<class DynamicBuffer> | |
46 | void | |
47 | write_dynabuf(DynamicBuffer& dynabuf, | |
48 | boost::asio::const_buffer const& buffer) | |
49 | { | |
50 | using boost::asio::buffer_copy; | |
51 | using boost::asio::buffer_size; | |
52 | dynabuf.commit(buffer_copy( | |
53 | dynabuf.prepare(buffer_size(buffer)), | |
54 | buffer)); | |
55 | } | |
56 | ||
57 | template<class DynamicBuffer> | |
58 | void | |
59 | write_dynabuf(DynamicBuffer& dynabuf, | |
60 | boost::asio::mutable_buffer const& buffer) | |
61 | { | |
62 | using boost::asio::buffer_copy; | |
63 | using boost::asio::buffer_size; | |
64 | dynabuf.commit(buffer_copy( | |
65 | dynabuf.prepare(buffer_size(buffer)), | |
66 | buffer)); | |
67 | } | |
68 | ||
69 | template<class DynamicBuffer, class T> | |
70 | typename std::enable_if< | |
71 | is_BufferConvertible<T>::value && | |
72 | ! std::is_convertible<T, boost::asio::const_buffer>::value && | |
73 | ! std::is_convertible<T, boost::asio::mutable_buffer>::value | |
74 | >::type | |
75 | write_dynabuf(DynamicBuffer& dynabuf, T const& t) | |
76 | { | |
77 | using boost::asio::buffer_copy; | |
78 | using boost::asio::buffer_size; | |
79 | auto const buffers = boost::asio::buffer(t); | |
80 | dynabuf.commit(buffer_copy( | |
81 | dynabuf.prepare(buffer_size(buffers)), | |
82 | buffers)); | |
83 | } | |
84 | ||
85 | template<class DynamicBuffer, class Buffers> | |
86 | typename std::enable_if< | |
87 | is_ConstBufferSequence<Buffers>::value && | |
88 | ! is_BufferConvertible<Buffers>::value && | |
89 | ! std::is_convertible<Buffers, boost::asio::const_buffer>::value && | |
90 | ! std::is_convertible<Buffers, boost::asio::mutable_buffer>::value | |
91 | >::type | |
92 | write_dynabuf(DynamicBuffer& dynabuf, Buffers const& buffers) | |
93 | { | |
94 | using boost::asio::buffer_copy; | |
95 | using boost::asio::buffer_size; | |
96 | dynabuf.commit(buffer_copy( | |
97 | dynabuf.prepare(buffer_size(buffers)), | |
98 | buffers)); | |
99 | } | |
100 | ||
101 | template<class DynamicBuffer, std::size_t N> | |
102 | void | |
103 | write_dynabuf(DynamicBuffer& dynabuf, const char (&s)[N]) | |
104 | { | |
105 | using boost::asio::buffer_copy; | |
106 | dynabuf.commit(buffer_copy( | |
107 | dynabuf.prepare(N - 1), | |
108 | boost::asio::buffer(s, N - 1))); | |
109 | } | |
110 | ||
111 | template<class DynamicBuffer, class T> | |
112 | typename std::enable_if< | |
113 | ! is_string_literal<T>::value && | |
114 | ! is_ConstBufferSequence<T>::value && | |
115 | ! is_BufferConvertible<T>::value && | |
116 | ! std::is_convertible<T, boost::asio::const_buffer>::value && | |
117 | ! std::is_convertible<T, boost::asio::mutable_buffer>::value | |
118 | >::type | |
119 | write_dynabuf(DynamicBuffer& dynabuf, T const& t) | |
120 | { | |
121 | using boost::asio::buffer; | |
122 | using boost::asio::buffer_copy; | |
123 | auto const s = boost::lexical_cast<std::string>(t); | |
124 | dynabuf.commit(buffer_copy( | |
125 | dynabuf.prepare(s.size()), buffer(s))); | |
126 | } | |
127 | ||
128 | template<class DynamicBuffer, class T0, class T1, class... TN> | |
129 | void | |
130 | write_dynabuf(DynamicBuffer& dynabuf, | |
131 | T0 const& t0, T1 const& t1, TN const&... tn) | |
132 | { | |
133 | write_dynabuf(dynabuf, t0); | |
134 | write_dynabuf(dynabuf, t1, tn...); | |
135 | } | |
136 | ||
137 | } // detail | |
138 | } // beast | |
139 | ||
140 | #endif |