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 ;
41- } // detail
39+ } // namespace detail
4240#endif
4341
4442/* * A serializer for HTTP/1 messages
@@ -68,7 +66,8 @@ class filter;
6866class serializer
6967{
7068public:
71- using const_buffers_type = buffers::const_buffer_span;
69+ using const_buffers_type =
70+ buffers::const_buffer_span;
7271
7372 struct stream ;
7473
@@ -219,36 +218,14 @@ class serializer
219218 void
220219 consume (std::size_t n);
221220
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
234-
235- After @ref reset is called, compression is not
236- applied to the next message.
221+ private:
222+ class const_buf_gen_base ;
237223
238- Must be called before any calls to @ref start.
239- */
240- BOOST_HTTP_PROTO_DECL
241- void
242- use_gzip_encoding ();
224+ template <class >
225+ class const_buf_gen ;
243226
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;
227+ detail::array_of_const_buffers
228+ make_array (std::size_t n);
252229
253230 template <
254231 class Source ,
@@ -279,10 +256,25 @@ class serializer
279256 ws_, std::forward<Args>(args)...);
280257 }
281258
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*);
259+ BOOST_HTTP_PROTO_DECL
260+ void
261+ start_init (
262+ message_view_base const &);
263+
264+ BOOST_HTTP_PROTO_DECL
265+ void
266+ start_empty (
267+ message_view_base const &);
268+
269+ BOOST_HTTP_PROTO_DECL
270+ void
271+ start_buffers (
272+ message_view_base const &);
273+
274+ BOOST_HTTP_PROTO_DECL
275+ void
276+ start_source (
277+ message_view_base const &);
286278
287279 enum class style
288280 {
@@ -292,68 +284,25 @@ class serializer
292284 stream
293285 };
294286
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_;
335287 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_;
288+ detail::workspace ws_;
343289
344- buffers::circular_buffer* in_ = nullptr ;
345- buffers::circular_buffer* out_ = nullptr ;
290+ const_buf_gen_base* buf_gen_;
291+ detail::filter* filter_;
292+ source* source_;
346293
347- buffers::const_buffer* hp_; // header
294+ buffers::circular_buffer cb0_;
295+ buffers::circular_buffer cb1_;
296+ detail::array_of_const_buffers prepped_;
297+ buffers::const_buffer tmp_;
348298
349299 style st_;
350- bool more_ ;
300+ bool more_input_ ;
351301 bool is_done_;
352302 bool is_header_done_;
353303 bool is_chunked_;
354- bool is_expect_continue_;
355- bool is_compressed_ = false ;
356- bool filter_done_ = false ;
304+ bool needs_exp100_continue_;
305+ bool filter_done_;
357306};
358307
359308// ------------------------------------------------
@@ -422,17 +371,6 @@ struct serializer::stream
422371 std::size_t
423372 capacity () const noexcept ;
424373
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-
436374 /* * Return true if the stream cannot currently hold
437375 additional output data.
438376
@@ -503,29 +441,115 @@ struct serializer::stream
503441
504442// ---------------------------------------------------------
505443
444+ class serializer ::const_buf_gen_base
445+ {
446+ public:
447+ // Next non-empty buffer
448+ virtual
449+ buffers::const_buffer
450+ operator ()() = 0 ;
451+
452+ // Size of remaining buffers
453+ virtual
454+ std::size_t
455+ size () const = 0 ;
456+
457+ // Count of remaining non-empty buffers
458+ virtual
459+ std::size_t
460+ count () const = 0 ;
461+
462+ // Returns true when there is no buffer or
463+ // the remaining buffers are empty
464+ virtual
465+ bool
466+ is_empty () const = 0 ;
467+ };
468+
469+ template <class ConstBufferSequence >
470+ class serializer ::const_buf_gen
471+ : public const_buf_gen_base
472+ {
473+ using it_t = decltype (buffers::begin(
474+ std::declval<ConstBufferSequence>()));
475+
476+ ConstBufferSequence cbs_;
477+ it_t current_;
478+ public:
479+ using const_buffer =
480+ buffers::const_buffer;
481+
482+ explicit
483+ const_buf_gen (ConstBufferSequence cbs)
484+ : cbs_(std::move(cbs))
485+ , current_(buffers::begin(cbs_))
486+ {
487+ }
488+
489+ const_buffer
490+ operator ()() override
491+ {
492+ while (current_ != buffers::end (cbs_))
493+ {
494+ const_buffer buf = *current_++;
495+ if (buf.size () != 0 )
496+ return buf;
497+ }
498+ return {};
499+ }
500+
501+ std::size_t
502+ size () const override
503+ {
504+ return std::accumulate (
505+ current_,
506+ buffers::end (cbs_),
507+ std::size_t {},
508+ [](std::size_t sum, const_buffer cb) {
509+ return sum + cb.size (); });
510+ }
511+
512+ std::size_t
513+ count () const override
514+ {
515+ return std::count_if (
516+ current_,
517+ buffers::end (cbs_),
518+ [](const_buffer cb) {
519+ return cb.size () != 0 ; });
520+ }
521+
522+ bool
523+ is_empty () const override
524+ {
525+ return std::all_of (
526+ current_,
527+ buffers::end (cbs_),
528+ [](const_buffer cb) {
529+ return cb.size () == 0 ; });
530+ }
531+ };
532+
533+ // ---------------------------------------------------------
534+
506535template <
507536 class ConstBufferSequence ,
508537 class >
509538void
510539serializer::
511540start (
512541 message_view_base const & m,
513- ConstBufferSequence&& body )
542+ ConstBufferSequence&& cbs )
514543{
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));
523-
524- buf_ = make_array (n);
525- auto p = buf_.data ();
526- for (buffers::const_buffer b : buffers::range (bs))
527- *p++ = b;
544+ static_assert (buffers::is_const_buffer_sequence<
545+ ConstBufferSequence>::value,
546+ " ConstBufferSequence type requirements not met" );
528547
548+ start_init (m);
549+ buf_gen_ = std::addressof (
550+ ws_.emplace <const_buf_gen<typename
551+ std::decay<ConstBufferSequence>::type>>(
552+ std::forward<ConstBufferSequence>(cbs)));
529553 start_buffers (m);
530554}
531555
@@ -549,24 +573,11 @@ start(
549573 start_init (m);
550574 auto & src = construct_source<Source>(
551575 std::forward<Args>(args)...);
552- start_source (m, std::addressof (src));
576+ source_ = std::addressof (src);
577+ start_source (m);
553578 return src;
554579}
555580
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-
570581} // http_proto
571582} // boost
572583
0 commit comments