RESTinio
buffers.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
5 /*!
6  Restinio buffers.
7 */
8 
9 #pragma once
10 
11 #include <memory>
12 #include <array>
13 #include <string>
14 #include <cstring>
15 #include <type_traits>
16 
17 #include <restinio/asio_include.hpp>
18 #include <restinio/exception.hpp>
19 #include <restinio/sendfile.hpp>
20 
21 namespace restinio
22 {
23 
24 namespace impl
25 {
26 
27 //
28 // writable_base_t
29 //
30 
31 //! A base class for writable items.
32 /*!
33  Having a condition to put heterogeneous writable-items sequence in vector
34  and to transfer it from builders to connection context,
35  internal writable-items are the pieces incapsulating various
36  implementation that fit into a fixed memory space.
37  That's makes it possible to fit any of them in a binary
38  buffer that resides in writable_item_t.
39  While different descendants might vary in size
40  size of writable_item_t remains the same, so it can be used in a vector.
41 */
43 {
44  public:
45  writable_base_t() = default;
46  writable_base_t( const writable_base_t & ) = default;
47  writable_base_t( writable_base_t && ) = default;
48  writable_base_t & operator = ( const writable_base_t & ) = delete;
49  writable_base_t & operator = ( writable_base_t && ) = delete;
50 
51  virtual ~writable_base_t()
52  {}
53 
54  //! Move this buffer enitity to a given location.
55  //! \note storage must have a sufficient space and proper alignment.
56  virtual void relocate_to( void * storage ) = 0;
57 
58  //! Get the size of a writable piece of data.
59  virtual std::size_t size() const = 0;
60 };
61 
62 //! Internal interface for a trivial buffer-like entity.
64 {
65  public:
66  //! Get asio buf entity.
67  /*!
68  Prepares an item for being used with ASIO API.
69  */
70  virtual asio_ns::const_buffer buffer() const = 0;
71 };
72 
73 //! Empty buffer entity.
74 class empty_buf_t final : public buf_iface_t
75 {
76  public:
77  empty_buf_t() noexcept {}
78 
79  empty_buf_t( const empty_buf_t & ) = delete;
80  empty_buf_t & operator = ( const empty_buf_t & ) = delete;
81 
82  empty_buf_t( empty_buf_t && ) = default; // allow only explicit move.
83  empty_buf_t & operator = ( empty_buf_t && ) = delete;
84 
85  /*!
86  @name An implementation of writable_base_t interface.
87 
88  \see writable_base_t
89  */
90  ///@{
91  virtual asio_ns::const_buffer buffer() const override
92  {
93  return asio_ns::const_buffer{ nullptr, 0 };
94  }
95 
96  virtual void relocate_to( void * storage ) override
97  {
98  new( storage ) empty_buf_t{};
99  }
100  ///@}
101 
102  /*!
103  @name An implementation of buf_iface_t interface.
104 
105  \see buf_iface_t
106  */
107  ///@{
108  virtual std::size_t size() const override { return 0; }
109  ///@}
110 };
111 
112 //! Buffer entity for const buffer.
113 class const_buf_t final : public buf_iface_t
114 {
115  public:
116  const_buf_t() = delete;
117 
118  constexpr const_buf_t( const void * data, std::size_t size ) noexcept
119  : m_data{ data }
120  , m_size{ size }
121  {}
122 
123  const_buf_t( const const_buf_t & ) = delete;
124  const_buf_t & operator = ( const const_buf_t & ) = delete;
125 
126  const_buf_t( const_buf_t && ) = default; // allow only explicit move.
127  const_buf_t & operator = ( const_buf_t && ) = delete;
128 
129  /*!
130  @name An implementation of writable_base_t interface.
131 
132  \see writable_base_t
133  */
134  ///@{
135  virtual asio_ns::const_buffer buffer() const override
136  {
137  return asio_ns::const_buffer{ m_data, m_size };
138  }
139 
140  virtual void relocate_to( void * storage ) override
141  {
142  new( storage ) const_buf_t{ std::move( *this ) };
143  }
144  ///@}
145 
146  /*!
147  @name An implementation of buf_iface_t interface.
148 
149  \see buf_iface_t
150  */
151  ///@{
152  virtual std::size_t size() const override { return m_size; }
153  ///@}
154 
155  private:
156  //! A pointer to data.
157  const void * const m_data;
158  //! The size of data.
159  const std::size_t m_size;
160 };
161 
162 //! User defined datasizable object.
163 /*!
164  \note there is a limitation on how large a `Datasizeable` type can be.
165  The limitation is checked with a following predicate:
166  \code
167  sizeof(datasizeable_buf_t<D>) <= needed_storage_max_size;
168  \endcode
169 */
170 template < typename Datasizeable >
172 {
173  // Check datasizeable contract:
174  static_assert(
176  decltype( std::declval< const Datasizeable >().data() ),
177  const void *
178  >::value,
179  "Datasizeable requires 'T* data() const' member function, "
180  "where 'T*' is convertible to 'void*' " );
181 
182  static_assert(
184  decltype( std::declval< const Datasizeable >().size() ),
185  std::size_t
186  >::value,
187  "Datasizeable requires 'N size() const' member function, "
188  "where 'N' is convertible to 'std::size_t'" );
189 
190  static_assert(
192  "Datasizeable must be move constructible" );
193 
194  public:
195  datasizeable_buf_t( Datasizeable buf )
196  : m_custom_buffer{ std::move( buf ) }
197  {}
198 
199  datasizeable_buf_t( datasizeable_buf_t && ) = default; // allow only explicit move.
200 
201  /*!
202  @name An implementation of writable_base_t interface.
203 
204  \see writable_base_t
205  */
206  ///@{
207  virtual asio_ns::const_buffer buffer() const override
208  {
209  return asio_ns::const_buffer{
211  m_custom_buffer.size() };
212  }
213 
214  virtual void relocate_to( void * storage ) override
215  {
216  new( storage ) datasizeable_buf_t{ std::move( *this ) };
217  }
218  ///@}
219 
220  /*!
221  @name An implementation of buf_iface_t interface.
222 
223  \see buf_iface_t
224  */
225  ///@{
226  virtual std::size_t size() const override { return m_custom_buffer.size(); }
227  ///@}
228 
229  private:
230  //! A datasizeable item that represents buffer.
231  Datasizeable m_custom_buffer;
232 };
233 
234 //! An alias for a std::string instantiation of datasizeable_buf_t<D> template.
235 /*!
236  Used to figure out buffer_storage_align and needed_storage_max_size
237  constants.
238 */
240 
241 //
242 // shared_datasizeable_buf_t
243 //
244 
245 //! Buffer based on shared_ptr of data-sizeable entity.
246 template < typename Datasizeable >
248 {
249  public:
251 
252  shared_datasizeable_buf_t() = delete;
253 
254  shared_datasizeable_buf_t( shared_ptr_t buf_ptr ) noexcept
255  : m_buf_ptr{ std::move( buf_ptr ) }
256  {}
257 
260 
261  shared_datasizeable_buf_t( shared_datasizeable_buf_t && ) = default; // allow only explicit move.
263 
264  /*!
265  @name An implementation of writable_base_t interface.
266 
267  \see writable_base_t
268  */
269  ///@{
270  virtual asio_ns::const_buffer buffer() const override
271  {
272  return asio_ns::const_buffer{ m_buf_ptr->data(), m_buf_ptr->size() };
273  }
274 
275  virtual void relocate_to( void * storage ) override
276  {
277  new( storage ) shared_datasizeable_buf_t{ std::move( *this ) };
278  }
279  ///@}
280 
281  /*!
282  @name An implementation of buf_iface_t interface.
283 
284  \see buf_iface_t
285  */
286  ///@{
287  virtual std::size_t size() const override { return m_buf_ptr->size(); }
288  ///@}
289 
290  private:
291  //! A shared pointer to a datasizeable entity.
293 };
294 
295 //
296 // sendfile_write_operation_t
297 //
298 
299 //! Send file operation wrapper.
301 {
302  public:
303  sendfile_write_operation_t() = delete;
304 
305  sendfile_write_operation_t( sendfile_t && sf_opts )
307  {}
308 
311 
314 
315  /*!
316  @name An implementation of writable_base_t interface.
317 
318  \see writable_base_t
319  */
320  ///@{
321  virtual void relocate_to( void * storage ) override
322  {
323  new( storage ) sendfile_write_operation_t{ std::move( *this ) };
324  }
325 
326  virtual std::size_t size() const override
327  {
328  return m_sendfile_options ? m_sendfile_options->size() : 0;
329  }
330  ///@}
331 
332  //! Get sendfile operation detaiols.
333  /*!
334  @note
335  Since v.0.4.9 it is non-const method. It is because we have
336  to work with mutable sendfile_t on some platform (like Windows).
337  */
338  sendfile_t &
339  sendfile_options() noexcept
340  {
341  return *m_sendfile_options;
342  }
343 
344  private:
345  //! A pointer to sendfile operation details.
347 };
348 
349 // Constant for suitable alignment of any entity in writable_base_t hierarchy.
351  std::max< std::size_t >( {
352  alignof( empty_buf_t ),
353  alignof( const_buf_t ),
354  alignof( string_buf_t ),
355  alignof( shared_datasizeable_buf_t< std::string > ),
356  alignof( sendfile_write_operation_t ) } );
357 
358 //! An of memory that is to be enough to hold any possible buffer entity.
360  std::max< std::size_t >( {
361  sizeof( empty_buf_t ),
362  sizeof( const_buf_t ),
363  sizeof( string_buf_t ),
364  sizeof( shared_datasizeable_buf_t< std::string > ),
365  sizeof( sendfile_write_operation_t ) } );
366 
367 } /* namespace impl */
368 
369 //
370 // const_buffer_t/
371 
372 //! Helper class for setting a constant buffer storage explicitly.
373 /*
374  A proxy DTO type.
375  Its instances are emitted with const_buffer functions and
376  are possible to converted to writable_item_t as it has a constructor for it.
377 */
379 {
380  constexpr const_buffer_t(
381  const void * str,
382  std::size_t size ) noexcept
383  : m_str{ str }
384  , m_size{ size }
385  {}
386 
387  const void * const m_str;
388  const std::size_t m_size;
389 };
390 
391 //! @name Create const buffers.
392 ///@{
393 inline constexpr const_buffer_t
394 const_buffer( const void * str, std::size_t size ) noexcept
395 {
396  return const_buffer_t{ str, size };
397 }
398 
399 inline const_buffer_t
400 const_buffer( const char * str ) noexcept
401 {
402  return const_buffer( str, std::strlen( str ) );
403 }
404 ///@}
405 
406 //
407 // writable_item_type_t
408 //
409 
410 //! Buffers write operation type.
412 {
413  //! Item is a buffer and must be written trivially
415 
416  //! Item is a sendfile operation and implicates file write operation.
418 };
419 
420 //
421 // writable_item_t
422 //
423 
424 //! Class for storing the buffers used for streaming body (request/response).
425 /*!
426  Supporting different types of entities that eventually result in
427  output data sent to peer is a bit tricky.
428  In the first step RESTionio distinguish two types of output data sources:
429  - trivial buffers (those ones that can be presented as a pair
430  of a pointer to data and the size of the data).
431  - sendfile (send a piece of data from file utilizing native
432  sendfile support Linux/FreeBSD/macOS and TransmitFile on windows).
433 
434  Also trivial buffers are implemented diferently for different cases,
435  includeing a template classes `impl::datasizeable_buf_t<Datasizeable>` and
436  `impl::shared_datasizeable_buf_t<Datasizeable>`.
437 
438  When using RESTinio response builder, response body can be constructed
439  using different types of buffers, and once the result
440  is flushed to the connection it must be sent to the socket.
441  A couple of issues arises here.
442  And one of them is how to store all these heterogeneous buffers
443  with fewer allocations and less boilerplate necessary
444  to handle each corner case.
445  Storing and moving a bunch of buffers as a vector would be
446  nice, but vector demands a single type to be used.
447  And writable_item_t represents a custom variant-like abstraction
448  for storing an arbitrary buffer object (`std::variant` itself is not the option
449  as it is restricted to types defined beforehand and cannot benifit
450  from the knowledge that all stored items are types derrived from
451  impl::writable_base_t).
452 
453  For storing the data of buffers #m_storage is used.
454  It is an aligned buffer sufficient to store
455  any impl::writable_base_t descendant (there is a limitation
456  concerned with impl::datasizeable_buf_t).
457  Also writable_item_t exposes interface to treat it
458  like a trivial buffer or a sendfile operation.
459  The type of buffer currently stored in writable_item_t
460  instance a write_type() function used.
461 
462  Having such writable_item_t class, RESTinio can store a sequence
463  of arbitrary buffers in `std::vector`.
464 */
466 {
467  public:
468  writable_item_t( const writable_item_t & ) = delete;
469  writable_item_t & operator = ( const writable_item_t & ) = delete;
470 
473  {
474  new( &m_storage ) impl::empty_buf_t{};
475  }
476 
479  {
480  new( &m_storage ) impl::const_buf_t{ const_buf.m_str, const_buf.m_size };
481  }
482 
483  template <
484  typename Datasizeable,
485  typename S = typename
486  std::enable_if_t<
487  !std::is_same<
489  Datasizeable >::value > >
492  {
493  static_assert(
495  "size of type is too big" );
496 
498  }
499 
500  writable_item_t( const char * str )
501  // We can't be sure whether it is valid to consider
502  // data pointed by str a const buffer, so we make a string copy here.
503  : writable_item_t{ std::string{ str } }
504  {}
505 
506  template < typename Datasizeable >
509  {
510  static_assert(
512  "size of shared_ptr on a type is too big" );
513 
514  if( !sp )
515  throw exception_t{ "empty shared_ptr cannot be used as buffer" };
516 
518  }
519 
522  {
524  }
525 
528  {
530  }
531 
534  {
535  if( this != &b )
536  {
540  }
541 
542  return *this;
543  }
544 
546  {
548  }
549 
550  //! Get a type of a stored buffer object.
552  write_type() const noexcept
553  {
554  return m_write_type;
555  }
556 
557  //! Get the size of the underlying buffer object.
558  std::size_t size() const { return get_writable_base()->size(); }
559 
560  //! Create a buf reference object used by ASIO.
561  /*!
562  \note Stored buffer must be of writable_item_type_t::trivial_write_operation.
563  */
564  asio_ns::const_buffer buf() const { return get_buf()->buffer(); }
565 
566  //! Get a reference to a sendfile operation.
567  /*!
568  @note Stored buffer must be of writable_item_type_t::file_write_operation.
569  @note
570  Since v.0.4.9 it is non-const method. It is because we have
571  to work with mutable sendfile_t on some platform (like Windows).
572  */
573  sendfile_t &
575  {
576  return get_sfwo()->sendfile_options();
577  }
578 
579  private:
580  void
582  {
585  }
586 
588 
589  /** @name Access an item as an object of specific types.
590  * @brief Casts a stored object to one of the types.
591  */
592  ///@{
593 
594  //! Access as writable_base_t item.
595  const impl::writable_base_t * get_writable_base() const noexcept
596  {
597  return reinterpret_cast< const impl::writable_base_t * >( &m_storage );
598  }
599 
600  //! Access as writable_base_t item.
602  {
603  return reinterpret_cast< impl::writable_base_t * >( &m_storage );
604  }
605 
606  //! Access as trivial buf item.
607  const impl::buf_iface_t * get_buf() const noexcept
608  {
609  return reinterpret_cast< const impl::buf_iface_t * >( &m_storage );
610  }
611 
612  //! Access as trivial buf item.
613  impl::buf_iface_t * get_buf() noexcept
614  {
615  return reinterpret_cast< impl::buf_iface_t * >( &m_storage );
616  }
617 
618  //! Access as sendfile_write_operation_t item.
620  {
621  return reinterpret_cast< impl::sendfile_write_operation_t * >( &m_storage );
622  }
623  ///@}
624 
625  using storage_t =
629 
630  //! A storage for a buffer object of various types.
632 };
633 
634 //
635 // writable_items_container_t
636 //
637 
639 
640 //
641 // write_status_cb_t
642 //
643 
644 //! An alias for a callback to be invoked after the write operation of
645 //! a particular group of "buffers".
646 /*!
647  @since v.0.4.8
648 */
649 using write_status_cb_t =
650  std::function< void( const asio_ns::error_code & ec ) >;
651 
652 //
653 // write_group_t
654 //
655 
656 //! Group of writable items transported to the context of underlying connection
657 //! as one solid piece.
658 /*!
659  @since v.0.4.8
660 */
662 {
663  public:
664  //! Swap two groups.
665  friend void
666  swap( write_group_t & left, write_group_t & right ) noexcept
667  {
668  using std::swap;
669  swap( left.m_items, right.m_items );
670  swap( left.m_status_line_size, right.m_status_line_size );
671  swap( left.m_after_write_notificator, right.m_after_write_notificator );
672  }
673 
674  //! Construct write group with a given bunch of writable items.
675  explicit write_group_t(
676  //! A buffer objects included in this group.
677  writable_items_container_t items )
678  : m_items{ std::move( items ) }
679  , m_status_line_size{ 0 }
680  {}
681 
682  /** @name Copy semantics.
683  * @brief Not allowed.
684  */
685  ///@{
686  write_group_t( const write_group_t & ) = delete;
687  write_group_t & operator = ( const write_group_t & ) = delete;
688  ///@}
689 
690  /** @name Move semantics.
691  * @brief Moves object leaving a moved one in clean state.
692  */
693  ///@{
695  : m_items{ std::move( wg.m_items ) }
698  {
699  wg.m_after_write_notificator = write_status_cb_t{}; // Make sure src is cleaned.
700  wg.m_status_line_size = 0;
701  }
702 
704  {
705  write_group_t tmp{ std::move( wg ) };
706  swap( *this, tmp );
707 
708  return *this;
709  }
710  ///@}
711 
712  //! Destruct object.
713  /*!
714  If notificator was not called it would be invoked with error.
715  */
717  {
718  if( m_after_write_notificator )
719  {
720  try
721  {
722  invoke_after_write_notificator_if_exists(
723  make_asio_compaible_error(
724  asio_convertible_error_t::write_group_destroyed_passively ) );
725  }
726  catch( ... )
727  {}
728  }
729  }
730 
731  /** @name Auxiliary data.
732  * @brief Accessors for working with auxiliary data.
733  */
734  ///@{
735  void
736  status_line_size( std::size_t n )
737  {
738  if( std::size_t{0} != n )
739  {
740  if( m_items.empty() )
741  {
742  throw exception_t{
743  "cannot set status line size for empty write group" };
744  }
745 
746  if( writable_item_type_t::trivial_write_operation !=
747  m_items.front().write_type() )
748  {
749  throw exception_t{
750  "cannot set status line size for write group: "
751  "first writable item must be 'trivial_write_operation'" };
752  }
753 
754  if( m_items.front().size() < n )
755  {
756  throw exception_t{
757  "cannot set status line size for write group: "
758  "first writable item size is less than provided value" };
759  }
760 
761  m_status_line_size = n;
762  }
763  }
764 
765  //! Get status line size.
766  std::size_t
767  status_line_size() const noexcept
768  {
769  return m_status_line_size;
770  }
771 
772  //! Set after write notificator.
773  void
774  after_write_notificator( write_status_cb_t notificator ) noexcept
775  {
776  m_after_write_notificator = std::move( notificator );
777  }
778 
779  //! Is there an after write notificator set?
780  bool
782  {
783  return static_cast< bool >( m_after_write_notificator );
784  }
785 
786  //! Get after write notificator.
787  void
788  invoke_after_write_notificator_if_exists( const asio_ns::error_code & ec )
789  {
790  if( m_after_write_notificator )
791  {
792  auto tmp = std::move( m_after_write_notificator );
793 
794  // Make sure we clean notificator,
795  // because on some platforms/compilers `std::move()` does not clean it.
796  m_after_write_notificator = write_status_cb_t{};
797 
798  tmp( ec );
799  }
800  }
801  ///@}
802 
803  //! Get the count of stored items.
804  auto
805  items_count() const noexcept
806  {
807  return m_items.size();
808  }
809 
810  //! Get access to the stored items.
811  const auto &
812  items() const noexcept
813  {
814  return m_items;
815  }
816 
817  //! Get access to the stored items.
818  /*!
819  Should be used for cases where we should have a non-const
820  access to writeable items.
821 
822  @since v.0.4.9
823  */
824  auto &
825  items() noexcept
826  {
827  return m_items;
828  }
829 
830  //! Reset group.
831  void
833  {
834  m_items.clear();
835  m_status_line_size = 0;
836  m_after_write_notificator = write_status_cb_t{};
837  }
838 
839  //! Merges with another group.
840  /*!
841  Two groups can be merged if the first one has no after-write callback
842  and the second one has no status line size.
843  */
844  void
846  {
847  auto & second_items = second.m_items;
848  m_items.reserve( m_items.size() + second_items.size() );
849 
850  std::move(
851  begin( second_items ),
852  end( second_items ),
853  std::back_inserter( m_items ) );
854 
855  m_after_write_notificator = std::move( second.m_after_write_notificator );
856  }
857 
858  private:
859  //! A buffer objects included in this group.
861 
862  //! A size of status line located in first "buffer".
863  /*!
864  If the value is not 0 then it means it references
865  a piece of data stored in the first buffer of m_items container.
866  */
868 
869  //! A callback to invoke once the the write opertaion of a given group completes.
871 };
872 
873 } /* namespace restinio */
const_buf_t(const const_buf_t &)=delete
const impl::buf_iface_t * get_buf() const noexcept
Access as trivial buf item.
Definition: buffers.hpp:607
Item is a sendfile operation and implicates file write operation.
write_status_cb_t m_after_write_notificator
A callback to invoke once the the write opertaion of a given group completes.
Definition: buffers.hpp:870
A base class for writable items.
Definition: buffers.hpp:42
Send file operation wrapper.
Definition: buffers.hpp:300
shared_datasizeable_buf_t & operator=(const shared_datasizeable_buf_t &)=delete
virtual void relocate_to(void *storage) override
Move this buffer enitity to a given location.
Definition: buffers.hpp:140
virtual std::size_t size() const override
Get the size of a writable piece of data.
Definition: buffers.hpp:108
sendfile_write_operation_t & operator=(const sendfile_write_operation_t &)=delete
constexpr const_buffer_t const_buffer(const void *str, std::size_t size) noexcept
Definition: buffers.hpp:394
sendfile_write_operation_t(sendfile_t &&sf_opts)
Definition: buffers.hpp:305
storage_t m_storage
A storage for a buffer object of various types.
Definition: buffers.hpp:631
writable_items_container_t m_items
A buffer objects included in this group.
Definition: buffers.hpp:860
virtual void relocate_to(void *storage) override
Move this buffer enitity to a given location.
Definition: buffers.hpp:214
writable_item_type_t
Buffers write operation type.
Definition: buffers.hpp:411
writable_base_t(writable_base_t &&)=default
bool has_after_write_notificator() const noexcept
Is there an after write notificator set?
Definition: buffers.hpp:781
virtual asio_ns::const_buffer buffer() const override
Get asio buf entity.
Definition: buffers.hpp:91
empty_buf_t(const empty_buf_t &)=delete
const_buffer_t const_buffer(const char *str) noexcept
Definition: buffers.hpp:400
Item is a buffer and must be written trivially.
const_buf_t & operator=(const const_buf_t &)=delete
empty_buf_t(empty_buf_t &&)=default
const_buf_t(const_buf_t &&)=default
virtual std::size_t size() const override
Get the size of a writable piece of data.
Definition: buffers.hpp:226
constexpr const_buffer_t(const void *str, std::size_t size) noexcept
Definition: buffers.hpp:380
impl::buf_iface_t * get_buf() noexcept
Access as trivial buf item.
Definition: buffers.hpp:613
datasizeable_buf_t(datasizeable_buf_t &&)=default
virtual void relocate_to(void *storage)=0
Move this buffer enitity to a given location.
void merge(write_group_t second)
Merges with another group.
Definition: buffers.hpp:845
shared_datasizeable_buf_t(shared_datasizeable_buf_t &&)=default
void after_write_notificator(write_status_cb_t notificator) noexcept
Set after write notificator.
Definition: buffers.hpp:774
write_group_t(const write_group_t &)=delete
Helper class for setting a constant buffer storage explicitly.
Definition: buffers.hpp:378
empty_buf_t & operator=(const empty_buf_t &)=delete
virtual std::size_t size() const override
Get the size of a writable piece of data.
Definition: buffers.hpp:152
virtual void relocate_to(void *storage) override
Move this buffer enitity to a given location.
Definition: buffers.hpp:275
std::size_t status_line_size() const noexcept
Get status line size.
Definition: buffers.hpp:767
constexpr std::size_t needed_storage_max_size
An of memory that is to be enough to hold any possible buffer entity.
Definition: buffers.hpp:359
auto items_count() const noexcept
Get the count of stored items.
Definition: buffers.hpp:805
~write_group_t()
Destruct object.
Definition: buffers.hpp:716
const impl::writable_base_t * get_writable_base() const noexcept
Access as writable_base_t item.
Definition: buffers.hpp:595
auto & items() noexcept
Get access to the stored items.
Definition: buffers.hpp:825
Internal interface for a trivial buffer-like entity.
Definition: buffers.hpp:63
const void *const m_str
Definition: buffers.hpp:387
writable_base_t(const writable_base_t &)=default
virtual void relocate_to(void *storage) override
Move this buffer enitity to a given location.
Definition: buffers.hpp:321
virtual std::size_t size() const override
Get the size of a writable piece of data.
Definition: buffers.hpp:326
writable_item_t & operator=(const writable_item_t &)=delete
virtual void relocate_to(void *storage) override
Move this buffer enitity to a given location.
Definition: buffers.hpp:96
std::unique_ptr< sendfile_t > m_sendfile_options
A pointer to sendfile operation details.
Definition: buffers.hpp:346
writable_item_t(const_buffer_t const_buf)
Definition: buffers.hpp:477
impl::sendfile_write_operation_t * get_sfwo() noexcept
Access as sendfile_write_operation_t item.
Definition: buffers.hpp:619
const auto & items() const noexcept
Get access to the stored items.
Definition: buffers.hpp:812
writable_base_t & operator=(const writable_base_t &)=delete
empty_buf_t & operator=(empty_buf_t &&)=delete
void invoke_after_write_notificator_if_exists(const asio_ns::error_code &ec)
Get after write notificator.
Definition: buffers.hpp:788
Group of writable items transported to the context of underlying connection as one solid piece...
Definition: buffers.hpp:661
impl::writable_base_t * get_writable_base() noexcept
Access as writable_base_t item.
Definition: buffers.hpp:601
shared_datasizeable_buf_t & operator=(shared_datasizeable_buf_t &&)=delete
void reset()
Reset group.
Definition: buffers.hpp:832
sendfile_t & sendfile_options() noexcept
Get sendfile operation detaiols.
Definition: buffers.hpp:339
void status_line_size(std::size_t n)
Definition: buffers.hpp:736
write_group_t(write_group_t &&wg)
Definition: buffers.hpp:694
virtual std::size_t size() const override
Get the size of a writable piece of data.
Definition: buffers.hpp:287
friend void swap(write_group_t &left, write_group_t &right) noexcept
Swap two groups.
Definition: buffers.hpp:666
const void *const m_data
A pointer to data.
Definition: buffers.hpp:157
const_buf_t & operator=(const_buf_t &&)=delete
virtual asio_ns::const_buffer buffer() const override
Get asio buf entity.
Definition: buffers.hpp:135
sendfile_write_operation_t(const sendfile_write_operation_t &)=delete
const std::size_t m_size
The size of data.
Definition: buffers.hpp:159
sendfile_write_operation_t(sendfile_write_operation_t &&)=default
writable_base_t & operator=(writable_base_t &&)=delete
constexpr std::size_t buffer_storage_align
Definition: buffers.hpp:350
datasizeable_buf_t(Datasizeable buf)
Definition: buffers.hpp:195
virtual asio_ns::const_buffer buffer() const override
Get asio buf entity.
Definition: buffers.hpp:207
const std::size_t m_size
Definition: buffers.hpp:388
Datasizeable m_custom_buffer
A datasizeable item that represents buffer.
Definition: buffers.hpp:231
write_group_t & operator=(const write_group_t &)=delete
sendfile_write_operation_t & operator=(sendfile_write_operation_t &&)=delete
shared_ptr_t m_buf_ptr
A shared pointer to a datasizeable entity.
Definition: buffers.hpp:292
writable_item_t(const writable_item_t &)=delete
virtual std::size_t size() const =0
Get the size of a writable piece of data.
virtual asio_ns::const_buffer buffer() const =0
Get asio buf entity.
shared_datasizeable_buf_t(shared_ptr_t buf_ptr) noexcept
Definition: buffers.hpp:254
shared_datasizeable_buf_t(const shared_datasizeable_buf_t &)=delete
User defined datasizable object.
Definition: buffers.hpp:171
write_group_t & operator=(write_group_t &&wg)
Definition: buffers.hpp:703
constexpr const_buf_t(const void *data, std::size_t size) noexcept
Definition: buffers.hpp:118
virtual asio_ns::const_buffer buffer() const override
Get asio buf entity.
Definition: buffers.hpp:270
write_group_t(writable_items_container_t items)
Construct write group with a given bunch of writable items.
Definition: buffers.hpp:675
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, optional_t< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in optional_t<Value_Type> if parameter exists ...
Definition: value_or.hpp:64
Buffer based on shared_ptr of data-sizeable entity.
Definition: buffers.hpp:247
std::size_t m_status_line_size
A size of status line located in first "buffer".
Definition: buffers.hpp:867