@@ -29,11 +29,11 @@ serializer(config const& cfg, capy::any_write_stream* stream)
2929 , min_prepare_(cfg.min_prepare)
3030 , direct_thr_(cfg.direct_thr)
3131 , enc_thr_(cfg.enc_thr)
32- , in_ (new unsigned char [
32+ , out_ (new unsigned char [
3333 cfg.out_buffer + cfg.enc_buffer + margin] + margin)
34- , in_cap_(cfg.out_buffer)
35- , out_(in_)
3634 , out_cap_(cfg.enc_buffer)
35+ , in_(out_)
36+ , in_cap_(cfg.out_buffer)
3737{
3838}
3939
@@ -74,24 +74,24 @@ serializer::
7474~serializer ()
7575{
7676 if (out_)
77- delete[] (( out_ > in_ ? in_ : out_) - margin);
77+ delete[] (out_ - margin);
7878}
7979
8080void
8181serializer::
8282reset (
8383 capy::any_write_stream* stream,
8484 http::message_base* msg,
85- encoder_base * enc,
85+ encoder * enc,
8686 bool head) noexcept
8787{
88- if (out_ > in_ )
89- out_ = in_ ;
88+ if (head )
89+ enc = nullptr ;
9090
91- if (!enc_ && enc )
91+ if (!enc == (in_ != out_) )
9292 {
93- std::swap (out_cap_, in_cap_ );
94- in_ += out_cap_;
93+ std::swap (in_cap_, out_cap_ );
94+ in_ = enc ? out_ + out_cap_ : out_ ;
9595 }
9696
9797 stream_ = stream;
@@ -169,7 +169,7 @@ do_commit(std::size_t n) noexcept
169169
170170bool
171171serializer::
172- can_coalesce (std::size_t avail) const noexcept
172+ should_coalesce (std::size_t avail) const noexcept
173173{
174174 if (avail > capacity ())
175175 return false ;
182182serializer::
183183finalize (std::size_t remaining) noexcept
184184{
185+ if (head_)
186+ return ;
187+
185188 if (enc_)
186189 {
187190 if (enc_started_)
@@ -192,8 +195,6 @@ finalize(std::size_t remaining) noexcept
192195
193196 msg_->erase (http::field::content_encoding);
194197 enc_ = nullptr ;
195- std::swap (out_, in_);
196- std::swap (out_cap_, in_cap_);
197198 }
198199 decide_framing (remaining);
199200}
@@ -246,11 +247,11 @@ encode(
246247 co_return { ec, consumed };
247248 }
248249
249- capy::mutable_buffer out =
250- { out_ + out_len_, out_cap_ - out_len_ };
251-
252250 auto r = enc_->process (
253- out, in, eof && n == tail.size ());
251+ { out_ + out_len_, out_cap_ - out_len_ },
252+ in,
253+ eof && n == tail.size ());
254+
254255 enc_started_ = true ;
255256 out_len_ += r.produced ;
256257 in += r.consumed ;
@@ -284,12 +285,11 @@ flush(
284285 std::span<capy::const_buffer const > tail,
285286 bool eof)
286287{
287- if (!enc_)
288- out_len_ = in_len_;
289-
290- auto const tail_size = capy::buffer_size (tail);
291- auto const chunked = msg_->chunked ();
292- BOOST_ASSERT (eof || out_len_ + tail_size != 0 );
288+ auto const buf = enc_ ? out_ : in_;
289+ auto & len = enc_ ? out_len_ : in_len_;
290+ auto const tail_len = capy::buffer_size (tail);
291+ auto const chunked = msg_->chunked () && !head_;
292+ BOOST_ASSERT (eof || len + tail_len != 0 );
293293 BOOST_ASSERT (tail.size () <= capy::detail::max_iovec_);
294294
295295 capy::const_buffer vec[capy::detail::max_iovec_ + 3 ];
@@ -306,20 +306,43 @@ flush(
306306
307307 if (chunked)
308308 {
309- append (chunk_frame (tail_size));
309+ static constexpr char hex[] = " 0123456789abcdef" ;
310+ auto s = len + tail_len;
311+ auto p = buf;
312+
313+ *--p = ' \n ' ;
314+ *--p = ' \r ' ;
315+
316+ do
317+ {
318+ *--p = hex[s & 0xF ];
319+ s >>= 4 ;
320+ } while (s != 0 );
321+
322+ // prev chunk's CRLF
323+ if (total_body_)
324+ {
325+ *--p = ' \n ' ;
326+ *--p = ' \r ' ;
327+ }
328+
329+ append ({ p, static_cast <std::size_t >(buf - p) + len });
310330 }
311331 else
312332 {
313- auto const declared =
314- msg_->payload () == http::payload::size
315- ? msg_->payload_size () : 0 ;
316- auto const produced = total_body_ + out_len_ + tail_size;
333+ auto const decl = [&]()-> std::uint64_t
334+ {
335+ if (head_ || msg_->payload () != http::payload::size)
336+ return 0 ;
337+ return msg_->payload_size ();
338+ }();
339+ auto const prod = total_body_ + len + tail_len;
317340
318- if (produced > declared || (eof && produced != declared ))
341+ if (prod > decl || (eof && prod != decl ))
319342 co_return { error::body_size_mismatch, 0 };
320343
321- if (out_len_ != 0 )
322- append ({ out_, out_len_ });
344+ if (len != 0 )
345+ append ({ buf, len });
323346 }
324347
325348 auto const owned = sum;
@@ -328,18 +351,16 @@ flush(
328351 append (b);
329352
330353 if (chunked && eof)
331- append ({ " \r\n 0\r\n\r\n " , out_len_ || tail_size ? 7u : 2u });
354+ append ({ " \r\n 0\r\n\r\n " , len || tail_len ? 7u : 2u });
332355
333- auto const need = chunked || eof ? sum : owned + (tail_size != 0 ) ;
356+ auto const need = chunked || eof ? sum : owned + !!tail_len ;
334357 auto [ec, written] = co_await write_at_least ({ vec, n }, need);
335358 if (ec)
336359 co_return { ec, 0 };
337360
338- auto const consumed = (std::min)(written - owned, tail_size);
339- total_body_ += out_len_ + consumed;
340- out_len_ = 0 ;
341- if (!enc_)
342- in_len_ = 0 ;
361+ auto const consumed = (std::min)(written - owned, tail_len);
362+ total_body_ += len + consumed;
363+ len = 0 ;
343364 hdr_sent_ = true ;
344365 done_ = eof;
345366 co_return { {}, consumed };
@@ -366,34 +387,6 @@ write_at_least(
366387 co_return { {}, written };
367388}
368389
369- capy::const_buffer
370- serializer::
371- chunk_frame (std::size_t tail_size) noexcept
372- {
373- static constexpr char hex[] = " 0123456789abcdef" ;
374- auto s = out_len_ + tail_size;
375- auto p = out_;
376-
377- *--p = ' \n ' ;
378- *--p = ' \r ' ;
379-
380- do
381- {
382- *--p = hex[s & 0xF ];
383- s >>= 4 ;
384- } while (s != 0 );
385-
386- // prev chunk's CRLF
387- if (total_body_ != 0 )
388- {
389- *--p = ' \n ' ;
390- *--p = ' \r ' ;
391- }
392-
393- return { p, static_cast <std::size_t >(
394- out_ - p) + out_len_ };
395- }
396-
397390} // namespace detail
398391} // namespace burl
399392} // namespace boost
0 commit comments