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