1717#include < boost/http_proto/detail/header.hpp>
1818#include < boost/http_proto/detail/workspace.hpp>
1919#include < boost/http_proto/source.hpp>
20+
2021#include < boost/buffers/circular_buffer.hpp>
2122#include < boost/buffers/const_buffer_span.hpp>
2223#include < boost/buffers/range.hpp>
2324#include < boost/buffers/type_traits.hpp>
2425#include < boost/system/result.hpp>
25- # include < cstdint >
26+
2627#include < memory>
28+ #include < numeric>
2729#include < type_traits>
2830#include < utility>
2931
3032namespace boost {
3133namespace http_proto {
3234
3335#ifndef BOOST_HTTP_PROTO_DOCS
34- class request ;
35- class response ;
36- class request_view ;
37- class response_view ;
3836class message_view_base ;
3937namespace detail {
4038class filter ;
@@ -219,36 +217,14 @@ class serializer
219217 void
220218 consume (std::size_t n);
221219
222- /* * Applies deflate compression to the current message
223-
224- After @ref reset is called, compression is not
225- applied to the next message.
226-
227- Must be called before any calls to @ref start.
228- */
229- BOOST_HTTP_PROTO_DECL
230- void
231- use_deflate_encoding ();
232-
233- /* * Applies gzip compression to the current message
220+ private:
221+ class const_buf_gen_base ;
234222
235- After @ref reset is called, compression is not
236- applied to the next message.
223+ template < class >
224+ class const_buf_gen ;
237225
238- Must be called before any calls to @ref start.
239- */
240- BOOST_HTTP_PROTO_DECL
241- void
242- use_gzip_encoding ();
243-
244- private:
245- static void copy (
246- buffers::const_buffer*,
247- buffers::const_buffer const *,
248- std::size_t n) noexcept ;
249- auto
250- make_array (std::size_t n) ->
251- detail::array_of_const_buffers;
226+ detail::array_of_const_buffers
227+ make_array (std::size_t n);
252228
253229 template <
254230 class Source ,
@@ -279,10 +255,24 @@ class serializer
279255 ws_, std::forward<Args>(args)...);
280256 }
281257
282- BOOST_HTTP_PROTO_DECL void start_init (message_view_base const &);
283- BOOST_HTTP_PROTO_DECL void start_empty (message_view_base const &);
284- BOOST_HTTP_PROTO_DECL void start_buffers (message_view_base const &);
285- BOOST_HTTP_PROTO_DECL void start_source (message_view_base const &, source*);
258+ BOOST_HTTP_PROTO_DECL
259+ void
260+ start_init (
261+ message_view_base const &);
262+
263+ BOOST_HTTP_PROTO_DECL
264+ void
265+ start_empty (
266+ message_view_base const &);
267+
268+ BOOST_HTTP_PROTO_DECL
269+ void start_buffers (
270+ message_view_base const &);
271+
272+ BOOST_HTTP_PROTO_DECL
273+ void
274+ start_source (
275+ message_view_base const &, source*);
286276
287277 enum class style
288278 {
@@ -292,68 +282,25 @@ class serializer
292282 stream
293283 };
294284
295- // chunked-body = *chunk
296- // last-chunk
297- // trailer-section
298- // CRLF
299-
300- static
301- constexpr
302- std::size_t
303- crlf_len_ = 2 ;
304-
305- // chunk = chunk-size [ chunk-ext ] CRLF
306- // chunk-data CRLF
307- static
308- constexpr
309- std::size_t
310- chunk_header_len_ =
311- 16 + // 16 hex digits => 64 bit number
312- crlf_len_;
313-
314- // last-chunk = 1*("0") [ chunk-ext ] CRLF
315- static
316- constexpr
317- std::size_t
318- last_chunk_len_ =
319- 1 + // "0"
320- crlf_len_ +
321- crlf_len_; // chunked-body termination requires an extra CRLF
322-
323- static
324- constexpr
325- std::size_t
326- chunked_overhead_ =
327- chunk_header_len_ +
328- crlf_len_ + // closing chunk data
329- last_chunk_len_;
330-
331- detail::workspace ws_;
332- detail::array_of_const_buffers buf_;
333- detail::filter* filter_ = nullptr ;
334- source* src_;
335285 context& ctx_;
336- buffers::circular_buffer tmp0_;
337- buffers::circular_buffer tmp1_;
338- detail::array_of_const_buffers prepped_;
339-
340- buffers::mutable_buffer chunk_header_;
341- buffers::mutable_buffer chunk_close_;
342- buffers::mutable_buffer last_chunk_;
286+ detail::workspace ws_;
343287
344- buffers::circular_buffer* in_ = nullptr ;
345- buffers::circular_buffer* out_ = nullptr ;
288+ const_buf_gen_base* buf_gen_;
289+ detail::filter* filter_;
290+ source* source_;
346291
347- buffers::const_buffer* hp_; // header
292+ buffers::circular_buffer cb0_;
293+ buffers::circular_buffer cb1_;
294+ detail::array_of_const_buffers prepped_;
295+ buffers::const_buffer tmp_;
348296
349297 style st_;
350- bool more_ ;
298+ bool more_input_ ;
351299 bool is_done_;
352300 bool is_header_done_;
353301 bool is_chunked_;
354- bool is_expect_continue_;
355- bool is_compressed_ = false ;
356- bool filter_done_ = false ;
302+ bool needs_exp100_continue_;
303+ bool filter_done_;
357304};
358305
359306// ------------------------------------------------
@@ -422,17 +369,6 @@ struct serializer::stream
422369 std::size_t
423370 capacity () const noexcept ;
424371
425- /* * Returns the number of octets serialized by this
426- stream.
427-
428- The associated serializer stores stream output in its
429- internal buffers. The stream returns the size of this
430- output.
431- */
432- BOOST_HTTP_PROTO_DECL
433- std::size_t
434- size () const noexcept ;
435-
436372 /* * Return true if the stream cannot currently hold
437373 additional output data.
438374
@@ -503,28 +439,116 @@ struct serializer::stream
503439
504440// ---------------------------------------------------------
505441
442+ class serializer ::const_buf_gen_base
443+ {
444+ public:
445+ // Next non-empty buffer
446+ virtual
447+ buffers::const_buffer
448+ next () = 0 ;
449+
450+ // Total size of remaining buffers
451+ virtual
452+ std::size_t
453+ remaining_size () const = 0 ;
454+
455+ // Count of non-empty remaining buffers
456+ virtual
457+ std::size_t
458+ remaining_count () const = 0 ;
459+
460+ // Returns true when there is no buffer or
461+ // the remaining buffers are empty
462+ virtual
463+ bool
464+ is_empty () const = 0 ;
465+ };
466+
467+ template <class ConstBufferSequence >
468+ class serializer ::const_buf_gen
469+ : public const_buf_gen_base
470+ {
471+ using it_t = decltype (buffers::begin(
472+ std::declval<ConstBufferSequence>()));
473+
474+ using const_buffer =
475+ buffers::const_buffer;
476+
477+ ConstBufferSequence cbs_;
478+ it_t current_;
479+ public:
480+ explicit
481+ const_buf_gen (ConstBufferSequence cbs)
482+ : cbs_(std::move(cbs))
483+ , current_(buffers::begin(cbs_))
484+ {
485+ }
486+
487+ buffers::const_buffer
488+ next () override
489+ {
490+ while (current_ != buffers::end (cbs_))
491+ {
492+ auto buf = static_cast <
493+ const_buffer>(*current_++);
494+ if (buf.size () != 0 )
495+ return buf;
496+ }
497+ return {};
498+ }
499+
500+ std::size_t
501+ remaining_size () const override
502+ {
503+ return std::accumulate (
504+ current_,
505+ buffers::end (cbs_),
506+ std::size_t {},
507+ [](std::size_t sum, const_buffer cb) {
508+ return sum + cb.size (); });
509+ }
510+
511+ std::size_t
512+ remaining_count () const override
513+ {
514+ return std::count_if (
515+ current_,
516+ buffers::end (cbs_),
517+ [](const_buffer cb) {
518+ return cb.size () != 0 ; });
519+ }
520+
521+ bool
522+ is_empty () const override
523+ {
524+ return std::all_of (
525+ current_,
526+ buffers::end (cbs_),
527+ [](const_buffer cb) {
528+ return cb.size () == 0 ; });
529+ }
530+ };
531+
532+ // ---------------------------------------------------------
533+
506534template <
507535 class ConstBufferSequence ,
508536 class >
509537void
510538serializer::
511539start (
512540 message_view_base const & m,
513- ConstBufferSequence&& body )
541+ ConstBufferSequence&& cbs )
514542{
515- start_init (m);
516- auto const & bs =
517- ws_.emplace <ConstBufferSequence>(
518- std::forward<ConstBufferSequence>(body));
519-
520- std::size_t n = std::distance (
521- buffers::begin (bs),
522- buffers::end (bs));
543+ static_assert (buffers::is_const_buffer_sequence<
544+ ConstBufferSequence>::value,
545+ " ConstBufferSequence type requirements not met" );
523546
524- buf_ = make_array (n);
525- auto p = buf_.data ();
526- for (buffers::const_buffer b : buffers::range (bs))
527- *p++ = b;
547+ start_init (m);
548+ buf_gen_ = &ws_.emplace <
549+ const_buf_gen<typename std::decay<
550+ ConstBufferSequence>::type>>(
551+ std::forward<ConstBufferSequence>(cbs));
528552
529553 start_buffers (m);
530554}
@@ -553,20 +577,6 @@ start(
553577 return src;
554578}
555579
556- // ------------------------------------------------
557-
558- inline
559- auto
560- serializer::
561- make_array (std::size_t n) ->
562- detail::array_of_const_buffers
563- {
564- return {
565- ws_.push_array (n,
566- buffers::const_buffer{}),
567- n };
568- }
569-
570580} // http_proto
571581} // boost
572582
0 commit comments