1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_BUFFERS_PREFIX_HPP
11 #define BOOST_BEAST_BUFFERS_PREFIX_HPP
12 
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/buffer_traits.hpp>
15 #include <boost/optional/optional.hpp> // for in_place_init_t
16 #include <algorithm>
17 #include <cstdint>
18 #include <type_traits>
19 
20 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
21 #include <boost/type_traits/is_convertible.hpp>
22 #endif
23 
24 namespace boost {
25 namespace beast {
26 
27 /** A buffer sequence adaptor that shortens the sequence size.
28 
29     The class adapts a buffer sequence to efficiently represent
30     a shorter subset of the original list of buffers starting
31     with the first byte of the original sequence.
32 
33     @tparam BufferSequence The buffer sequence to adapt.
34 */
35 template<class BufferSequence>
36 class buffers_prefix_view
37 {
38     using iter_type =
39         buffers_iterator_type<BufferSequence>;
40 
41     BufferSequence bs_;
42     std::size_t size_ = 0;
43     std::size_t remain_ = 0;
44     iter_type end_{};
45 
46     void
47     setup(std::size_t size);
48 
49     buffers_prefix_view(
50         buffers_prefix_view const& other,
51         std::size_t dist);
52 
53 public:
54     /** The type for each element in the list of buffers.
55 
56         If the type `BufferSequence` meets the requirements of
57         <em>MutableBufferSequence</em>, then `value_type` is
58         `net::mutable_buffer`. Otherwise, `value_type` is
59         `net::const_buffer`.
60 
61         @see buffers_type
62     */
63 #if BOOST_BEAST_DOXYGEN
64     using value_type = __see_below__;
65 #elif BOOST_WORKAROUND(BOOST_MSVC, < 1910)
66     using value_type = typename std::conditional<
67         boost::is_convertible<typename
68             std::iterator_traits<iter_type>::value_type,
69                 net::mutable_buffer>::value,
70                     net::mutable_buffer,
71                         net::const_buffer>::type;
72 #else
73     using value_type = buffers_type<BufferSequence>;
74 #endif
75 
76 #if BOOST_BEAST_DOXYGEN
77     /// A bidirectional iterator type that may be used to read elements.
78     using const_iterator = __implementation_defined__;
79 
80 #else
81     class const_iterator;
82 
83 #endif
84 
85     /// Copy Constructor
86     buffers_prefix_view(buffers_prefix_view const&);
87 
88     /// Copy Assignment
89     buffers_prefix_view& operator=(buffers_prefix_view const&);
90 
91     /** Construct a buffer sequence prefix.
92 
93         @param size The maximum number of bytes in the prefix.
94         If this is larger than the size of passed buffers,
95         the resulting sequence will represent the entire
96         input sequence.
97 
98         @param buffers The buffer sequence to adapt. A copy of
99         the sequence will be made, but ownership of the underlying
100         memory is not transferred. The copy is maintained for
101         the lifetime of the view.
102     */
103     buffers_prefix_view(
104         std::size_t size,
105         BufferSequence const& buffers);
106 
107     /** Construct a buffer sequence prefix in-place.
108 
109         @param size The maximum number of bytes in the prefix.
110         If this is larger than the size of passed buffers,
111         the resulting sequence will represent the entire
112         input sequence.
113 
114         @param args Arguments forwarded to the contained buffer's constructor.
115     */
116     template<class... Args>
117     buffers_prefix_view(
118         std::size_t size,
119         boost::in_place_init_t,
120         Args&&... args);
121 
122     /// Returns an iterator to the first buffer in the sequence
123     const_iterator
124     begin() const;
125 
126     /// Returns an iterator to one past the last buffer in the sequence
127     const_iterator
128     end() const;
129 
130 #if ! BOOST_BEAST_DOXYGEN
131     std::size_t
buffer_bytes_impl() const132     buffer_bytes_impl() const noexcept
133     {
134         return size_;
135     }
136 #endif
137 };
138 
139 //------------------------------------------------------------------------------
140 
141 /** Returns a prefix of a constant or mutable buffer sequence.
142 
143     The returned buffer sequence points to the same memory as the
144     passed buffer sequence, but with a size that is equal to or
145     smaller. No memory allocations are performed; the resulting
146     sequence is calculated as a lazy range.
147 
148     @param size The maximum size of the returned buffer sequence
149     in bytes. If this is greater than or equal to the size of
150     the passed buffer sequence, the result will have the same
151     size as the original buffer sequence.
152 
153     @param buffers An object whose type meets the requirements
154     of <em>BufferSequence</em>. The returned value will
155     maintain a copy of the passed buffers for its lifetime;
156     however, ownership of the underlying memory is not
157     transferred.
158 
159     @return A constant buffer sequence that represents the prefix
160     of the original buffer sequence. If the original buffer sequence
161     also meets the requirements of <em>MutableBufferSequence</em>,
162     then the returned value will also be a mutable buffer sequence.
163 */
164 template<class BufferSequence>
165 buffers_prefix_view<BufferSequence>
buffers_prefix(std::size_t size,BufferSequence const & buffers)166 buffers_prefix(
167     std::size_t size, BufferSequence const& buffers)
168 {
169     static_assert(
170         net::is_const_buffer_sequence<BufferSequence>::value,
171             "BufferSequence type requirements not met");
172     return buffers_prefix_view<BufferSequence>(size, buffers);
173 }
174 
175 /** Returns the first buffer in a buffer sequence
176 
177     This returns the first buffer in the buffer sequence.
178     If the buffer sequence is an empty range, the returned
179     buffer will have a zero buffer size.
180 
181     @param buffers The buffer sequence. If the sequence is
182     mutable, the returned buffer sequence will also be mutable.
183     Otherwise, the returned buffer sequence will be constant.
184 */
185 template<class BufferSequence>
186 buffers_type<BufferSequence>
buffers_front(BufferSequence const & buffers)187 buffers_front(BufferSequence const& buffers)
188 {
189     auto const first =
190         net::buffer_sequence_begin(buffers);
191     if(first == net::buffer_sequence_end(buffers))
192         return {};
193     return *first;
194 }
195 
196 } // beast
197 } // boost
198 
199 #include <boost/beast/core/impl/buffers_prefix.hpp>
200 
201 #endif
202