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