]>
Commit | Line | Data |
---|---|---|
b32b8144 | 1 | // |
92f5a8d4 | 2 | // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) |
b32b8144 FG |
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/boostorg/beast | |
8 | // | |
9 | ||
10 | #ifndef BOOST_BEAST_HTTP_BUFFER_BODY_HPP | |
11 | #define BOOST_BEAST_HTTP_BUFFER_BODY_HPP | |
12 | ||
13 | #include <boost/beast/core/detail/config.hpp> | |
92f5a8d4 | 14 | #include <boost/beast/core/buffer_traits.hpp> |
b32b8144 FG |
15 | #include <boost/beast/http/error.hpp> |
16 | #include <boost/beast/http/message.hpp> | |
17 | #include <boost/beast/http/type_traits.hpp> | |
18 | #include <boost/optional.hpp> | |
19 | #include <type_traits> | |
20 | #include <utility> | |
21 | ||
22 | namespace boost { | |
23 | namespace beast { | |
24 | namespace http { | |
25 | ||
92f5a8d4 | 26 | /** A <em>Body</em> using a caller provided buffer |
b32b8144 FG |
27 | |
28 | Messages using this body type may be serialized and parsed. | |
29 | To use this class, the caller must initialize the members | |
30 | of @ref buffer_body::value_type to appropriate values before | |
31 | each call to read or write during a stream operation. | |
32 | */ | |
33 | struct buffer_body | |
34 | { | |
35 | /// The type of the body member when used in a message. | |
36 | struct value_type | |
37 | { | |
38 | /** A pointer to a contiguous area of memory of @ref size octets, else `nullptr`. | |
39 | ||
40 | @par When Serializing | |
41 | ||
42 | If this is `nullptr` and `more` is `true`, the error | |
43 | @ref error::need_buffer will be returned from @ref serializer::get | |
44 | Otherwise, the serializer will use the memory pointed to | |
45 | by `data` having `size` octets of valid storage as the | |
46 | next buffer representing the body. | |
47 | ||
48 | @par When Parsing | |
49 | ||
50 | If this is `nullptr`, the error @ref error::need_buffer | |
51 | will be returned from @ref parser::put. Otherwise, the | |
52 | parser will store body octets into the memory pointed to | |
53 | by `data` having `size` octets of valid storage. After | |
54 | octets are stored, the `data` and `size` members are | |
55 | adjusted: `data` is incremented to point to the next | |
56 | octet after the data written, while `size` is decremented | |
57 | to reflect the remaining space at the memory location | |
58 | pointed to by `data`. | |
59 | */ | |
60 | void* data = nullptr; | |
61 | ||
62 | /** The number of octets in the buffer pointed to by @ref data. | |
63 | ||
64 | @par When Serializing | |
65 | ||
66 | If `data` is `nullptr` during serialization, this value | |
67 | is ignored. Otherwise, it represents the number of valid | |
68 | body octets pointed to by `data`. | |
69 | ||
70 | @par When Parsing | |
71 | ||
72 | The value of this field will be decremented during parsing | |
73 | to indicate the number of remaining free octets in the | |
74 | buffer pointed to by `data`. When it reaches zero, the | |
75 | parser will return @ref error::need_buffer, indicating to | |
76 | the caller that the values of `data` and `size` should be | |
77 | updated to point to a new memory buffer. | |
78 | */ | |
79 | std::size_t size = 0; | |
80 | ||
81 | /** `true` if this is not the last buffer. | |
82 | ||
83 | @par When Serializing | |
84 | ||
85 | If this is `true` and `data` is `nullptr`, the error | |
86 | @ref error::need_buffer will be returned from @ref serializer::get | |
87 | ||
88 | @par When Parsing | |
89 | ||
90 | This field is not used during parsing. | |
91 | */ | |
92 | bool more = true; | |
93 | }; | |
94 | ||
95 | /** The algorithm for parsing the body | |
96 | ||
92f5a8d4 | 97 | Meets the requirements of <em>BodyReader</em>. |
b32b8144 FG |
98 | */ |
99 | #if BOOST_BEAST_DOXYGEN | |
92f5a8d4 | 100 | using reader = __implementation_defined__; |
b32b8144 FG |
101 | #else |
102 | class reader | |
103 | { | |
104 | value_type& body_; | |
105 | ||
106 | public: | |
107 | template<bool isRequest, class Fields> | |
108 | explicit | |
11fdf7f2 TL |
109 | reader(header<isRequest, Fields>&, value_type& b) |
110 | : body_(b) | |
b32b8144 FG |
111 | { |
112 | } | |
113 | ||
114 | void | |
115 | init(boost::optional<std::uint64_t> const&, error_code& ec) | |
116 | { | |
92f5a8d4 | 117 | ec = {}; |
b32b8144 FG |
118 | } |
119 | ||
120 | template<class ConstBufferSequence> | |
121 | std::size_t | |
122 | put(ConstBufferSequence const& buffers, | |
123 | error_code& ec) | |
124 | { | |
b32b8144 FG |
125 | if(! body_.data) |
126 | { | |
127 | ec = error::need_buffer; | |
128 | return 0; | |
129 | } | |
130 | auto const bytes_transferred = | |
92f5a8d4 | 131 | net::buffer_copy(net::buffer( |
b32b8144 | 132 | body_.data, body_.size), buffers); |
92f5a8d4 | 133 | body_.data = static_cast<char*>( |
b32b8144 FG |
134 | body_.data) + bytes_transferred; |
135 | body_.size -= bytes_transferred; | |
92f5a8d4 TL |
136 | if(bytes_transferred == buffer_bytes(buffers)) |
137 | ec = {}; | |
b32b8144 FG |
138 | else |
139 | ec = error::need_buffer; | |
140 | return bytes_transferred; | |
141 | } | |
142 | ||
143 | void | |
144 | finish(error_code& ec) | |
145 | { | |
92f5a8d4 | 146 | ec = {}; |
b32b8144 FG |
147 | } |
148 | }; | |
149 | #endif | |
150 | ||
151 | /** The algorithm for serializing the body | |
152 | ||
92f5a8d4 | 153 | Meets the requirements of <em>BodyWriter</em>. |
b32b8144 FG |
154 | */ |
155 | #if BOOST_BEAST_DOXYGEN | |
92f5a8d4 | 156 | using writer = __implementation_defined__; |
b32b8144 FG |
157 | #else |
158 | class writer | |
159 | { | |
160 | bool toggle_ = false; | |
161 | value_type const& body_; | |
162 | ||
163 | public: | |
164 | using const_buffers_type = | |
92f5a8d4 | 165 | net::const_buffer; |
b32b8144 FG |
166 | |
167 | template<bool isRequest, class Fields> | |
168 | explicit | |
11fdf7f2 TL |
169 | writer(header<isRequest, Fields> const&, value_type const& b) |
170 | : body_(b) | |
b32b8144 FG |
171 | { |
172 | } | |
173 | ||
174 | void | |
175 | init(error_code& ec) | |
176 | { | |
92f5a8d4 | 177 | ec = {}; |
b32b8144 FG |
178 | } |
179 | ||
180 | boost::optional< | |
181 | std::pair<const_buffers_type, bool>> | |
182 | get(error_code& ec) | |
183 | { | |
184 | if(toggle_) | |
185 | { | |
186 | if(body_.more) | |
187 | { | |
188 | toggle_ = false; | |
189 | ec = error::need_buffer; | |
190 | } | |
191 | else | |
192 | { | |
92f5a8d4 | 193 | ec = {}; |
b32b8144 FG |
194 | } |
195 | return boost::none; | |
196 | } | |
197 | if(body_.data) | |
198 | { | |
92f5a8d4 | 199 | ec = {}; |
b32b8144 FG |
200 | toggle_ = true; |
201 | return {{const_buffers_type{ | |
202 | body_.data, body_.size}, body_.more}}; | |
203 | } | |
204 | if(body_.more) | |
205 | ec = error::need_buffer; | |
206 | else | |
92f5a8d4 | 207 | ec = {}; |
b32b8144 FG |
208 | return boost::none; |
209 | } | |
210 | }; | |
211 | #endif | |
212 | }; | |
213 | ||
214 | #if ! BOOST_BEAST_DOXYGEN | |
215 | // operator<< is not supported for buffer_body | |
216 | template<bool isRequest, class Fields> | |
217 | std::ostream& | |
218 | operator<<(std::ostream& os, message<isRequest, | |
219 | buffer_body, Fields> const& msg) = delete; | |
220 | #endif | |
221 | ||
222 | } // http | |
223 | } // beast | |
224 | } // boost | |
225 | ||
226 | #endif |