Line | Branch | Exec | Source |
---|---|---|---|
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_proto | ||
8 | // | ||
9 | |||
10 | #ifndef BOOST_HTTP_PROTO_IMPL_SERIALIZER_IPP | ||
11 | #define BOOST_HTTP_PROTO_IMPL_SERIALIZER_IPP | ||
12 | |||
13 | #include <boost/http_proto/serializer.hpp> | ||
14 | #include <boost/http_proto/detail/codec.hpp> | ||
15 | #include <boost/http_proto/detail/except.hpp> | ||
16 | #include <boost/buffers/buffer_copy.hpp> | ||
17 | #include <boost/buffers/buffer_size.hpp> | ||
18 | #include <boost/core/ignore_unused.hpp> | ||
19 | #include <stddef.h> | ||
20 | |||
21 | namespace boost { | ||
22 | namespace http_proto { | ||
23 | |||
24 | //------------------------------------------------ | ||
25 | |||
26 | void | ||
27 | ✗ | consume_buffers( | |
28 | buffers::const_buffer*& p, | ||
29 | std::size_t& n, | ||
30 | std::size_t bytes) | ||
31 | { | ||
32 | ✗ | while(n > 0) | |
33 | { | ||
34 | ✗ | if(bytes < p->size()) | |
35 | { | ||
36 | ✗ | *p += bytes; | |
37 | ✗ | return; | |
38 | } | ||
39 | ✗ | bytes -= p->size(); | |
40 | ✗ | ++p; | |
41 | ✗ | --n; | |
42 | } | ||
43 | |||
44 | // Precondition violation | ||
45 | ✗ | if(bytes > 0) | |
46 | ✗ | detail::throw_invalid_argument(); | |
47 | } | ||
48 | |||
49 | template<class MutableBuffers> | ||
50 | void | ||
51 | 6 | write_chunk_header( | |
52 | MutableBuffers const& dest0, | ||
53 | std::size_t size) noexcept | ||
54 | { | ||
55 | static constexpr char hexdig[] = | ||
56 | "0123456789ABCDEF"; | ||
57 | char buf[18]; | ||
58 | 6 | auto p = buf + 16; | |
59 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3 times.
|
102 | for(std::size_t i = 16; i--;) |
60 | { | ||
61 | 96 | *--p = hexdig[size & 0xf]; | |
62 | 96 | size >>= 4; | |
63 | } | ||
64 | 6 | buf[16] = '\r'; | |
65 | 6 | buf[17] = '\n'; | |
66 | 6 | auto n = buffers::buffer_copy( | |
67 | dest0, | ||
68 | buffers::const_buffer( | ||
69 | buf, sizeof(buf))); | ||
70 | ignore_unused(n); | ||
71 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
6 | BOOST_ASSERT(n == 18); |
72 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
6 | BOOST_ASSERT( |
73 | buffers::buffer_size(dest0) == n); | ||
74 | 6 | } | |
75 | |||
76 | //------------------------------------------------ | ||
77 | |||
78 | 11 | serializer:: | |
79 |
6/8✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 11 times.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 33 times.
✓ Branch 8 taken 11 times.
|
77 | ~serializer() |
80 | { | ||
81 | 11 | } | |
82 | |||
83 | 10 | serializer:: | |
84 | 10 | serializer() | |
85 | 10 | : serializer(65536) | |
86 | { | ||
87 | 10 | } | |
88 | |||
89 | serializer:: | ||
90 | serializer( | ||
91 | serializer&&) noexcept = default; | ||
92 | |||
93 | 11 | serializer:: | |
94 | serializer( | ||
95 | 11 | std::size_t buffer_size) | |
96 | 11 | : ws_(buffer_size) | |
97 | { | ||
98 | 11 | } | |
99 | |||
100 | void | ||
101 | ✗ | serializer:: | |
102 | reset() noexcept | ||
103 | { | ||
104 | } | ||
105 | |||
106 | //------------------------------------------------ | ||
107 | |||
108 | auto | ||
109 | 14 | serializer:: | |
110 | prepare() -> | ||
111 | result<const_buffers_type> | ||
112 | { | ||
113 | // Precondition violation | ||
114 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if(is_done_) |
115 | ✗ | detail::throw_logic_error(); | |
116 | |||
117 | // Expect: 100-continue | ||
118 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10 times.
|
14 | if(is_expect_continue_) |
119 | { | ||
120 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
4 | if(out_.data() == hp_) |
121 | 2 | return const_buffers_type(hp_, 1); | |
122 | 2 | is_expect_continue_ = false; | |
123 | 2 | BOOST_HTTP_PROTO_RETURN_EC( | |
124 | error::expect_100_continue); | ||
125 | } | ||
126 | |||
127 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
|
10 | if(st_ == style::empty) |
128 | { | ||
129 | 9 | return const_buffers_type( | |
130 | 3 | out_.data(), | |
131 | 3 | out_.size()); | |
132 | } | ||
133 | |||
134 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
|
7 | if(st_ == style::buffers) |
135 | { | ||
136 | 9 | return const_buffers_type( | |
137 | 3 | out_.data(), | |
138 | 3 | out_.size()); | |
139 | } | ||
140 | |||
141 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if(st_ == style::source) |
142 | { | ||
143 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | if(! is_chunked_) |
144 | { | ||
145 | 3 | auto rv = src_->read( | |
146 | ✗ | tmp0_.prepare( | |
147 | 3 | tmp0_.capacity() - | |
148 |
2/4✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
3 | tmp0_.size())); |
149 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | tmp0_.commit(rv.bytes); |
150 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if(rv.ec.failed()) |
151 | ✗ | return rv.ec; | |
152 | 3 | more_ = ! rv.finished; | |
153 | } | ||
154 | else | ||
155 | { | ||
156 | 1 | if((tmp0_.capacity() - | |
157 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | tmp0_.size()) > |
158 | chunked_overhead_) | ||
159 | { | ||
160 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | auto dest = tmp0_.prepare(18); |
161 | 1 | write_chunk_header(dest, 0); | |
162 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | tmp0_.commit(18); |
163 | 1 | auto rv = src_->read( | |
164 | ✗ | tmp0_.prepare( | |
165 | 1 | tmp0_.capacity() - | |
166 | 2 - // CRLF | ||
167 | 1 | 5 - // final chunk | |
168 |
2/4✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
1 | tmp0_.size())); |
169 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | tmp0_.commit(rv.bytes); |
170 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(rv.bytes == 0) |
171 | ✗ | tmp0_.uncommit(18); // undo | |
172 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if(rv.ec.failed()) |
173 | ✗ | return rv.ec; | |
174 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if(rv.bytes > 0) |
175 | { | ||
176 | // rewrite with correct size | ||
177 | 1 | write_chunk_header( | |
178 | dest, rv.bytes); | ||
179 | // terminate chunk | ||
180 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | tmp0_.commit( |
181 | buffers::buffer_copy( | ||
182 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | tmp0_.prepare(2), |
183 | 2 | buffers::const_buffer( | |
184 | "\r\n", 2))); | ||
185 | } | ||
186 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if(rv.finished) |
187 | { | ||
188 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | tmp0_.commit( |
189 | buffers::buffer_copy( | ||
190 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | tmp0_.prepare(5), |
191 | 2 | buffers::const_buffer( | |
192 | "0\r\n\r\n", 5))); | ||
193 | } | ||
194 | 1 | more_ = ! rv.finished; | |
195 | } | ||
196 | } | ||
197 | |||
198 | 4 | std::size_t n = 0; | |
199 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
|
4 | if(out_.data() == hp_) |
200 | 3 | ++n; | |
201 |
2/2✓ Branch 3 taken 8 times.
✓ Branch 4 taken 4 times.
|
12 | for(buffers::const_buffer const& b : tmp0_.data()) |
202 | 8 | out_[n++] = b; | |
203 | |||
204 | 12 | return const_buffers_type( | |
205 | 4 | out_.data(), | |
206 | 4 | out_.size()); | |
207 | } | ||
208 | |||
209 | ✗ | if(st_ == style::stream) | |
210 | { | ||
211 | ✗ | std::size_t n = 0; | |
212 | ✗ | if(out_.data() == hp_) | |
213 | ✗ | ++n; | |
214 | ✗ | if(tmp0_.size() == 0 && more_) | |
215 | { | ||
216 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
217 | error::need_data); | ||
218 | } | ||
219 | ✗ | for(buffers::const_buffer const& b : tmp0_.data()) | |
220 | ✗ | out_[n++] = b; | |
221 | |||
222 | ✗ | return const_buffers_type( | |
223 | ✗ | out_.data(), | |
224 | ✗ | out_.size()); | |
225 | } | ||
226 | |||
227 | // should never get here | ||
228 | ✗ | detail::throw_logic_error(); | |
229 | } | ||
230 | |||
231 | void | ||
232 | 12 | serializer:: | |
233 | consume( | ||
234 | std::size_t n) | ||
235 | { | ||
236 | // Precondition violation | ||
237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if(is_done_) |
238 | ✗ | detail::throw_logic_error(); | |
239 | |||
240 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
|
12 | if(is_expect_continue_) |
241 | { | ||
242 | // Cannot consume more than | ||
243 | // the header on 100-continue | ||
244 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if(n > hp_->size()) |
245 | ✗ | detail::throw_invalid_argument(); | |
246 | |||
247 | 2 | out_.consume(n); | |
248 | 2 | return; | |
249 | } | ||
250 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
|
10 | else if(out_.data() == hp_) |
251 | { | ||
252 | // consume header | ||
253 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if(n < hp_->size()) |
254 | { | ||
255 | ✗ | out_.consume(n); | |
256 | ✗ | return; | |
257 | } | ||
258 | 8 | n -= hp_->size(); | |
259 | 8 | out_.consume(hp_->size()); | |
260 | } | ||
261 | |||
262 |
3/3✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
|
10 | switch(st_) |
263 | { | ||
264 | 3 | default: | |
265 | case style::empty: | ||
266 | 3 | out_.consume(n); | |
267 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if(out_.empty()) |
268 | 3 | is_done_ = true; | |
269 | 3 | return; | |
270 | |||
271 | 3 | case style::buffers: | |
272 | 3 | out_.consume(n); | |
273 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if(out_.empty()) |
274 | 3 | is_done_ = true; | |
275 | 3 | return; | |
276 | |||
277 | 4 | case style::source: | |
278 | case style::stream: | ||
279 | 4 | tmp0_.consume(n); | |
280 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
8 | if( tmp0_.size() == 0 && |
281 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | ! more_) |
282 | 4 | is_done_ = true; | |
283 | 4 | return; | |
284 | } | ||
285 | } | ||
286 | |||
287 | //------------------------------------------------ | ||
288 | |||
289 | void | ||
290 | 14 | serializer:: | |
291 | copy( | ||
292 | buffers::const_buffer* dest, | ||
293 | buffers::const_buffer const* src, | ||
294 | std::size_t n) noexcept | ||
295 | { | ||
296 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | while(n--) |
297 | 7 | *dest++ = *src++; | |
298 | 7 | } | |
299 | |||
300 | void | ||
301 | 17 | serializer:: | |
302 | start_init( | ||
303 | message_view_base const& m) | ||
304 | { | ||
305 | 17 | ws_.clear(); | |
306 | |||
307 | // VFALCO what do we do with | ||
308 | // metadata error code failures? | ||
309 | // m.ph_->md.maybe_throw(); | ||
310 | |||
311 | 17 | is_done_ = false; | |
312 | |||
313 | 17 | is_expect_continue_ = | |
314 | 17 | m.ph_->md.expect.is_100_continue; | |
315 | |||
316 | // Transfer-Encoding | ||
317 | { | ||
318 | 17 | auto const& te = | |
319 | 17 | m.ph_->md.transfer_encoding; | |
320 | 17 | is_chunked_ = te.is_chunked; | |
321 | 17 | cod_ = nullptr; | |
322 | } | ||
323 | 17 | } | |
324 | |||
325 | void | ||
326 | 4 | serializer:: | |
327 | start_empty( | ||
328 | message_view_base const& m) | ||
329 | { | ||
330 | 4 | start_init(m); | |
331 | |||
332 | 4 | st_ = style::empty; | |
333 | |||
334 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | if(! is_chunked_) |
335 | { | ||
336 | out_ = make_array( | ||
337 | 3 | 1); // header | |
338 | } | ||
339 | else | ||
340 | { | ||
341 | out_ = make_array( | ||
342 | 1 + // header | ||
343 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | 1); // final chunk |
344 | |||
345 | // Buffer is too small | ||
346 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if(ws_.size() < 5) |
347 | ✗ | detail::throw_length_error(); | |
348 | |||
349 | buffers::mutable_buffer dest( | ||
350 | 1 | ws_.data(), 5); | |
351 | 1 | buffers::buffer_copy( | |
352 | dest, | ||
353 | 1 | buffers::const_buffer( | |
354 | "0\r\n\r\n", 5)); | ||
355 | 1 | out_[1] = dest; | |
356 | } | ||
357 | |||
358 | 4 | hp_ = &out_[0]; | |
359 | 4 | *hp_ = { m.ph_->cbuf, m.ph_->size }; | |
360 | 4 | } | |
361 | |||
362 | void | ||
363 | 7 | serializer:: | |
364 | start_buffers( | ||
365 | message_view_base const& m) | ||
366 | { | ||
367 | 7 | st_ = style::buffers; | |
368 | |||
369 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
|
7 | if(! is_chunked_) |
370 | { | ||
371 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if(! cod_) |
372 | { | ||
373 | out_ = make_array( | ||
374 | 1 + // header | ||
375 | 6 | buf_.size()); // body | |
376 | 12 | copy(&out_[1], | |
377 | 6 | buf_.data(), buf_.size()); | |
378 | } | ||
379 | else | ||
380 | { | ||
381 | out_ = make_array( | ||
382 | 1 + // header | ||
383 | ✗ | 2); // tmp1 | |
384 | } | ||
385 | } | ||
386 | else | ||
387 | { | ||
388 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if(! cod_) |
389 | { | ||
390 | out_ = make_array( | ||
391 | 1 + // header | ||
392 | 1 + // chunk size | ||
393 | 1 | buf_.size() + // body | |
394 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | 1); // final chunk |
395 | 2 | copy(&out_[2], | |
396 | 1 | buf_.data(), buf_.size()); | |
397 | |||
398 | // Buffer is too small | ||
399 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if(ws_.size() < 18 + 7) |
400 | ✗ | detail::throw_length_error(); | |
401 | 1 | buffers::mutable_buffer s1(ws_.data(), 18); | |
402 | 1 | buffers::mutable_buffer s2(ws_.data(), 18 + 7); | |
403 | 1 | s2 += 18; // VFALCO HACK | |
404 | 1 | write_chunk_header( | |
405 | s1, | ||
406 | 1 | buffers::buffer_size(buf_)); | |
407 | 1 | buffers::buffer_copy(s2, buffers::const_buffer( | |
408 | "\r\n" | ||
409 | "0\r\n" | ||
410 | "\r\n", 7)); | ||
411 | 1 | out_[1] = s1; | |
412 | 1 | out_[out_.size() - 1] = s2; | |
413 | } | ||
414 | else | ||
415 | { | ||
416 | out_ = make_array( | ||
417 | 1 + // header | ||
418 | ✗ | 2); // tmp1 | |
419 | } | ||
420 | } | ||
421 | |||
422 | 7 | hp_ = &out_[0]; | |
423 | 7 | *hp_ = { m.ph_->cbuf, m.ph_->size }; | |
424 | 7 | } | |
425 | |||
426 | void | ||
427 | 6 | serializer:: | |
428 | start_source( | ||
429 | message_view_base const& m, | ||
430 | buffers::source* src) | ||
431 | { | ||
432 | 6 | st_ = style::source; | |
433 | 6 | src_ = src; | |
434 | out_ = make_array( | ||
435 | 1 + // header | ||
436 | 6 | 2); // tmp | |
437 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if(! cod_) |
438 | { | ||
439 | buffers::buffered_base::allocator a( | ||
440 | 6 | ws_.data(), ws_.size()/2, false); | |
441 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | src->init(a); |
442 |
1/2✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | ws_.reserve(a.size_used()); |
443 | |||
444 | 6 | tmp0_ = { ws_.data(), ws_.size() }; | |
445 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | if(tmp0_.capacity() < |
446 | 18 + // chunk size | ||
447 | 1 + // body (1 byte) | ||
448 | 2 + // CRLF | ||
449 | 5) // final chunk | ||
450 | ✗ | detail::throw_length_error(); | |
451 | } | ||
452 | else | ||
453 | { | ||
454 | buffers::buffered_base::allocator a( | ||
455 | ✗ | ws_.data(), ws_.size()/3, false); | |
456 | ✗ | src->init(a); | |
457 | ✗ | ws_.reserve(a.size_used()); | |
458 | |||
459 | ✗ | auto const n = ws_.size() / 2; | |
460 | |||
461 | ✗ | tmp0_ = { ws_.data(), ws_.size() / 2 }; | |
462 | ✗ | ws_.reserve(n); | |
463 | |||
464 | // Buffer is too small | ||
465 | ✗ | if(ws_.size() < 1) | |
466 | ✗ | detail::throw_length_error(); | |
467 | |||
468 | ✗ | tmp1_ = { ws_.data(), ws_.size() }; | |
469 | } | ||
470 | |||
471 | 6 | hp_ = &out_[0]; | |
472 | 6 | *hp_ = { m.ph_->cbuf, m.ph_->size }; | |
473 | 6 | } | |
474 | |||
475 | auto | ||
476 | ✗ | serializer:: | |
477 | start_stream( | ||
478 | message_view_base const& m) -> | ||
479 | stream | ||
480 | { | ||
481 | ✗ | start_init(m); | |
482 | |||
483 | ✗ | st_ = style::stream; | |
484 | out_ = make_array( | ||
485 | 1 + // header | ||
486 | ✗ | 2); // tmp | |
487 | ✗ | if(! cod_) | |
488 | { | ||
489 | ✗ | tmp0_ = { ws_.data(), ws_.size() }; | |
490 | ✗ | if(tmp0_.capacity() < | |
491 | 18 + // chunk size | ||
492 | 1 + // body (1 byte) | ||
493 | 2 + // CRLF | ||
494 | 5) // final chunk | ||
495 | ✗ | detail::throw_length_error(); | |
496 | } | ||
497 | else | ||
498 | { | ||
499 | ✗ | auto const n = ws_.size() / 2; | |
500 | ✗ | tmp0_ = { ws_.data(), n }; | |
501 | ✗ | ws_.reserve(n); | |
502 | |||
503 | // Buffer is too small | ||
504 | ✗ | if(ws_.size() < 1) | |
505 | ✗ | detail::throw_length_error(); | |
506 | |||
507 | ✗ | tmp1_ = { ws_.data(), ws_.size() }; | |
508 | } | ||
509 | |||
510 | ✗ | hp_ = &out_[0]; | |
511 | ✗ | *hp_ = { m.ph_->cbuf, m.ph_->size }; | |
512 | |||
513 | ✗ | more_ = true; | |
514 | |||
515 | ✗ | return stream{*this}; | |
516 | } | ||
517 | |||
518 | //------------------------------------------------ | ||
519 | |||
520 | std::size_t | ||
521 | ✗ | serializer:: | |
522 | stream:: | ||
523 | capacity() const | ||
524 | { | ||
525 | ✗ | auto const n = | |
526 | chunked_overhead_ + | ||
527 | 2 + // CRLF | ||
528 | 5; // final chunk | ||
529 | ✗ | return sr_->tmp0_.capacity() - n; // VFALCO ? | |
530 | } | ||
531 | |||
532 | std::size_t | ||
533 | ✗ | serializer:: | |
534 | stream:: | ||
535 | size() const | ||
536 | { | ||
537 | ✗ | return sr_->tmp0_.size(); | |
538 | } | ||
539 | |||
540 | auto | ||
541 | ✗ | serializer:: | |
542 | stream:: | ||
543 | prepare( | ||
544 | std::size_t n) const -> | ||
545 | buffers_type | ||
546 | { | ||
547 | ✗ | return sr_->tmp0_.prepare(n); | |
548 | } | ||
549 | |||
550 | void | ||
551 | ✗ | serializer:: | |
552 | stream:: | ||
553 | commit(std::size_t n) const | ||
554 | { | ||
555 | ✗ | sr_->tmp0_.commit(n); | |
556 | } | ||
557 | |||
558 | void | ||
559 | ✗ | serializer:: | |
560 | stream:: | ||
561 | close() const | ||
562 | { | ||
563 | // Precondition violation | ||
564 | ✗ | if(! sr_->more_) | |
565 | ✗ | detail::throw_logic_error(); | |
566 | ✗ | sr_->more_ = false; | |
567 | } | ||
568 | |||
569 | //------------------------------------------------ | ||
570 | |||
571 | } // http_proto | ||
572 | } // boost | ||
573 | |||
574 | #endif | ||
575 |