| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // | ||
| 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | ||
| 3 | // Copyright (c) 2024 Christian Mazakas | ||
| 4 | // Copyright (c) 2024 Mohammad Nejati | ||
| 5 | // | ||
| 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
| 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| 8 | // | ||
| 9 | // Official repository: https://github.com/cppalliance/http_proto | ||
| 10 | // | ||
| 11 | |||
| 12 | #include <boost/http_proto/detail/except.hpp> | ||
| 13 | #include <boost/http_proto/message_view_base.hpp> | ||
| 14 | #include <boost/http_proto/serializer.hpp> | ||
| 15 | #include <boost/http_proto/service/zlib_service.hpp> | ||
| 16 | |||
| 17 | #include "src/detail/filter.hpp" | ||
| 18 | |||
| 19 | #include <boost/buffers/copy.hpp> | ||
| 20 | #include <boost/buffers/prefix.hpp> | ||
| 21 | #include <boost/buffers/sans_prefix.hpp> | ||
| 22 | #include <boost/buffers/sans_suffix.hpp> | ||
| 23 | #include <boost/buffers/suffix.hpp> | ||
| 24 | #include <boost/buffers/size.hpp> | ||
| 25 | #include <boost/core/ignore_unused.hpp> | ||
| 26 | |||
| 27 | #include <stddef.h> | ||
| 28 | |||
| 29 | namespace boost { | ||
| 30 | namespace http_proto { | ||
| 31 | |||
| 32 | namespace { | ||
| 33 | |||
| 34 | class deflator_filter | ||
| 35 | : public http_proto::detail::filter | ||
| 36 | { | ||
| 37 | zlib::stream& deflator_; | ||
| 38 | |||
| 39 | public: | ||
| 40 | 49 | deflator_filter( | |
| 41 | context& ctx, | ||
| 42 | http_proto::detail::workspace& ws, | ||
| 43 | bool use_gzip) | ||
| 44 | 196 | : deflator_{ ctx.get_service<zlib::service>() | |
| 45 |
2/2✓ Branch 2 taken 25 times.
✓ Branch 3 taken 24 times.
|
49 | .make_deflator(ws, -1, use_gzip ? 31 : 15, 8) } |
| 46 | { | ||
| 47 | 49 | } | |
| 48 | |||
| 49 | virtual filter::results | ||
| 50 | 21229 | on_process( | |
| 51 | buffers::mutable_buffer out, | ||
| 52 | buffers::const_buffer in, | ||
| 53 | bool more) override | ||
| 54 | { | ||
| 55 | 21229 | auto flush = | |
| 56 |
2/2✓ Branch 0 taken 21132 times.
✓ Branch 1 taken 97 times.
|
21229 | more ? zlib::flush::none : zlib::flush::finish; |
| 57 | 21229 | filter::results results; | |
| 58 | |||
| 59 | for(;;) | ||
| 60 | { | ||
| 61 | 38865 | auto params = zlib::params{in.data(), in.size(), | |
| 62 | 38865 | out.data(), out.size() }; | |
| 63 | 38865 | auto ec = deflator_.write(params, flush); | |
| 64 | |||
| 65 | 38865 | results.in_bytes += in.size() - params.avail_in; | |
| 66 | 38865 | results.out_bytes += out.size() - params.avail_out; | |
| 67 | |||
| 68 |
4/4✓ Branch 1 taken 8921 times.
✓ Branch 2 taken 29944 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 8920 times.
|
47786 | if( ec.failed() && |
| 69 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 38864 times.
|
47786 | ec != zlib::error::buf_err) |
| 70 | { | ||
| 71 | 1 | results.ec = ec; | |
| 72 | 21229 | return results; | |
| 73 | } | ||
| 74 | |||
| 75 |
2/2✓ Branch 2 taken 48 times.
✓ Branch 3 taken 38816 times.
|
38864 | if( ec == zlib::error::stream_end ) |
| 76 | { | ||
| 77 | 48 | results.finished = true; | |
| 78 | 48 | return results; | |
| 79 | } | ||
| 80 | |||
| 81 | 38816 | in = buffers::suffix(in, params.avail_in); | |
| 82 | 38816 | out = buffers::suffix(out, params.avail_out); | |
| 83 | |||
| 84 |
2/2✓ Branch 1 taken 3524 times.
✓ Branch 2 taken 35292 times.
|
38816 | if( out.size() == 0 ) |
| 85 | 3524 | return results; | |
| 86 | |||
| 87 |
1/2✓ Branch 1 taken 35292 times.
✗ Branch 2 not taken.
|
35292 | if( in.size() == 0 ) |
| 88 | { | ||
| 89 |
4/4✓ Branch 0 taken 23960 times.
✓ Branch 1 taken 11332 times.
✓ Branch 2 taken 17636 times.
✓ Branch 3 taken 6324 times.
|
35292 | if( results.out_bytes == 0 && |
| 90 | flush == zlib::flush::none ) | ||
| 91 | { | ||
| 92 | // TODO: Is flush::block the right choice? | ||
| 93 | // We might need a filter::flush() interface | ||
| 94 | // so that the caller can decide when to flush. | ||
| 95 | 17636 | flush = zlib::flush::block; | |
| 96 | 17636 | continue; | |
| 97 | } | ||
| 98 | 17656 | return results; | |
| 99 | } | ||
| 100 | 17636 | } | |
| 101 | } | ||
| 102 | }; | ||
| 103 | |||
| 104 | //------------------------------------------------ | ||
| 105 | |||
| 106 | constexpr | ||
| 107 | std::size_t | ||
| 108 | crlf_len = 2; | ||
| 109 | |||
| 110 | constexpr | ||
| 111 | std::size_t | ||
| 112 | chunk_header_len = 16 + crlf_len; | ||
| 113 | |||
| 114 | constexpr | ||
| 115 | std::size_t | ||
| 116 | final_chunk_len = 1 + crlf_len + crlf_len; | ||
| 117 | |||
| 118 | constexpr | ||
| 119 | std::size_t | ||
| 120 | chunked_overhead_ = | ||
| 121 | chunk_header_len + | ||
| 122 | crlf_len + | ||
| 123 | final_chunk_len; | ||
| 124 | |||
| 125 | template<class MutableBufferSequence> | ||
| 126 | void | ||
| 127 | 9134 | write_chunk_header( | |
| 128 | const MutableBufferSequence& mbs, | ||
| 129 | std::size_t size) noexcept | ||
| 130 | { | ||
| 131 | static constexpr char hexdig[] = | ||
| 132 | "0123456789ABCDEF"; | ||
| 133 | char buf[18]; | ||
| 134 | 9134 | auto p = buf + 16; | |
| 135 |
2/2✓ Branch 0 taken 73072 times.
✓ Branch 1 taken 4567 times.
|
155278 | for(std::size_t i = 16; i--;) |
| 136 | { | ||
| 137 | 146144 | *--p = hexdig[size & 0xf]; | |
| 138 | 146144 | size >>= 4; | |
| 139 | } | ||
| 140 | 9134 | buf[16] = '\r'; | |
| 141 | 9134 | buf[17] = '\n'; | |
| 142 | 9134 | auto n = buffers::copy( | |
| 143 | mbs, | ||
| 144 | 18268 | buffers::const_buffer( | |
| 145 | buf, sizeof(buf))); | ||
| 146 | ignore_unused(n); | ||
| 147 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4567 times.
|
9134 | BOOST_ASSERT(n == 18); |
| 148 | 9134 | } | |
| 149 | |||
| 150 | template<class MutableBufferSequence> | ||
| 151 | void | ||
| 152 | 9134 | write_crlf( | |
| 153 | const MutableBufferSequence& mbs) noexcept | ||
| 154 | { | ||
| 155 | 9134 | auto n = buffers::copy( | |
| 156 | mbs, | ||
| 157 | 18268 | buffers::const_buffer( | |
| 158 | "\r\n", 2)); | ||
| 159 | ignore_unused(n); | ||
| 160 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4567 times.
|
9134 | BOOST_ASSERT(n == 2); |
| 161 | 9134 | } | |
| 162 | |||
| 163 | template<class MutableBufferSequence> | ||
| 164 | void | ||
| 165 | 62 | write_final_chunk( | |
| 166 | const MutableBufferSequence& mbs) noexcept | ||
| 167 | { | ||
| 168 | 62 | auto n = buffers::copy( | |
| 169 | mbs, | ||
| 170 | 124 | buffers::const_buffer( | |
| 171 | "0\r\n\r\n", 5)); | ||
| 172 | ignore_unused(n); | ||
| 173 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
|
62 | BOOST_ASSERT(n == 5); |
| 174 | 62 | } | |
| 175 | |||
| 176 | //------------------------------------------------ | ||
| 177 | |||
| 178 | class appender | ||
| 179 | { | ||
| 180 | buffers::circular_buffer& cb_; | ||
| 181 | buffers::mutable_buffer_pair mbp_; | ||
| 182 | std::size_t n_ = 0; | ||
| 183 | bool is_chunked_ = false; | ||
| 184 | bool more_input_ = true; | ||
| 185 | |||
| 186 | public: | ||
| 187 | 9071 | appender( | |
| 188 | buffers::circular_buffer& cb, | ||
| 189 | bool is_chunked) | ||
| 190 | 9071 | : cb_(cb) | |
| 191 | 9071 | , mbp_(cb.prepare(cb.capacity())) | |
| 192 | 9071 | , is_chunked_(is_chunked) | |
| 193 | { | ||
| 194 | 9071 | } | |
| 195 | |||
| 196 | bool | ||
| 197 | 21331 | is_full() const noexcept | |
| 198 | { | ||
| 199 | 21331 | auto remaining = cb_.capacity() - n_; | |
| 200 |
2/2✓ Branch 0 taken 10684 times.
✓ Branch 1 taken 10647 times.
|
21331 | if(is_chunked_) |
| 201 | 10684 | return remaining <= chunked_overhead_; | |
| 202 | |||
| 203 | 10647 | return remaining == 0; | |
| 204 | } | ||
| 205 | |||
| 206 | buffers::mutable_buffer_pair | ||
| 207 | 12327 | prepare() noexcept | |
| 208 | { | ||
| 209 |
2/2✓ Branch 0 taken 6164 times.
✓ Branch 1 taken 6163 times.
|
12327 | if(is_chunked_) |
| 210 | { | ||
| 211 | 6164 | return buffers::sans_suffix( | |
| 212 | 6164 | buffers::sans_prefix( | |
| 213 | 6164 | mbp_, | |
| 214 | 6164 | chunk_header_len + n_) | |
| 215 | 6164 | , final_chunk_len + crlf_len); | |
| 216 | } | ||
| 217 | 6163 | return buffers::sans_prefix(mbp_, n_); | |
| 218 | } | ||
| 219 | |||
| 220 | void | ||
| 221 | 12325 | commit(std::size_t n, bool more) noexcept | |
| 222 | { | ||
| 223 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12325 times.
|
12325 | BOOST_ASSERT(more_input_); |
| 224 | 12325 | n_ += n; | |
| 225 | 12325 | more_input_ = more; | |
| 226 | 12325 | } | |
| 227 | |||
| 228 | 9071 | ~appender() | |
| 229 | { | ||
| 230 |
2/2✓ Branch 0 taken 4552 times.
✓ Branch 1 taken 4519 times.
|
9071 | if(is_chunked_) |
| 231 | { | ||
| 232 |
2/2✓ Branch 0 taken 4551 times.
✓ Branch 1 taken 1 times.
|
4552 | if(n_) |
| 233 | { | ||
| 234 | 4551 | write_chunk_header(mbp_, n_); | |
| 235 | 4551 | cb_.commit(n_ + chunk_header_len); | |
| 236 | |||
| 237 | 4551 | write_crlf( | |
| 238 | 4551 | cb_.prepare(crlf_len)); | |
| 239 | 4551 | cb_.commit(crlf_len); | |
| 240 | } | ||
| 241 | |||
| 242 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 4526 times.
|
4552 | if(!more_input_) |
| 243 | { | ||
| 244 | 26 | write_final_chunk( | |
| 245 | 26 | cb_.prepare(final_chunk_len)); | |
| 246 | 26 | cb_.commit(final_chunk_len); | |
| 247 | } | ||
| 248 | } | ||
| 249 | else // is_chunked_ == false | ||
| 250 | { | ||
| 251 | 4519 | cb_.commit(n_); | |
| 252 | } | ||
| 253 | 9071 | } | |
| 254 | }; | ||
| 255 | |||
| 256 | } // namespace | ||
| 257 | |||
| 258 | //------------------------------------------------ | ||
| 259 | |||
| 260 | 45 | serializer:: | |
| 261 | ~serializer() | ||
| 262 | { | ||
| 263 | 45 | } | |
| 264 | |||
| 265 | ✗ | serializer:: | |
| 266 | serializer( | ||
| 267 | serializer&&) noexcept = default; | ||
| 268 | |||
| 269 | 11 | serializer:: | |
| 270 | serializer( | ||
| 271 | 11 | context& ctx) | |
| 272 | 11 | : serializer(ctx, 65536) | |
| 273 | { | ||
| 274 | 11 | } | |
| 275 | |||
| 276 | 45 | serializer:: | |
| 277 | serializer( | ||
| 278 | context& ctx, | ||
| 279 | 45 | std::size_t buffer_size) | |
| 280 | 45 | : ctx_(ctx) | |
| 281 | 45 | , ws_(buffer_size) | |
| 282 | { | ||
| 283 | 45 | } | |
| 284 | |||
| 285 | void | ||
| 286 | 131 | serializer:: | |
| 287 | reset() noexcept | ||
| 288 | { | ||
| 289 | 131 | filter_ = nullptr; | |
| 290 | |||
| 291 | 131 | cb0_ = {}; | |
| 292 | 131 | tmp_ = {}; | |
| 293 | |||
| 294 | 131 | more_input_ = false; | |
| 295 | 131 | is_done_ = false; | |
| 296 | 131 | is_header_done_ = false; | |
| 297 | 131 | is_chunked_ = false; | |
| 298 | 131 | needs_exp100_continue_ = false; | |
| 299 | 131 | filter_done_ = false; | |
| 300 | |||
| 301 | 131 | ws_.clear(); | |
| 302 | 131 | } | |
| 303 | |||
| 304 | //------------------------------------------------ | ||
| 305 | |||
| 306 | auto | ||
| 307 | 9138 | serializer:: | |
| 308 | prepare() -> | ||
| 309 | system::result<const_buffers_type> | ||
| 310 | { | ||
| 311 | // Precondition violation | ||
| 312 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9137 times.
|
9138 | if(is_done_) |
| 313 | 1 | detail::throw_logic_error(); | |
| 314 | |||
| 315 | // Expect: 100-continue | ||
| 316 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9133 times.
|
9137 | if(needs_exp100_continue_) |
| 317 | { | ||
| 318 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | if(!is_header_done_) |
| 319 | 4 | return const_buffers_type( | |
| 320 | 2 | prepped_.begin(), | |
| 321 | 2 | 1); // limit to header | |
| 322 | |||
| 323 | 2 | needs_exp100_continue_ = false; | |
| 324 | |||
| 325 | 2 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 326 | error::expect_100_continue); | ||
| 327 | } | ||
| 328 | |||
| 329 |
2/2✓ Branch 0 taken 80 times.
✓ Branch 1 taken 9053 times.
|
9133 | if(!filter_) |
| 330 | { | ||
| 331 |
4/5✓ Branch 0 taken 3 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 35 times.
✗ Branch 4 not taken.
|
80 | switch(st_) |
| 332 | { | ||
| 333 | 3 | case style::empty: | |
| 334 | 6 | return const_buffers_type( | |
| 335 | 3 | prepped_.begin(), | |
| 336 | 6 | prepped_.size()); | |
| 337 | |||
| 338 | 19 | case style::buffers: | |
| 339 | // add more buffers if prepped_ is half empty. | ||
| 340 |
6/6✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 17 times.
|
29 | if(more_input_ && |
| 341 | 10 | prepped_.capacity() >= prepped_.size()) | |
| 342 | { | ||
| 343 | 2 | prepped_.slide_to_front(); | |
| 344 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | while(prepped_.capacity() != 0) |
| 345 | { | ||
| 346 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | auto buf = buf_gen_->operator()(); |
| 347 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 2 times.
|
15 | if(buf.size() != 0) |
| 348 | { | ||
| 349 | 13 | prepped_.append(buf); | |
| 350 | } | ||
| 351 | else // buf_gen_ is empty | ||
| 352 | { | ||
| 353 | // crlf and final chunk | ||
| 354 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
|
2 | if(tmp_.size() != 0) |
| 355 | { | ||
| 356 | 1 | prepped_.append(tmp_); | |
| 357 | 1 | tmp_ = {}; | |
| 358 | } | ||
| 359 | 2 | break; | |
| 360 | } | ||
| 361 | } | ||
| 362 |
4/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
|
2 | if(buf_gen_->is_empty() && tmp_.size() == 0) |
| 363 | 2 | more_input_ = false; | |
| 364 | } | ||
| 365 | 38 | return const_buffers_type( | |
| 366 | 19 | prepped_.begin(), | |
| 367 | 38 | prepped_.size()); | |
| 368 | |||
| 369 | 23 | case style::source: | |
| 370 | { | ||
| 371 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 18 times.
|
23 | if(!more_input_) |
| 372 | 22 | break; | |
| 373 | |||
| 374 | // handles chunked payloads automatically | ||
| 375 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | appender apndr(cb0_, is_chunked_); |
| 376 | |||
| 377 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
|
18 | if(apndr.is_full()) |
| 378 | ✗ | break; | |
| 379 | |||
| 380 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | auto rs = source_->read( |
| 381 | 18 | apndr.prepare()); | |
| 382 | |||
| 383 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 17 times.
|
18 | if(rs.ec.failed()) |
| 384 | { | ||
| 385 | 1 | is_done_ = true; | |
| 386 | 1 | BOOST_HTTP_PROTO_RETURN_EC(rs.ec); | |
| 387 | } | ||
| 388 | |||
| 389 | 17 | more_input_ = !rs.finished; | |
| 390 | 17 | apndr.commit(rs.bytes, more_input_); | |
| 391 | 17 | break; | |
| 392 |
2/2✓ Branch 1 taken 17 times.
✓ Branch 2 taken 1 times.
|
18 | } |
| 393 | |||
| 394 | 35 | case style::stream: | |
| 395 |
6/6✓ Branch 0 taken 30 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 34 times.
|
35 | if(is_header_done_ && cb0_.size() == 0) |
| 396 | 1 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 397 | error::need_data); | ||
| 398 | 34 | break; | |
| 399 | } | ||
| 400 | } | ||
| 401 | else // filter | ||
| 402 | { | ||
| 403 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9053 times.
|
9053 | if(st_ == style::empty) |
| 404 | ✗ | return const_buffers_type( | |
| 405 | ✗ | prepped_.begin(), | |
| 406 | ✗ | prepped_.size()); | |
| 407 | |||
| 408 | 17789 | auto get_input = [&]() | |
| 409 | { | ||
| 410 |
2/2✓ Branch 0 taken 1329 times.
✓ Branch 1 taken 16460 times.
|
17789 | if(st_ == style::buffers) |
| 411 | { | ||
| 412 | // TODO: for efficiency of deflator, we might | ||
| 413 | // need to return multiple buffers at once | ||
| 414 |
2/2✓ Branch 1 taken 385 times.
✓ Branch 2 taken 944 times.
|
1329 | if(tmp_.size() == 0) |
| 415 | { | ||
| 416 | 385 | tmp_ = buf_gen_->operator()(); | |
| 417 | 385 | more_input_ = !buf_gen_->is_empty(); | |
| 418 | } | ||
| 419 | return buffers:: | ||
| 420 | 1329 | const_buffer_pair{ tmp_, {} }; | |
| 421 | } | ||
| 422 | |||
| 423 |
3/4✓ Branch 0 taken 10976 times.
✓ Branch 1 taken 5484 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10976 times.
|
16460 | BOOST_ASSERT( |
| 424 | st_ == style::source || | ||
| 425 | st_ == style::stream); | ||
| 426 | |||
| 427 | 38404 | if(st_ == style::source && | |
| 428 |
7/8✓ Branch 0 taken 5484 times.
✓ Branch 1 taken 10976 times.
✓ Branch 2 taken 5480 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 5480 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5480 times.
✓ Branch 7 taken 10980 times.
|
21940 | more_input_ && |
| 429 | 5480 | cb1_.capacity() != 0) | |
| 430 | { | ||
| 431 | // TODO: handle source error | ||
| 432 |
1/2✓ Branch 1 taken 5480 times.
✗ Branch 2 not taken.
|
5480 | auto rs = source_->read( |
| 433 |
1/2✓ Branch 2 taken 5480 times.
✗ Branch 3 not taken.
|
5480 | cb1_.prepare(cb1_.capacity())); |
| 434 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 5464 times.
|
5480 | if(rs.finished) |
| 435 | 16 | more_input_ = false; | |
| 436 | 5480 | cb1_.commit(rs.bytes); | |
| 437 | } | ||
| 438 | |||
| 439 | 16460 | return cb1_.data(); | |
| 440 | 9053 | }; | |
| 441 | |||
| 442 | 12308 | auto consume = [&](std::size_t n) | |
| 443 | { | ||
| 444 |
2/2✓ Branch 0 taken 1328 times.
✓ Branch 1 taken 10980 times.
|
12308 | if(st_ == style::buffers) |
| 445 | { | ||
| 446 | 1328 | tmp_ = buffers::sans_prefix( | |
| 447 | 1328 | tmp_, n); | |
| 448 | 1328 | return; | |
| 449 | } | ||
| 450 |
3/4✓ Branch 0 taken 5496 times.
✓ Branch 1 taken 5484 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5496 times.
|
10980 | BOOST_ASSERT( |
| 451 | st_ == style::source || | ||
| 452 | st_ == style::stream); | ||
| 453 | 10980 | cb1_.consume(n); | |
| 454 | 9053 | }; | |
| 455 | |||
| 456 | // handles chunked payloads automatically | ||
| 457 |
1/2✓ Branch 1 taken 9053 times.
✗ Branch 2 not taken.
|
9053 | appender apndr(cb0_, is_chunked_); |
| 458 | for(;;) | ||
| 459 | { | ||
| 460 |
2/2✓ Branch 1 taken 3524 times.
✓ Branch 2 taken 17789 times.
|
21313 | if(apndr.is_full()) |
| 461 | 3524 | break; | |
| 462 | |||
| 463 |
1/2✓ Branch 1 taken 17789 times.
✗ Branch 2 not taken.
|
17789 | auto cbs = get_input(); |
| 464 | |||
| 465 |
6/6✓ Branch 0 taken 17692 times.
✓ Branch 1 taken 97 times.
✓ Branch 3 taken 5480 times.
✓ Branch 4 taken 12212 times.
✓ Branch 5 taken 5480 times.
✓ Branch 6 taken 12309 times.
|
17789 | if(more_input_ && buffers::size(cbs) == 0) |
| 466 | 5480 | break; | |
| 467 | |||
| 468 |
1/2✓ Branch 1 taken 12309 times.
✗ Branch 2 not taken.
|
12309 | auto rs = filter_->process( |
| 469 | ✗ | apndr.prepare(), | |
| 470 | cbs, | ||
| 471 | 12309 | more_input_); | |
| 472 | |||
| 473 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 12308 times.
|
12309 | if(rs.ec.failed()) |
| 474 | { | ||
| 475 | 1 | is_done_ = true; | |
| 476 | 1 | BOOST_HTTP_PROTO_RETURN_EC(rs.ec); | |
| 477 | } | ||
| 478 | |||
| 479 |
1/2✓ Branch 1 taken 12308 times.
✗ Branch 2 not taken.
|
12308 | consume(rs.in_bytes); |
| 480 | 12308 | apndr.commit(rs.out_bytes, !rs.finished); | |
| 481 | |||
| 482 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 12260 times.
|
12308 | if(rs.finished) |
| 483 | { | ||
| 484 | 48 | filter_done_ = true; | |
| 485 | 48 | break; | |
| 486 | } | ||
| 487 | 12260 | } | |
| 488 |
2/2✓ Branch 1 taken 9052 times.
✓ Branch 2 taken 1 times.
|
9053 | } |
| 489 | |||
| 490 | 9108 | prepped_.reset(!is_header_done_); | |
| 491 | 9108 | const auto cbp = cb0_.data(); | |
| 492 |
2/2✓ Branch 2 taken 9105 times.
✓ Branch 3 taken 3 times.
|
9108 | if(cbp[0].size() != 0) |
| 493 | 9105 | prepped_.append(cbp[0]); | |
| 494 |
2/2✓ Branch 2 taken 14 times.
✓ Branch 3 taken 9094 times.
|
9108 | if(cbp[1].size() != 0) |
| 495 | 14 | prepped_.append(cbp[1]); | |
| 496 | |||
| 497 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9108 times.
|
9108 | BOOST_ASSERT( |
| 498 | buffers::size(prepped_) > 0); | ||
| 499 | |||
| 500 | 18216 | return const_buffers_type( | |
| 501 | 9108 | prepped_.begin(), | |
| 502 | 18216 | prepped_.size()); | |
| 503 | } | ||
| 504 | |||
| 505 | void | ||
| 506 | 10871 | serializer:: | |
| 507 | consume( | ||
| 508 | std::size_t n) | ||
| 509 | { | ||
| 510 | // Precondition violation | ||
| 511 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10870 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
10871 | if(is_done_ && n != 0) |
| 512 | 1 | detail::throw_logic_error(); | |
| 513 | |||
| 514 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 10794 times.
|
10870 | if(!is_header_done_) |
| 515 | { | ||
| 516 | const auto header_remain = | ||
| 517 | 76 | prepped_[0].size(); | |
| 518 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 65 times.
|
76 | if(n < header_remain) |
| 519 | { | ||
| 520 | 11 | prepped_.consume(n); | |
| 521 | 11 | return; | |
| 522 | } | ||
| 523 | 65 | n -= header_remain; | |
| 524 | 65 | prepped_.consume(header_remain); | |
| 525 | 65 | is_header_done_ = true; | |
| 526 | } | ||
| 527 | |||
| 528 | 10859 | prepped_.consume(n); | |
| 529 | |||
| 530 | // no-op when cb0_ is not in use | ||
| 531 | 10859 | cb0_.consume(n); | |
| 532 | |||
| 533 |
2/2✓ Branch 1 taken 1760 times.
✓ Branch 2 taken 9099 times.
|
10859 | if(!prepped_.empty()) |
| 534 | 1760 | return; | |
| 535 | |||
| 536 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9098 times.
|
9099 | if(needs_exp100_continue_) |
| 537 | 1 | return; | |
| 538 | |||
| 539 |
2/2✓ Branch 0 taken 8985 times.
✓ Branch 1 taken 113 times.
|
9098 | if(more_input_) |
| 540 | 8985 | return; | |
| 541 | |||
| 542 |
4/4✓ Branch 0 taken 96 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 48 times.
|
113 | if(filter_ && !filter_done_) |
| 543 | 48 | return; | |
| 544 | |||
| 545 | 65 | is_done_ = true; | |
| 546 | } | ||
| 547 | |||
| 548 | //------------------------------------------------ | ||
| 549 | |||
| 550 | detail::array_of_const_buffers | ||
| 551 | 75 | serializer:: | |
| 552 | make_array(std::size_t n) | ||
| 553 | { | ||
| 554 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
|
75 | if(n > std::numeric_limits<std::uint16_t>::max()) |
| 555 | ✗ | detail::throw_length_error(); | |
| 556 | |||
| 557 | return { | ||
| 558 | 75 | ws_.push_array(n, | |
| 559 | ✗ | buffers::const_buffer{}), | |
| 560 |
1/2✓ Branch 2 taken 75 times.
✗ Branch 3 not taken.
|
75 | static_cast<std::uint16_t>(n) }; |
| 561 | } | ||
| 562 | |||
| 563 | void | ||
| 564 | 75 | serializer:: | |
| 565 | start_init( | ||
| 566 | message_view_base const& m) | ||
| 567 | { | ||
| 568 | 75 | reset(); | |
| 569 | |||
| 570 | // VFALCO what do we do with | ||
| 571 | // metadata error code failures? | ||
| 572 | // m.ph_->md.maybe_throw(); | ||
| 573 | |||
| 574 | 75 | auto const& md = m.metadata(); | |
| 575 | 75 | needs_exp100_continue_ = md.expect.is_100_continue; | |
| 576 | |||
| 577 | // Transfer-Encoding | ||
| 578 | 75 | is_chunked_ = md.transfer_encoding.is_chunked; | |
| 579 | |||
| 580 | // Content-Encoding | ||
| 581 | 75 | auto const& ce = md.content_encoding; | |
| 582 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 51 times.
|
75 | if(ce.encoding == encoding::deflate) |
| 583 | { | ||
| 584 | 24 | filter_ = &ws_.emplace< | |
| 585 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
24 | deflator_filter>(ctx_, ws_, false); |
| 586 | } | ||
| 587 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 26 times.
|
51 | else if(ce.encoding == encoding::gzip) |
| 588 | { | ||
| 589 | 25 | filter_ = &ws_.emplace< | |
| 590 |
1/2✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
|
25 | deflator_filter>(ctx_, ws_, true); |
| 591 | } | ||
| 592 | 75 | } | |
| 593 | |||
| 594 | void | ||
| 595 | 4 | serializer:: | |
| 596 | start_empty( | ||
| 597 | message_view_base const& m) | ||
| 598 | { | ||
| 599 | using mutable_buffer = | ||
| 600 | buffers::mutable_buffer; | ||
| 601 | |||
| 602 | 4 | start_init(m); | |
| 603 | 4 | st_ = style::empty; | |
| 604 | |||
| 605 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | if(!is_chunked_) |
| 606 | { | ||
| 607 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | prepped_ = make_array( |
| 608 | 1); // header | ||
| 609 | } | ||
| 610 | else | ||
| 611 | { | ||
| 612 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | prepped_ = make_array( |
| 613 | 1 + // header | ||
| 614 | 1); // final chunk | ||
| 615 | |||
| 616 | mutable_buffer final_chunk = { | ||
| 617 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ws_.reserve_front( |
| 618 | final_chunk_len), | ||
| 619 | 1 | final_chunk_len }; | |
| 620 | 1 | write_final_chunk(final_chunk); | |
| 621 | |||
| 622 | 1 | prepped_[1] = final_chunk; | |
| 623 | } | ||
| 624 | |||
| 625 | 4 | prepped_[0] = { m.ph_->cbuf, m.ph_->size }; | |
| 626 | 4 | } | |
| 627 | |||
| 628 | void | ||
| 629 | 24 | serializer:: | |
| 630 | start_buffers( | ||
| 631 | message_view_base const& m) | ||
| 632 | { | ||
| 633 | using mutable_buffer = | ||
| 634 | buffers::mutable_buffer; | ||
| 635 | |||
| 636 | // start_init() already called | ||
| 637 | 24 | st_ = style::buffers; | |
| 638 | |||
| 639 | 24 | const auto buffers_max = (std::min)( | |
| 640 | 48 | std::size_t{ 16 }, | |
| 641 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
24 | buf_gen_->count()); |
| 642 | |||
| 643 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 17 times.
|
24 | if(!filter_) |
| 644 | { | ||
| 645 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
|
7 | if(!is_chunked_) |
| 646 | { | ||
| 647 | // no filter and no chunked | ||
| 648 | |||
| 649 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | prepped_ = make_array( |
| 650 | 1 + // header | ||
| 651 | buffers_max ); // buffers | ||
| 652 | |||
| 653 | 6 | prepped_[0] = { m.ph_->cbuf, m.ph_->size }; | |
| 654 |
1/2✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
12 | std::generate( |
| 655 | 6 | prepped_.begin() + 1, | |
| 656 | prepped_.end(), | ||
| 657 | 6 | std::ref(*buf_gen_)); | |
| 658 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | more_input_ = !buf_gen_->is_empty(); |
| 659 | 6 | return; | |
| 660 | } | ||
| 661 | |||
| 662 | // no filter and chunked | ||
| 663 | |||
| 664 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
1 | if(buf_gen_->is_empty()) |
| 665 | { | ||
| 666 | ✗ | prepped_ = make_array( | |
| 667 | 1 + // header | ||
| 668 | 1); // final chunk | ||
| 669 | |||
| 670 | mutable_buffer final_chunk = { | ||
| 671 | ✗ | ws_.reserve_front( | |
| 672 | final_chunk_len), | ||
| 673 | ✗ | final_chunk_len }; | |
| 674 | ✗ | write_final_chunk( | |
| 675 | final_chunk); | ||
| 676 | |||
| 677 | ✗ | prepped_[0] = { m.ph_->cbuf, m.ph_->size }; | |
| 678 | ✗ | prepped_[1] = final_chunk; | |
| 679 | ✗ | return; | |
| 680 | } | ||
| 681 | |||
| 682 | // Write entire buffers as a single chunk | ||
| 683 | // since total size is known | ||
| 684 | |||
| 685 | mutable_buffer chunk_header = { | ||
| 686 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ws_.reserve_front( |
| 687 | chunk_header_len), | ||
| 688 | 1 | chunk_header_len }; | |
| 689 | |||
| 690 | 1 | write_chunk_header( | |
| 691 | chunk_header, | ||
| 692 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | buf_gen_->size()); |
| 693 | |||
| 694 | mutable_buffer crlf_and_final_chunk = { | ||
| 695 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ws_.reserve_front( |
| 696 | crlf_len + final_chunk_len), | ||
| 697 | 1 | crlf_len + final_chunk_len }; | |
| 698 | |||
| 699 | 1 | write_crlf( | |
| 700 | 1 | buffers::prefix( | |
| 701 | crlf_and_final_chunk, | ||
| 702 | crlf_len)); | ||
| 703 | |||
| 704 | 1 | write_final_chunk( | |
| 705 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | buffers::sans_prefix( |
| 706 | crlf_and_final_chunk, | ||
| 707 | crlf_len)); | ||
| 708 | |||
| 709 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | prepped_ = make_array( |
| 710 | 1 + // header | ||
| 711 | 1 + // chunk header | ||
| 712 | buffers_max + // buffers | ||
| 713 | 1); // buffer or (crlf and final chunk) | ||
| 714 | |||
| 715 | 1 | prepped_[0] = { m.ph_->cbuf, m.ph_->size }; | |
| 716 | 1 | prepped_[1] = chunk_header; | |
| 717 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::generate( |
| 718 | 1 | prepped_.begin() + 2, | |
| 719 | 1 | prepped_.end() - 1, | |
| 720 | 1 | std::ref(*buf_gen_)); | |
| 721 | |||
| 722 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | more_input_ = !buf_gen_->is_empty(); |
| 723 | // assigning the last slot | ||
| 724 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if(more_input_) |
| 725 | { | ||
| 726 | 1 | prepped_[prepped_.size() - 1] = | |
| 727 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | buf_gen_->operator()(); |
| 728 | |||
| 729 | // deferred until buf_gen_ is drained | ||
| 730 | 1 | tmp_ = crlf_and_final_chunk; | |
| 731 | } | ||
| 732 | else | ||
| 733 | { | ||
| 734 | ✗ | prepped_[prepped_.size() - 1] = | |
| 735 | crlf_and_final_chunk; | ||
| 736 | } | ||
| 737 | 1 | return; | |
| 738 | } | ||
| 739 | |||
| 740 | // filter | ||
| 741 | |||
| 742 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | prepped_ = make_array( |
| 743 | 1 + // header | ||
| 744 | 2); // circular buffer | ||
| 745 | |||
| 746 | 17 | const auto n = ws_.size() - 1; | |
| 747 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | cb0_ = { ws_.reserve_front(n), n }; |
| 748 | |||
| 749 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9 times.
|
17 | if(is_chunked_) |
| 750 | { | ||
| 751 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if(cb0_.capacity() <= chunked_overhead_) |
| 752 | ✗ | detail::throw_length_error(); | |
| 753 | } | ||
| 754 | else | ||
| 755 | { | ||
| 756 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
9 | if(cb0_.capacity() == 0) |
| 757 | ✗ | detail::throw_length_error(); | |
| 758 | } | ||
| 759 | |||
| 760 | 17 | prepped_[0] = { m.ph_->cbuf, m.ph_->size }; | |
| 761 | 17 | more_input_ = !buf_gen_->is_empty(); | |
| 762 | } | ||
| 763 | |||
| 764 | void | ||
| 765 | 25 | serializer:: | |
| 766 | start_source( | ||
| 767 | message_view_base const& m) | ||
| 768 | { | ||
| 769 | // start_init() already called | ||
| 770 | 25 | st_ = style::source; | |
| 771 | |||
| 772 |
1/2✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
|
25 | prepped_ = make_array( |
| 773 | 1 + // header | ||
| 774 | 2); // circular buffer | ||
| 775 | |||
| 776 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 9 times.
|
25 | if(filter_) |
| 777 | { | ||
| 778 | // TODO: Optimize buffer distribution | ||
| 779 | 16 | const auto n = (ws_.size() - 1) / 2; | |
| 780 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | cb0_ = { ws_.reserve_front(n), n }; |
| 781 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | cb1_ = { ws_.reserve_front(n), n }; |
| 782 | } | ||
| 783 | else | ||
| 784 | { | ||
| 785 | 9 | const auto n = ws_.size() - 1; | |
| 786 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | cb0_ = { ws_.reserve_front(n), n }; |
| 787 | } | ||
| 788 | |||
| 789 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 15 times.
|
25 | if(is_chunked_) |
| 790 | { | ||
| 791 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if(cb0_.capacity() <= chunked_overhead_) |
| 792 | ✗ | detail::throw_length_error(); | |
| 793 | } | ||
| 794 | else | ||
| 795 | { | ||
| 796 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
|
15 | if(cb0_.capacity() == 0) |
| 797 | ✗ | detail::throw_length_error(); | |
| 798 | } | ||
| 799 | |||
| 800 | 25 | prepped_[0] = { m.ph_->cbuf, m.ph_->size }; | |
| 801 | 25 | more_input_ = true; | |
| 802 | 25 | } | |
| 803 | |||
| 804 | auto | ||
| 805 | 22 | serializer:: | |
| 806 | start_stream( | ||
| 807 | message_view_base const& m) -> | ||
| 808 | stream | ||
| 809 | { | ||
| 810 | 22 | start_init(m); | |
| 811 | 22 | st_ = style::stream; | |
| 812 | |||
| 813 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | prepped_ = make_array( |
| 814 | 1 + // header | ||
| 815 | 2); // circular buffer | ||
| 816 | |||
| 817 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
|
22 | if(filter_) |
| 818 | { | ||
| 819 | // TODO: Optimize buffer distribution | ||
| 820 | 16 | const auto n = (ws_.size() - 1) / 2; | |
| 821 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | cb0_ = { ws_.reserve_front(n), n }; |
| 822 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | cb1_ = { ws_.reserve_front(n), n }; |
| 823 | } | ||
| 824 | else | ||
| 825 | { | ||
| 826 | 6 | const auto n = ws_.size() - 1; | |
| 827 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | cb0_ = { ws_.reserve_front(n), n }; |
| 828 | } | ||
| 829 | |||
| 830 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | if(is_chunked_) |
| 831 | { | ||
| 832 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | if(cb0_.capacity() <= chunked_overhead_) |
| 833 | ✗ | detail::throw_length_error(); | |
| 834 | } | ||
| 835 | else | ||
| 836 | { | ||
| 837 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | if(cb0_.capacity() == 0) |
| 838 | ✗ | detail::throw_length_error(); | |
| 839 | } | ||
| 840 | |||
| 841 | 22 | prepped_[0] = { m.ph_->cbuf, m.ph_->size }; | |
| 842 | 22 | more_input_ = true; | |
| 843 | 22 | return stream{ *this }; | |
| 844 | } | ||
| 845 | |||
| 846 | //------------------------------------------------ | ||
| 847 | |||
| 848 | std::size_t | ||
| 849 | 69 | serializer:: | |
| 850 | stream:: | ||
| 851 | capacity() const noexcept | ||
| 852 | { | ||
| 853 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
|
69 | if(sr_->filter_) |
| 854 | ✗ | return sr_->cb1_.capacity(); | |
| 855 | |||
| 856 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 35 times.
|
69 | if(!sr_->is_chunked_) |
| 857 | 34 | return sr_->cb0_.capacity(); | |
| 858 | |||
| 859 | // chunked with no filter | ||
| 860 | 35 | const auto cap = sr_->cb0_.capacity(); | |
| 861 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 14 times.
|
35 | if(cap > chunked_overhead_) |
| 862 | 21 | return cap - chunked_overhead_; | |
| 863 | |||
| 864 | 14 | return 0; | |
| 865 | } | ||
| 866 | |||
| 867 | bool | ||
| 868 | 61 | serializer:: | |
| 869 | stream:: | ||
| 870 | is_full() const noexcept | ||
| 871 | { | ||
| 872 | 61 | return capacity() == 0; | |
| 873 | } | ||
| 874 | |||
| 875 | auto | ||
| 876 | 5511 | serializer:: | |
| 877 | stream:: | ||
| 878 | prepare() const -> | ||
| 879 | buffers_type | ||
| 880 | { | ||
| 881 |
2/2✓ Branch 0 taken 5480 times.
✓ Branch 1 taken 31 times.
|
5511 | if(sr_->filter_) |
| 882 | 5480 | return sr_->cb1_.prepare( | |
| 883 | 10960 | sr_->cb1_.capacity()); | |
| 884 | |||
| 885 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 16 times.
|
31 | if(!sr_->is_chunked_) |
| 886 | 15 | return sr_->cb0_.prepare( | |
| 887 | 30 | sr_->cb0_.capacity()); | |
| 888 | |||
| 889 | // chunked with no filter | ||
| 890 | 16 | const auto cap = sr_->cb0_.capacity(); | |
| 891 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if(cap <= chunked_overhead_) |
| 892 | ✗ | detail::throw_length_error(); | |
| 893 | |||
| 894 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | return buffers::sans_prefix( |
| 895 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
32 | sr_->cb0_.prepare( |
| 896 | cap - crlf_len - final_chunk_len), | ||
| 897 | 16 | chunk_header_len); | |
| 898 | } | ||
| 899 | |||
| 900 | void | ||
| 901 | 5511 | serializer:: | |
| 902 | stream:: | ||
| 903 | commit(std::size_t n) const | ||
| 904 | { | ||
| 905 |
2/2✓ Branch 0 taken 5480 times.
✓ Branch 1 taken 31 times.
|
5511 | if(sr_->filter_) |
| 906 | 5480 | return sr_->cb1_.commit(n); | |
| 907 | |||
| 908 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 16 times.
|
31 | if(!sr_->is_chunked_) |
| 909 | 15 | return sr_->cb0_.commit(n); | |
| 910 | |||
| 911 | // chunked with no filter | ||
| 912 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
|
16 | if(n != 0) |
| 913 | { | ||
| 914 | 15 | write_chunk_header( | |
| 915 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | sr_->cb0_.prepare( |
| 916 | chunk_header_len), | ||
| 917 | n); | ||
| 918 | 15 | sr_->cb0_.commit( | |
| 919 | chunk_header_len); | ||
| 920 | |||
| 921 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | sr_->cb0_.prepare(n); |
| 922 | 15 | sr_->cb0_.commit(n); | |
| 923 | |||
| 924 | 15 | write_crlf( | |
| 925 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | sr_->cb0_.prepare(crlf_len)); |
| 926 | 15 | sr_->cb0_.commit(crlf_len); | |
| 927 | } | ||
| 928 | } | ||
| 929 | |||
| 930 | void | ||
| 931 | 25 | serializer:: | |
| 932 | stream:: | ||
| 933 | close() const | ||
| 934 | { | ||
| 935 | // Precondition violation | ||
| 936 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 21 times.
|
25 | if(!sr_->more_input_) |
| 937 | 4 | detail::throw_logic_error(); | |
| 938 | |||
| 939 | 21 | sr_->more_input_ = false; | |
| 940 | |||
| 941 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 5 times.
|
21 | if(sr_->filter_) |
| 942 | 16 | return; | |
| 943 | |||
| 944 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | if(!sr_->is_chunked_) |
| 945 | 2 | return; | |
| 946 | |||
| 947 | // chunked with no filter | ||
| 948 | 3 | write_final_chunk( | |
| 949 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | sr_->cb0_.prepare( |
| 950 | final_chunk_len)); | ||
| 951 | 3 | sr_->cb0_.commit(final_chunk_len); | |
| 952 | } | ||
| 953 | |||
| 954 | //------------------------------------------------ | ||
| 955 | |||
| 956 | } // http_proto | ||
| 957 | } // boost | ||
| 958 |