Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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 : // Official repository: https://github.com/cppalliance/http
8 : //
9 :
10 : #ifndef BOOST_HTTP_SOURCE_HPP
11 : #define BOOST_HTTP_SOURCE_HPP
12 :
13 : #include <boost/http/detail/config.hpp>
14 : #include <boost/capy/buffers.hpp>
15 : #include <boost/core/span.hpp>
16 : #include <boost/system/error_code.hpp>
17 : #include <cstddef>
18 : #include <type_traits>
19 :
20 : namespace boost {
21 : namespace http {
22 :
23 : /** An interface for producing buffers of data.
24 :
25 : This interface abstracts the production of
26 : a finite stream of data, returned by writing
27 : into caller-provided buffers until there
28 : is no more output data.
29 :
30 : @par Thread Safety
31 : Non-const member functions may not be
32 : called concurrently on the same instance.
33 :
34 : @see
35 : @ref file_source,
36 : @ref sink,
37 : @ref serializer.
38 : */
39 : struct BOOST_HTTP_SYMBOL_VISIBLE
40 : source
41 : {
42 : /** The results of producing data.
43 : */
44 : struct results
45 : {
46 : /** The error, if any occurred.
47 : */
48 : system::error_code ec;
49 :
50 : /** The number of bytes produced in the output.
51 : */
52 : std::size_t bytes = 0;
53 :
54 : /** True if there will be no more output.
55 : */
56 : bool finished = false;
57 :
58 : /** Accumulate results.
59 : */
60 : results&
61 : operator+=(
62 : results const& rv) noexcept;
63 :
64 : #ifdef BOOST_HTTP_AGGREGATE_WORKAROUND
65 : constexpr
66 : results() = default;
67 :
68 : constexpr
69 : results(
70 : system::error_code ec_,
71 : std::size_t bytes_,
72 : bool finished_) noexcept
73 : : ec(ec_)
74 : , bytes(bytes_)
75 : , finished(finished_)
76 : {
77 : }
78 : #endif
79 : };
80 :
81 : /** Produce data.
82 :
83 : This function attempts to read from the
84 : source, placing the data into the given
85 : mutable buffer sequence.
86 : The return value indicates the number of
87 : bytes placed into the buffers, the error
88 : if any occurred, and a `bool` indicating
89 : whether or not there is more data
90 : remaining in the source.
91 :
92 : @par Preconditions
93 : @code
94 : buffer_size(bs) != 0
95 : @endcode
96 :
97 : @par Postconditions
98 : @code
99 : rv.ec.failed() == true || rv.finished == true || rv.bytes == buffer_size(bs)
100 : @endcode
101 :
102 : @return The result of the operation.
103 :
104 : @param bs The buffers to use.
105 : Each buffer in the sequence will
106 : be filled completely before data
107 : is placed in the next buffer.
108 : */
109 : template<class MutableBufferSequence>
110 : results
111 1005 : read(MutableBufferSequence const& bs)
112 : {
113 : static_assert(
114 : capy::mutable_buffer_sequence<MutableBufferSequence>,
115 : "Type requirements not met");
116 :
117 1005 : return read_impl(bs);
118 : }
119 :
120 : protected:
121 : /** Derived class override.
122 :
123 : This pure virtual function is called by
124 : the implementation and must be overriden.
125 : The callee should attempt to place data
126 : into the given mutable buffer.
127 : The return value must be set to indicate
128 : the number of bytes placed into the
129 : buffers, the error if any occurred,
130 : and a `bool` indicating whether or
131 : not there is more data remaining
132 : in the source.
133 : The implementation must fill the
134 : provided buffer completely, report
135 : an error or set `rv.finished` to true.
136 :
137 : @par Preconditions
138 : @code
139 : buffer_size(bs) != 0
140 : @endcode
141 :
142 : @par Postconditions
143 : @code
144 : rv.ec.failed() == true || rv.finished == true || rv.bytes == buffer_size(bs)
145 : @endcode
146 :
147 : @return The result of the operation.
148 :
149 : @param b The buffer to use.
150 : If this is not filled completely,
151 : then the result must indicate failure
152 : or that no more data remains (or both).
153 : */
154 : virtual
155 : results
156 : on_read(
157 : capy::mutable_buffer b) = 0;
158 :
159 : /** Derived class override.
160 :
161 : This pure virtual function is called by
162 : the implementation and must be overriden.
163 : The callee should attempt to place data
164 : into the given mutable buffer sequence.
165 : The return value must be set to indicate
166 : the number of bytes placed into the
167 : buffers, the error if any occurred,
168 : and a `bool` indicating whether or
169 : not there is more data remaining
170 : in the source.
171 :
172 : @par Preconditions
173 : @code
174 : buffer_size(bs) != 0
175 : @endcode
176 :
177 : @par Postconditions
178 : @code
179 : rv.ec.failed() == true || rv.finished == true || rv.bytes == buffer_size(bs)
180 : @endcode
181 :
182 : @return The result of the operation.
183 :
184 : @param bs The buffer sequence to use.
185 : Each buffer in the sequence must
186 : be filled completely before data
187 : is placed in the next buffer.
188 : If the buffers are not filled
189 : completely, then the result must
190 : indicate failure or that no more
191 : data remains (or both).
192 : */
193 : BOOST_HTTP_DECL
194 : virtual
195 : results
196 : on_read(
197 : boost::span<capy::mutable_buffer const> bs);
198 :
199 : private:
200 : results
201 9 : read_impl(
202 : capy::mutable_buffer const& b)
203 : {
204 9 : return on_read(b);
205 : }
206 :
207 : results
208 5 : read_impl(
209 : boost::span<capy::mutable_buffer const> const& bs)
210 : {
211 5 : return on_read(bs);
212 : }
213 :
214 : template<class T>
215 : results
216 : read_impl(T const&);
217 : };
218 :
219 : //------------------------------------------------
220 :
221 : /** A type trait that determines if T is a source.
222 :
223 : @tparam T The type to check.
224 :
225 : @see
226 : @ref source.
227 : */
228 : template<class T>
229 : using is_source =
230 : std::is_convertible<
231 : typename std::decay<T>::type*,
232 : source*>;
233 :
234 : } // http
235 : } // boost
236 :
237 : #include <boost/http/impl/source.hpp>
238 :
239 : #endif
|