src/serializer.cpp
98.9% Lines (344/348)
96.6% List of functions (28/29)
95.0% Branches (322/339)
Functions (29)
Function
Calls
Lines
Branches
Blocks
boost::burl::(anonymous namespace)::suffix(boost::capy::const_buffer, unsigned long)
:46
1369x
100.0%
–
100.0%
boost::burl::serializer::serializer(boost::burl::serializer::config const&)
:56
189x
100.0%
–
100.0%
boost::burl::serializer::serializer(boost::burl::serializer&&)
:68
1x
100.0%
–
100.0%
boost::burl::serializer::operator=(boost::burl::serializer&&)
:72
0
0.0%
–
0.0%
boost::burl::serializer::~serializer()
:75
190x
100.0%
–
100.0%
boost::burl::serializer::start(boost::burl::message_head_base*, bool)
:79
200x
100.0%
50.0%
83.0%
boost::burl::serializer::select_framing_()
:107
200x
100.0%
89.5%
94.0%
boost::burl::serializer::select_framing_()::{lambda()#1}::operator()() const
:127
200x
100.0%
100.0%
100.0%
boost::burl::serializer::revise_framing_(unsigned long)
:145
180x
100.0%
100.0%
100.0%
boost::burl::serializer::split_()
:164
235x
100.0%
100.0%
100.0%
boost::burl::serializer::sealed_() const
:175
5020x
100.0%
–
100.0%
boost::burl::serializer::set_encoder(std::unique_ptr<boost::burl::detail::encoder, std::default_delete<boost::burl::detail::encoder> >)
:182
35x
100.0%
50.0%
100.0%
boost::burl::serializer::prepare(std::span<boost::capy::mutable_buffer, 18446744073709551615ul>)
:194
27x
100.0%
88.9%
100.0%
boost::burl::serializer::commit(unsigned long)
:215
66x
100.0%
50.0%
71.0%
boost::burl::serializer::chunked_() const
:224
4411x
100.0%
–
100.0%
boost::burl::serializer::to_eof_() const
:231
548x
100.0%
–
100.0%
boost::burl::serializer::should_coalesce_(unsigned long) const
:238
165x
100.0%
100.0%
100.0%
boost::burl::serializer::buffered_()
:250
2762x
100.0%
100.0%
100.0%
boost::burl::serializer::epilogue_buf_() const
:257
465x
100.0%
100.0%
100.0%
boost::burl::serializer::trailer_buf_() const
:268
465x
100.0%
100.0%
100.0%
boost::burl::serializer::settled_() const
:277
460x
100.0%
100.0%
100.0%
boost::burl::serializer::open_chunk_(unsigned long)
:299
127x
100.0%
70.0%
79.0%
boost::burl::serializer::encode_(boost::burl::serializer::source&, std::error_code&)
:333
200x
100.0%
–
97.0%
boost::burl::serializer::encode_(boost::burl::serializer::source&, std::error_code&)::{lambda(boost::capy::const_buffer, bool)#1}::operator()(boost::capy::const_buffer, bool) const
:336
74x
100.0%
100.0%
100.0%
boost::burl::serializer::ingest_(boost::burl::serializer::source&, bool)
:394
684x
96.5%
99.0%
97.0%
boost::burl::serializer::gather_(std::span<boost::capy::const_buffer, 18446744073709551615ul>, boost::burl::serializer::source&, bool, bool)
:487
1086x
100.0%
–
100.0%
boost::burl::serializer::gather_(std::span<boost::capy::const_buffer, 18446744073709551615ul>, boost::burl::serializer::source&, bool, bool)::{lambda(boost::capy::const_buffer)#1}::operator()(boost::capy::const_buffer) const
:497
3033x
100.0%
100.0%
100.0%
boost::burl::serializer::frame_(std::span<boost::capy::const_buffer, 18446744073709551615ul>, boost::burl::serializer::source&, bool)
:559
1276x
96.9%
89.6%
93.0%
boost::burl::serializer::consume(unsigned long)
:616
1270x
100.0%
90.0%
97.0%
| Line | Branch | TLA | Hits | Source Code |
|---|---|---|---|---|
| 1 | // | |||
| 2 | // Copyright (c) 2026 Mohammad Nejati | |||
| 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/burl | |||
| 8 | // | |||
| 9 | ||||
| 10 | #include <boost/burl/error.hpp> | |||
| 11 | #include <boost/burl/serializer.hpp> | |||
| 12 | ||||
| 13 | #include "detail/content_coding.hpp" | |||
| 14 | #include "detail/encoder.hpp" | |||
| 15 | #include "detail/util.hpp" | |||
| 16 | ||||
| 17 | #include <boost/assert.hpp> | |||
| 18 | #include <boost/capy/buffers/buffer_copy.hpp> | |||
| 19 | #include <boost/capy/buffers/make_buffer.hpp> | |||
| 20 | #include <boost/capy/cond.hpp> | |||
| 21 | #include <boost/url/grammar/ci_string.hpp> | |||
| 22 | ||||
| 23 | #include <algorithm> | |||
| 24 | #include <utility> | |||
| 25 | ||||
| 26 | namespace boost | |||
| 27 | { | |||
| 28 | namespace burl | |||
| 29 | { | |||
| 30 | ||||
| 31 | // assert relying facts | |||
| 32 | static_assert( | |||
| 33 | fields_base::max_buffer_size <= | |||
| 34 | (std::numeric_limits<std::uint32_t>::max)()); | |||
| 35 | ||||
| 36 | using http::payload; | |||
| 37 | ||||
| 38 | using detail::clamp; | |||
| 39 | using detail::content_coding; | |||
| 40 | using detail::make_encoder; | |||
| 41 | ||||
| 42 | namespace | |||
| 43 | { | |||
| 44 | ||||
| 45 | capy::const_buffer | |||
| 46 | 1369x | suffix(capy::const_buffer buf, std::size_t n) noexcept | ||
| 47 | { | |||
| 48 | return { | |||
| 49 | 1369x | static_cast<char const*>(buf.data()) + n, | ||
| 50 | 1369x | buf.size() - n | ||
| 51 | 1369x | }; | ||
| 52 | } | |||
| 53 | ||||
| 54 | } // namespace | |||
| 55 | ||||
| 56 | 189x | serializer:: | ||
| 57 | 189x | serializer(config const& cfg) | ||
| 58 | 189x | : buf_(new char[margin + cfg.stage_buffer + cfg.enc_buffer]) | ||
| 59 | 189x | , min_prepare_(cfg.min_prepare) | ||
| 60 | 189x | , min_direct_(cfg.min_direct) | ||
| 61 | 189x | , enc_threshold_(cfg.enc_threshold) | ||
| 62 | 189x | , stage_{ buf_.get() + margin, cfg.stage_buffer } | ||
| 63 | 189x | , enc_out_{ buf_.get() + margin, cfg.enc_buffer } | ||
| 64 | 189x | , enc_cfg_(cfg.encoder) | ||
| 65 | { | |||
| 66 | 189x | } | ||
| 67 | ||||
| 68 | 1x | serializer:: | ||
| 69 | serializer(serializer&& other) noexcept = default; | |||
| 70 | ||||
| 71 | serializer& | |||
| 72 | ✗ | serializer:: | ||
| 73 | operator=(serializer&& other) noexcept = default; | |||
| 74 | ||||
| 75 | 190x | serializer:: | ||
| 76 | ~serializer() = default; | |||
| 77 | ||||
| 78 | void | |||
| 79 | 200x | serializer:: | ||
| 80 | start( | |||
| 81 | message_head_base* msg, | |||
| 82 | bool head) | |||
| 83 | { | |||
| 84 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
|
200x | BOOST_ASSERT(msg != nullptr); | |
| 85 | ||||
| 86 | 200x | stage_.clear(); | ||
| 87 | 200x | enc_out_.clear(); | ||
| 88 | ||||
| 89 | 200x | msg_ = msg; | ||
| 90 | 200x | enc_ = nullptr; | ||
| 91 | 200x | trailer_ = nullptr; | ||
| 92 | ||||
| 93 | 200x | header_offset_ = 0; | ||
| 94 | 200x | tail_offset_ = 0; | ||
| 95 | 200x | owed_ = 0; | ||
| 96 | 200x | input_framed_ = 0; | ||
| 97 | 200x | input_digested_ = 0; | ||
| 98 | 200x | prefix_rem_ = 0; | ||
| 99 | 200x | payload_ = payload::none; | ||
| 100 | 200x | state_ = state::started; | ||
| 101 | 200x | head_ = head; | ||
| 102 | 200x | crlf_owed_ = false; | ||
| 103 | 200x | enc_started_ = false; | ||
| 104 | 200x | } | ||
| 105 | ||||
| 106 | void | |||
| 107 | 200x | serializer:: | ||
| 108 | select_framing_() | |||
| 109 | { | |||
| 110 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
|
200x | BOOST_ASSERT(state_ == state::started); | |
| 111 | ||||
| 112 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 193 times.
|
200x | payload_ = head_ ? payload::none : msg_->payload(); | |
| 113 | ||||
| 114 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 13 times.
|
21x | if( payload_ == payload::to_eof && | |
| 115 |
4/4✓ Branch 0 taken 21 times.
✓ Branch 1 taken 179 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 193 times.
|
221x | msg_->version() == http::version::http_1_1 && | |
| 116 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 time.
|
8x | !msg_->contains(http::field::transfer_encoding)) | |
| 117 | { | |||
| 118 | 7x | msg_->set_chunked(true); | ||
| 119 | 7x | payload_ = payload::chunked; | ||
| 120 | } | |||
| 121 | ||||
| 122 |
5/6✓ Branch 1 taken 3 times.
✓ Branch 2 taken 197 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 197 times.
|
200x | if(enc_cfg_ && payload_ != payload::none) | |
| 123 |
1/1✓ Branch 3 taken 3 times.
|
3x | enc_ = make_encoder(content_coding(*msg_), *enc_cfg_); | |
| 124 | ||||
| 125 | 200x | split_(); | ||
| 126 | ||||
| 127 | 600x | owed_ = [&]() -> std::uint64_t | ||
| 128 | { | |||
| 129 |
3/3✓ Branch 0 taken 148 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 38 times.
|
200x | switch(payload_) | |
| 130 | { | |||
| 131 | 148x | case payload::none: | ||
| 132 | case payload::chunked: | |||
| 133 | 148x | return 0; | ||
| 134 | 14x | case payload::to_eof: | ||
| 135 | 14x | return std::uint64_t(-1); | ||
| 136 | 38x | default: | ||
| 137 | 38x | return msg_->content_length().value_or(0); | ||
| 138 | } | |||
| 139 |
1/1✓ Branch 1 taken 200 times.
|
200x | }(); | |
| 140 | ||||
| 141 | 200x | state_ = state::streaming; | ||
| 142 | 200x | } | ||
| 143 | ||||
| 144 | void | |||
| 145 | 180x | serializer:: | ||
| 146 | revise_framing_(std::uint64_t remaining) noexcept | |||
| 147 | { | |||
| 148 |
6/6✓ Branch 1 taken 85 times.
✓ Branch 2 taken 95 times.
✓ Branch 4 taken 71 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 71 times.
✓ Branch 7 taken 109 times.
|
180x | if(!chunked_() && !to_eof_()) | |
| 149 | 71x | return; | ||
| 150 | ||||
| 151 |
4/4✓ Branch 0 taken 31 times.
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 8 times.
|
109x | if(header_offset_ == 0 && !trailer_) | |
| 152 | { | |||
| 153 | 23x | msg_->set_content_length(remaining); | ||
| 154 | 23x | payload_ = payload::size; | ||
| 155 | 23x | owed_ = remaining; | ||
| 156 | } | |||
| 157 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 2 taken 72 times.
|
86x | else if(to_eof_()) | |
| 158 | { | |||
| 159 | 14x | owed_ = remaining; | ||
| 160 | } | |||
| 161 | } | |||
| 162 | ||||
| 163 | void | |||
| 164 | 235x | serializer:: | ||
| 165 | split_() noexcept | |||
| 166 | { | |||
| 167 |
2/2✓ Branch 1 taken 40 times.
✓ Branch 2 taken 195 times.
|
235x | if((enc_ != nullptr) != (stage_.ptr != enc_out_.ptr)) | |
| 168 | { | |||
| 169 | 40x | std::swap(stage_.cap, enc_out_.cap); | ||
| 170 |
2/2✓ Branch 1 taken 38 times.
✓ Branch 2 taken 2 times.
|
40x | stage_.ptr = enc_out_.ptr + (enc_ ? enc_out_.cap : 0); | |
| 171 | } | |||
| 172 | 235x | } | ||
| 173 | ||||
| 174 | bool | |||
| 175 | 5020x | serializer:: | ||
| 176 | sealed_() const noexcept | |||
| 177 | { | |||
| 178 | 5020x | return state_ == state::sealed; | ||
| 179 | } | |||
| 180 | ||||
| 181 | void | |||
| 182 | 35x | serializer:: | ||
| 183 | set_encoder( | |||
| 184 | std::unique_ptr<detail::encoder> enc) | |||
| 185 | { | |||
| 186 |
1/2✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
|
35x | if(state_ == state::started) | |
| 187 | 35x | select_framing_(); | ||
| 188 | ||||
| 189 | 35x | enc_ = std::move(enc); | ||
| 190 | 35x | split_(); | ||
| 191 | 35x | } | ||
| 192 | ||||
| 193 | std::span<capy::mutable_buffer> | |||
| 194 | 27x | serializer:: | ||
| 195 | prepare(std::span<capy::mutable_buffer> dest) | |||
| 196 | { | |||
| 197 |
2/3✓ Branch 0 taken 13 times.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
27x | switch(state_) | |
| 198 | { | |||
| 199 | 13x | case state::started: | ||
| 200 | 13x | select_framing_(); | ||
| 201 | BOOST_FALLTHROUGH; | |||
| 202 | 27x | case state::streaming: | ||
| 203 |
6/6✓ Branch 1 taken 26 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 25 times.
✓ Branch 7 taken 2 times.
|
27x | if(!dest.empty() && !stage_.full()) | |
| 204 | { | |||
| 205 | 25x | dest[0] = stage_.prepare(); | ||
| 206 | 25x | return dest.first(1); | ||
| 207 | } | |||
| 208 | BOOST_FALLTHROUGH; | |||
| 209 | default: | |||
| 210 | 2x | return {}; | ||
| 211 | }; | |||
| 212 | } | |||
| 213 | ||||
| 214 | void | |||
| 215 | 66x | serializer:: | ||
| 216 | commit(std::size_t n) noexcept | |||
| 217 | { | |||
| 218 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66x | BOOST_ASSERT(msg_ != nullptr); | |
| 219 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
|
66x | BOOST_ASSERT(!sealed_()); | |
| 220 | 66x | stage_.commit(n); | ||
| 221 | 66x | } | ||
| 222 | ||||
| 223 | bool | |||
| 224 | 4411x | serializer:: | ||
| 225 | chunked_() const noexcept | |||
| 226 | { | |||
| 227 | 4411x | return payload_ == payload::chunked; | ||
| 228 | } | |||
| 229 | ||||
| 230 | bool | |||
| 231 | 548x | serializer:: | ||
| 232 | to_eof_() const noexcept | |||
| 233 | { | |||
| 234 | 548x | return payload_ == payload::to_eof; | ||
| 235 | } | |||
| 236 | ||||
| 237 | bool | |||
| 238 | 165x | serializer:: | ||
| 239 | should_coalesce_(std::size_t avail) const noexcept | |||
| 240 | { | |||
| 241 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 153 times.
|
165x | if(avail > stage_.capacity()) | |
| 242 | 12x | return false; | ||
| 243 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 146 times.
|
153x | if(enc_) | |
| 244 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
|
11x | return !enc_started_ && | |
| 245 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
11x | avail + stage_.len < enc_threshold_; | |
| 246 | 146x | return avail < min_direct_; | ||
| 247 | } | |||
| 248 | ||||
| 249 | detail::flat_buffer& | |||
| 250 | 2762x | serializer:: | ||
| 251 | buffered_() noexcept | |||
| 252 | { | |||
| 253 |
2/2✓ Branch 1 taken 2308 times.
✓ Branch 2 taken 454 times.
|
2762x | return enc_out_.empty() ? stage_ : enc_out_; | |
| 254 | } | |||
| 255 | ||||
| 256 | capy::const_buffer | |||
| 257 | 465x | serializer:: | ||
| 258 | epilogue_buf_() const noexcept | |||
| 259 | { | |||
| 260 | static constexpr char s[] = | |||
| 261 | "\r\n" "0\r\n" "\r\n"; | |||
| 262 |
2/2✓ Branch 0 taken 459 times.
✓ Branch 1 taken 6 times.
|
465x | std::size_t const skip = crlf_owed_ ? 0 : 2; | |
| 263 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 389 times.
|
465x | std::size_t const drop = trailer_ ? 2 : 0; | |
| 264 | 465x | return { s + skip, sizeof(s) - 1 - skip - drop }; | ||
| 265 | } | |||
| 266 | ||||
| 267 | capy::const_buffer | |||
| 268 | 465x | serializer:: | ||
| 269 | trailer_buf_() const noexcept | |||
| 270 | { | |||
| 271 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 389 times.
|
465x | if(trailer_) | |
| 272 | 76x | return capy::make_buffer(trailer_->buffer()); | ||
| 273 | 389x | return {}; | ||
| 274 | } | |||
| 275 | ||||
| 276 | bool | |||
| 277 | 460x | serializer:: | ||
| 278 | settled_() const noexcept | |||
| 279 | { | |||
| 280 |
2/2✓ Branch 2 taken 71 times.
✓ Branch 3 taken 389 times.
|
460x | if(msg_->buffer().size() != header_offset_) | |
| 281 | 71x | return false; | ||
| 282 | ||||
| 283 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 319 times.
|
389x | if(input_framed_ != 0) | |
| 284 | 70x | return false; | ||
| 285 | ||||
| 286 |
6/6✓ Branch 1 taken 310 times.
✓ Branch 2 taken 9 times.
✓ Branch 4 taken 80 times.
✓ Branch 5 taken 230 times.
✓ Branch 6 taken 89 times.
✓ Branch 7 taken 230 times.
|
319x | if(!stage_.empty() || !enc_out_.empty()) | |
| 287 | 89x | return false; | ||
| 288 | ||||
| 289 |
2/2✓ Branch 1 taken 119 times.
✓ Branch 2 taken 111 times.
|
349x | if( chunked_() && | |
| 290 | 119x | tail_offset_ != | ||
| 291 |
2/2✓ Branch 2 taken 49 times.
✓ Branch 3 taken 70 times.
|
238x | epilogue_buf_().size() + | |
| 292 |
2/2✓ Branch 2 taken 49 times.
✓ Branch 3 taken 181 times.
|
349x | trailer_buf_().size()) | |
| 293 | 49x | return false; | ||
| 294 | ||||
| 295 | 181x | return owed_ == 0; | ||
| 296 | } | |||
| 297 | ||||
| 298 | void | |||
| 299 | 127x | serializer:: | ||
| 300 | open_chunk_(std::uint64_t s) noexcept | |||
| 301 | { | |||
| 302 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
|
127x | BOOST_ASSERT(prefix_rem_ == 0); | |
| 303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
|
127x | BOOST_ASSERT(owed_ == 0); | |
| 304 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
|
127x | BOOST_ASSERT(s != 0); | |
| 305 | ||||
| 306 | 127x | auto const p0 = buffered_().ptr + buffered_().pos; | ||
| 307 | 127x | auto p = p0; | ||
| 308 | ||||
| 309 | 127x | *--p = '\n'; | ||
| 310 | 127x | *--p = '\r'; | ||
| 311 | ||||
| 312 | static constexpr char hex[] = "0123456789abcdef"; | |||
| 313 | 127x | auto v = s; | ||
| 314 | do | |||
| 315 | { | |||
| 316 | 205x | *--p = hex[v & 0xF]; | ||
| 317 | 205x | v >>= 4; | ||
| 318 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 127 times.
|
205x | } while(v != 0); | |
| 319 | ||||
| 320 | // prev chunk's CRLF | |||
| 321 |
2/2✓ Branch 0 taken 50 times.
✓ Branch 1 taken 77 times.
|
127x | if(crlf_owed_) | |
| 322 | { | |||
| 323 | 50x | *--p = '\n'; | ||
| 324 | 50x | *--p = '\r'; | ||
| 325 | } | |||
| 326 | 127x | crlf_owed_ = true; | ||
| 327 | ||||
| 328 | 127x | prefix_rem_ = static_cast<std::uint8_t>(p0 - p); | ||
| 329 | 127x | owed_ = s; | ||
| 330 | 127x | } | ||
| 331 | ||||
| 332 | void | |||
| 333 | 200x | serializer:: | ||
| 334 | encode_(source& src, std::error_code& ec) | |||
| 335 | { | |||
| 336 | 74x | auto process = [&]( | ||
| 337 | capy::const_buffer in, bool more) | |||
| 338 | { | |||
| 339 |
1/1✓ Branch 2 taken 74 times.
|
148x | auto const r = enc_->process( | |
| 340 | 74x | enc_out_.prepare(), in, more); | ||
| 341 | 74x | enc_started_ = true; | ||
| 342 | 74x | enc_out_.commit(r.produced); | ||
| 343 |
2/2✓ Branch 2 taken 28 times.
✓ Branch 3 taken 46 times.
|
74x | if(r.ec == capy::cond::eof) | |
| 344 | { | |||
| 345 | 28x | revise_framing_(enc_out_.size()); | ||
| 346 | 28x | enc_ = nullptr; | ||
| 347 | } | |||
| 348 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 43 times.
|
46x | else if(r.ec) | |
| 349 | { | |||
| 350 | 3x | ec = r.ec; | ||
| 351 | } | |||
| 352 | 74x | return r.consumed; | ||
| 353 | 200x | }; | ||
| 354 | ||||
| 355 | // staged input drains first | |||
| 356 |
2/2✓ Branch 1 taken 9 times.
✓ Branch 2 taken 197 times.
|
206x | while(!stage_.empty()) | |
| 357 | { | |||
| 358 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 8 times.
|
9x | if(enc_out_.capacity() == 0) | |
| 359 | 173x | return; | ||
| 360 |
4/4✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 2 times.
|
8x | auto const more = !sealed_() || src.remain != 0; | |
| 361 |
1/1✓ Branch 2 taken 8 times.
|
8x | auto const n = process(stage_.data(), more); | |
| 362 | 8x | stage_.consume(n); | ||
| 363 |
6/6✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 6 times.
|
8x | if(ec || !enc_) | |
| 364 | 2x | return; | ||
| 365 | } | |||
| 366 | ||||
| 367 | // the supplied buffers | |||
| 368 |
2/2✓ Branch 2 taken 192 times.
✓ Branch 3 taken 39 times.
|
428x | for(auto cur = src.next(); cur.size() != 0;) | |
| 369 | { | |||
| 370 |
2/2✓ Branch 1 taken 139 times.
✓ Branch 2 taken 53 times.
|
192x | if(enc_out_.capacity() == 0) | |
| 371 | 158x | return; | ||
| 372 |
4/4✓ Branch 1 taken 36 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 35 times.
|
53x | auto const more = !sealed_() || src.remain != 0; | |
| 373 |
1/1✓ Branch 1 taken 53 times.
|
53x | auto const n = process(cur, more); | |
| 374 | 53x | cur += n; | ||
| 375 | 53x | input_digested_ += n; | ||
| 376 |
6/6✓ Branch 1 taken 52 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 34 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 34 times.
|
53x | if(ec || !enc_) | |
| 377 | 19x | return; | ||
| 378 |
2/2✓ Branch 1 taken 23 times.
✓ Branch 2 taken 11 times.
|
34x | if(cur.size() == 0) | |
| 379 | 11x | cur = src.next(); | ||
| 380 | } | |||
| 381 | ||||
| 382 | // finish the stream | |||
| 383 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 27 times.
|
42x | while(sealed_()) | |
| 384 | { | |||
| 385 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 13 times.
|
15x | if(enc_out_.capacity() == 0) | |
| 386 | 2x | return; | ||
| 387 |
1/1✓ Branch 2 taken 13 times.
|
13x | process({}, false); | |
| 388 |
6/6✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 3 times.
|
13x | if(ec || !enc_) | |
| 389 | 10x | return; | ||
| 390 | } | |||
| 391 | } | |||
| 392 | ||||
| 393 | system::result<bool, std::error_code> | |||
| 394 | 684x | serializer:: | ||
| 395 | ingest_( | |||
| 396 | source& src, | |||
| 397 | bool more) | |||
| 398 | { | |||
| 399 |
4/4✓ Branch 0 taken 409 times.
✓ Branch 1 taken 275 times.
✓ Branch 3 taken 187 times.
✓ Branch 4 taken 222 times.
|
684x | auto const sealing = !more && !sealed_(); | |
| 400 | 1368x | auto const have = std::uint64_t(src.remain) + | ||
| 401 | 684x | stage_.size() + enc_out_.size(); | ||
| 402 | ||||
| 403 |
2/2✓ Branch 1 taken 321 times.
✓ Branch 2 taken 363 times.
|
684x | if(chunked_()) | |
| 404 | { | |||
| 405 |
8/8✓ Branch 1 taken 45 times.
✓ Branch 2 taken 276 times.
✓ Branch 4 taken 40 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 39 times.
✓ Branch 8 taken 1 time.
✓ Branch 9 taken 320 times.
|
321x | if(sealed_() && !enc_ && src.remain != 0) | |
| 406 | 2x | return make_error_code( | ||
| 407 | 1x | std::errc::invalid_argument); | ||
| 408 | } | |||
| 409 |
2/2✓ Branch 1 taken 223 times.
✓ Branch 2 taken 140 times.
|
363x | else if(!enc_) | |
| 410 | { | |||
| 411 |
4/4✓ Branch 0 taken 216 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 212 times.
|
439x | if( have > owed_ || | |
| 412 |
6/6✓ Branch 1 taken 108 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 70 times.
✓ Branch 4 taken 38 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 66 times.
|
216x | (!to_eof_() && sealing && have < owed_)) | |
| 413 | { | |||
| 414 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11x | if(to_eof_()) | |
| 415 | ✗ | return make_error_code( | ||
| 416 | ✗ | std::errc::invalid_argument); | ||
| 417 | 11x | return error::body_size_mismatch; | ||
| 418 | } | |||
| 419 | } | |||
| 420 | ||||
| 421 |
2/2✓ Branch 0 taken 183 times.
✓ Branch 1 taken 489 times.
|
672x | if(sealing) | |
| 422 | 183x | state_ = state::sealed; | ||
| 423 | ||||
| 424 |
2/2✓ Branch 1 taken 404 times.
✓ Branch 2 taken 268 times.
|
672x | if(sealed_()) | |
| 425 | { | |||
| 426 |
8/8✓ Branch 1 taken 168 times.
✓ Branch 2 taken 236 times.
✓ Branch 3 taken 29 times.
✓ Branch 4 taken 139 times.
✓ Branch 5 taken 23 times.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 398 times.
|
427x | if( enc_ && !enc_started_ && header_offset_ == 0 && | |
| 427 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 17 times.
|
23x | have < enc_threshold_) | |
| 428 | { | |||
| 429 | 6x | msg_->erase(http::field::content_encoding); | ||
| 430 | 6x | enc_ = nullptr; | ||
| 431 | } | |||
| 432 |
6/6✓ Branch 1 taken 242 times.
✓ Branch 2 taken 162 times.
✓ Branch 3 taken 152 times.
✓ Branch 4 taken 90 times.
✓ Branch 5 taken 152 times.
✓ Branch 6 taken 252 times.
|
404x | if(!enc_ && sealing) | |
| 433 | 152x | revise_framing_(have); | ||
| 434 | } | |||
| 435 | ||||
| 436 | // small inputs are coalesced into the stage | |||
| 437 |
8/8✓ Branch 1 taken 268 times.
✓ Branch 2 taken 404 times.
✓ Branch 3 taken 165 times.
✓ Branch 4 taken 103 times.
✓ Branch 5 taken 49 times.
✓ Branch 6 taken 116 times.
✓ Branch 7 taken 49 times.
✓ Branch 8 taken 623 times.
|
837x | if( !sealed_() && src.remain != 0 && | |
| 438 | 165x | should_coalesce_(src.remain)) | ||
| 439 | { | |||
| 440 | 49x | input_digested_ = src.remain; | ||
| 441 |
2/2✓ Branch 2 taken 49 times.
✓ Branch 3 taken 49 times.
|
98x | for(auto b = src.next(); b.size() != 0; | |
| 442 | 49x | b = src.next()) | ||
| 443 | 49x | stage_.commit(capy::buffer_copy( | ||
| 444 | 98x | stage_.prepare(), b)); | ||
| 445 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 47 times.
|
49x | if(enc_) | |
| 446 | 2x | return false; | ||
| 447 | } | |||
| 448 |
2/2✓ Branch 1 taken 200 times.
✓ Branch 2 taken 423 times.
|
623x | else if(enc_) | |
| 449 | { | |||
| 450 | 200x | std::error_code ec; | ||
| 451 |
1/1✓ Branch 1 taken 200 times.
|
200x | encode_(src, ec); | |
| 452 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 197 times.
|
200x | if(ec) | |
| 453 | { | |||
| 454 | 3x | enc_ = nullptr; | ||
| 455 | 3x | state_ = state::failed; | ||
| 456 | 3x | return ec; | ||
| 457 | } | |||
| 458 | ||||
| 459 | 197x | auto const finished = (enc_ == nullptr); | ||
| 460 | 197x | auto const encoded = enc_out_.size(); | ||
| 461 |
6/6✓ Branch 1 taken 147 times.
✓ Branch 2 taken 50 times.
✓ Branch 4 taken 138 times.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 138 times.
✓ Branch 7 taken 59 times.
|
197x | if(!chunked_() && !to_eof_()) | |
| 462 | { | |||
| 463 |
6/6✓ Branch 0 taken 136 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 126 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 9 times.
|
138x | if(encoded > owed_ || (finished && encoded != owed_)) | |
| 464 | { | |||
| 465 | 3x | state_ = state::failed; | ||
| 466 | 3x | return error::body_size_mismatch; | ||
| 467 | } | |||
| 468 | } | |||
| 469 |
4/4✓ Branch 0 taken 169 times.
✓ Branch 1 taken 25 times.
✓ Branch 3 taken 144 times.
✓ Branch 4 taken 25 times.
|
194x | auto const flush = finished || enc_out_.capacity() == 0; | |
| 470 |
8/8✓ Branch 0 taken 169 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 167 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 30 times.
✓ Branch 6 taken 137 times.
✓ Branch 7 taken 30 times.
✓ Branch 8 taken 164 times.
|
194x | if(flush && encoded != 0 && chunked_()) | |
| 471 | 30x | open_chunk_(encoded); | ||
| 472 | 194x | return flush; | ||
| 473 | } | |||
| 474 | ||||
| 475 |
4/4✓ Branch 1 taken 129 times.
✓ Branch 2 taken 141 times.
✓ Branch 3 taken 123 times.
✓ Branch 4 taken 6 times.
|
399x | auto const flush = src.remain != 0 || sealed_() || | |
| 476 |
4/4✓ Branch 0 taken 270 times.
✓ Branch 1 taken 200 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 122 times.
|
869x | should_drain() || stage_.pos != 0; | |
| 477 |
6/6✓ Branch 0 taken 348 times.
✓ Branch 1 taken 122 times.
✓ Branch 3 taken 152 times.
✓ Branch 4 taken 196 times.
✓ Branch 5 taken 152 times.
✓ Branch 6 taken 318 times.
|
470x | if(flush && chunked_()) | |
| 478 | { | |||
| 479 | 152x | auto const s = buffered_().size() + src.remain; | ||
| 480 |
2/2✓ Branch 0 taken 97 times.
✓ Branch 1 taken 55 times.
|
152x | if(s != 0) | |
| 481 | 97x | open_chunk_(s); | ||
| 482 | } | |||
| 483 | 470x | return flush; | ||
| 484 | } | |||
| 485 | ||||
| 486 | std::span<capy::const_buffer const> | |||
| 487 | 1086x | serializer:: | ||
| 488 | gather_( | |||
| 489 | std::span<capy::const_buffer> dest, | |||
| 490 | source& src, | |||
| 491 | bool flush_body, | |||
| 492 | bool flush_header) noexcept | |||
| 493 | { | |||
| 494 | 1086x | std::size_t n = 0; | ||
| 495 | ||||
| 496 | // returns false when dest is exhausted | |||
| 497 | 3033x | auto const push = [&](capy::const_buffer b) | ||
| 498 | { | |||
| 499 |
2/2✓ Branch 1 taken 1094 times.
✓ Branch 2 taken 1939 times.
|
3033x | if(b.size() == 0) | |
| 500 | 1094x | return true; | ||
| 501 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 1924 times.
|
1939x | if(n == dest.size()) | |
| 502 | 15x | return false; | ||
| 503 | 1924x | dest[n++] = b; | ||
| 504 | 1924x | return true; | ||
| 505 | 1086x | }; | ||
| 506 | ||||
| 507 | // [header] | |||
| 508 |
2/2✓ Branch 0 taken 1033 times.
✓ Branch 1 taken 53 times.
|
1086x | if(flush_header) | |
| 509 | 1033x | push(suffix(capy::make_buffer( | ||
| 510 | 1033x | msg_->buffer()), header_offset_)); | ||
| 511 | ||||
| 512 | // [CRLF + chunk_header][buffered] | |||
| 513 | 1086x | auto const& buffered = buffered_(); | ||
| 514 | 1086x | auto buffered_take = std::uint64_t(buffered.size()); | ||
| 515 |
2/2✓ Branch 1 taken 714 times.
✓ Branch 2 taken 372 times.
|
1086x | if(chunked_()) | |
| 516 | 714x | buffered_take = (std::min)(buffered_take, owed_); | ||
| 517 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 334 times.
|
372x | else if(!flush_body) | |
| 518 | 38x | buffered_take = 0; | ||
| 519 | 1086x | push({ buffered.ptr + buffered.pos - prefix_rem_, | ||
| 520 | 1086x | prefix_rem_ + std::size_t(buffered_take) }); | ||
| 521 | ||||
| 522 | // [supplied body] | |||
| 523 | 1086x | auto const quota = owed_ - buffered_take; | ||
| 524 | 1086x | auto const supplied = src.remain; | ||
| 525 | 1086x | std::size_t placed = 0; | ||
| 526 |
2/2✓ Branch 1 taken 914 times.
✓ Branch 2 taken 172 times.
|
1086x | if(!enc_) | |
| 527 | { | |||
| 528 |
2/2✓ Branch 0 taken 659 times.
✓ Branch 1 taken 825 times.
|
1484x | while(placed != quota) | |
| 529 | { | |||
| 530 | 659x | auto const b = src.next(); | ||
| 531 |
2/2✓ Branch 1 taken 81 times.
✓ Branch 2 taken 578 times.
|
659x | if(b.size() == 0) | |
| 532 | 89x | break; | ||
| 533 | 578x | auto const k = clamp(quota - placed, b.size()); | ||
| 534 |
2/2✓ Branch 3 taken 8 times.
✓ Branch 4 taken 570 times.
|
578x | if(!push({ b.data(), k })) | |
| 535 | 8x | break; | ||
| 536 | 570x | placed += k; | ||
| 537 | } | |||
| 538 | } | |||
| 539 | 1086x | input_framed_ = placed; | ||
| 540 | ||||
| 541 | // [epilogue][trailer] | |||
| 542 |
4/4✓ Branch 2 taken 329 times.
✓ Branch 3 taken 131 times.
✓ Branch 5 taken 173 times.
✓ Branch 6 taken 156 times.
|
1546x | if( sealed_() && !enc_ && chunked_() && | |
| 543 |
8/8✓ Branch 0 taken 460 times.
✓ Branch 1 taken 626 times.
✓ Branch 3 taken 170 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 168 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 168 times.
✓ Branch 8 taken 918 times.
|
1546x | buffered.size() + supplied == owed_ && | |
| 544 | placed == supplied) | |||
| 545 | { | |||
| 546 | 168x | auto const eb = epilogue_buf_(); | ||
| 547 | 168x | auto const tb = trailer_buf_(); | ||
| 548 | 168x | auto const k = clamp(tail_offset_, eb.size()); | ||
| 549 | 168x | push(suffix(eb, k)); | ||
| 550 | 168x | push(suffix(tb, tail_offset_ - k)); | ||
| 551 | } | |||
| 552 | ||||
| 553 | 1086x | return { dest.data(), n }; | ||
| 554 | } | |||
| 555 | ||||
| 556 | system::result< | |||
| 557 | std::span<capy::const_buffer const>, | |||
| 558 | std::error_code> | |||
| 559 | 1276x | serializer:: | ||
| 560 | frame_( | |||
| 561 | std::span<capy::const_buffer> dest, | |||
| 562 | source& src, | |||
| 563 | bool more) | |||
| 564 | { | |||
| 565 |
4/4✓ Branch 0 taken 152 times.
✓ Branch 1 taken 952 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 4 times.
|
1276x | switch(state_) | |
| 566 | { | |||
| 567 | 152x | case state::started: | ||
| 568 | 152x | select_framing_(); | ||
| 569 | BOOST_FALLTHROUGH; | |||
| 570 | 1104x | case state::streaming: | ||
| 571 | case state::sealed: | |||
| 572 | { | |||
| 573 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1104 times.
|
1104x | BOOST_ASSERT(input_digested_ == 0); | |
| 574 | ||||
| 575 | 1104x | auto const drain_call = (src.remain == 0); | ||
| 576 | ||||
| 577 | 1104x | bool flush_body = true; | ||
| 578 |
6/6✓ Branch 0 taken 734 times.
✓ Branch 1 taken 370 times.
✓ Branch 3 taken 314 times.
✓ Branch 4 taken 420 times.
✓ Branch 5 taken 684 times.
✓ Branch 6 taken 420 times.
|
1104x | if(owed_ == 0 || !chunked_()) | |
| 579 | { | |||
| 580 |
1/1✓ Branch 1 taken 684 times.
|
684x | auto const r = ingest_(src, more); | |
| 581 |
2/2✓ Branch 1 taken 18 times.
✓ Branch 2 taken 666 times.
|
684x | if(r.has_error()) | |
| 582 | 18x | return r.error(); | ||
| 583 |
1/1✓ Branch 1 taken 666 times.
|
666x | flush_body = *r; | |
| 584 | } | |||
| 585 | ||||
| 586 | 1086x | auto const out = gather_( | ||
| 587 |
4/4✓ Branch 0 taken 149 times.
✓ Branch 1 taken 937 times.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 53 times.
|
1086x | dest, src, flush_body, flush_body || drain_call); | |
| 588 | ||||
| 589 |
6/6✓ Branch 1 taken 142 times.
✓ Branch 2 taken 944 times.
✓ Branch 4 taken 139 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 139 times.
✓ Branch 7 taken 947 times.
|
1086x | if(out.empty() && !dest.empty()) | |
| 590 | { | |||
| 591 |
4/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 6 times.
|
139x | if(!more && owed_ != 0) | |
| 592 | { | |||
| 593 |
4/6✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
3x | if(to_eof_() || chunked_()) | |
| 594 | 6x | return make_error_code( | ||
| 595 | 3x | std::errc::invalid_argument); | ||
| 596 | ✗ | return error::body_size_mismatch; | ||
| 597 | } | |||
| 598 |
5/6✓ Branch 1 taken 6 times.
✓ Branch 2 taken 130 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 130 times.
|
136x | if(sealed_() && settled_()) | |
| 599 | 6x | state_ = state::done; | ||
| 600 | } | |||
| 601 | ||||
| 602 | 1083x | return out; | ||
| 603 | } | |||
| 604 | 168x | case state::done: | ||
| 605 |
5/6✓ Branch 0 taken 165 times.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 165 times.
|
168x | if(src.remain != 0 || !stage_.empty()) | |
| 606 | 6x | return make_error_code( | ||
| 607 | 3x | std::errc::invalid_argument); | ||
| 608 | 165x | return {}; | ||
| 609 | 4x | default: | ||
| 610 | 8x | return make_error_code( | ||
| 611 | 4x | std::errc::state_not_recoverable); | ||
| 612 | }; | |||
| 613 | } | |||
| 614 | ||||
| 615 | std::size_t | |||
| 616 | 1270x | serializer:: | ||
| 617 | consume(std::size_t n) noexcept | |||
| 618 | { | |||
| 619 | // [header] | |||
| 620 | { | |||
| 621 | 1270x | auto const k = clamp( | ||
| 622 | 1270x | n, msg_->buffer().size() - header_offset_); | ||
| 623 | 1270x | header_offset_ += static_cast<std::uint32_t>(k); | ||
| 624 | 1270x | n -= k; | ||
| 625 | } | |||
| 626 | ||||
| 627 | // [CRLF + chunk_header] | |||
| 628 | { | |||
| 629 | 1270x | auto const k = clamp(n, prefix_rem_); | ||
| 630 | 1270x | prefix_rem_ -= static_cast<std::uint8_t>(k); | ||
| 631 | 1270x | n -= k; | ||
| 632 | } | |||
| 633 | ||||
| 634 | // [buffered] | |||
| 635 | { | |||
| 636 | 1270x | auto& buffered = buffered_(); | ||
| 637 | 1270x | auto const rem = clamp(owed_, buffered.size()); | ||
| 638 | 1270x | auto const k = clamp(n, rem); | ||
| 639 | 1270x | buffered.consume(k); | ||
| 640 | 1270x | owed_ -= k; | ||
| 641 | 1270x | n -= k; | ||
| 642 | } | |||
| 643 | ||||
| 644 | // [supplied body] | |||
| 645 | std::size_t input_taken; | |||
| 646 | { | |||
| 647 | 1270x | auto const k = clamp(n, input_framed_); | ||
| 648 | 1270x | input_framed_ -= k; | ||
| 649 | 1270x | owed_ -= k; | ||
| 650 | 1270x | input_taken = k; | ||
| 651 | 1270x | n -= k; | ||
| 652 | } | |||
| 653 | ||||
| 654 |
2/2✓ Branch 1 taken 454 times.
✓ Branch 2 taken 816 times.
|
1270x | if(sealed_()) | |
| 655 | { | |||
| 656 | // [epilogue][trailer] | |||
| 657 |
2/2✓ Branch 1 taken 178 times.
✓ Branch 2 taken 276 times.
|
454x | if(chunked_()) | |
| 658 | { | |||
| 659 | 178x | auto const total = epilogue_buf_().size() + | ||
| 660 | 178x | trailer_buf_().size(); | ||
| 661 | 178x | auto const k = clamp(n, total - tail_offset_); | ||
| 662 | 178x | tail_offset_ += static_cast<std::uint32_t>(k); | ||
| 663 | 178x | n -= k; | ||
| 664 | } | |||
| 665 | ||||
| 666 |
2/2✓ Branch 1 taken 169 times.
✓ Branch 2 taken 285 times.
|
454x | if(settled_()) | |
| 667 | 169x | state_ = state::done; | ||
| 668 | } | |||
| 669 | ||||
| 670 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1270 times.
|
1270x | BOOST_ASSERT(n == 0); | |
| 671 | ||||
| 672 |
2/2✓ Branch 0 taken 91 times.
✓ Branch 1 taken 1179 times.
|
1270x | if(input_digested_ != 0) | |
| 673 | 91x | return std::exchange(input_digested_, 0); | ||
| 674 | ||||
| 675 | 1179x | return input_taken; | ||
| 676 | } | |||
| 677 | ||||
| 678 | } // namespace burl | |||
| 679 | } // namespace boost | |||
| 680 |