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