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_ADAPTOR_HPP
11 #define BOOST_BEAST_BUFFERS_ADAPTOR_HPP
12 
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/buffer_traits.hpp>
15 #include <boost/optional.hpp>
16 #include <type_traits>
17 
18 namespace boost {
19 namespace beast {
20 
21 /** Adapts a <em>MutableBufferSequence</em> into a <em>DynamicBuffer</em>.
22 
23     This class wraps a <em>MutableBufferSequence</em> to meet the requirements
24     of <em>DynamicBuffer</em>. Upon construction the input and output sequences
25     are empty. A copy of the mutable buffer sequence object is stored; however,
26     ownership of the underlying memory is not transferred. The caller is
27     responsible for making sure that referenced memory remains valid
28     for the duration of any operations.
29 
30     The size of the mutable buffer sequence determines the maximum
31     number of bytes which may be prepared and committed.
32 
33     @tparam MutableBufferSequence The type of mutable buffer sequence to adapt.
34 */
35 template<class MutableBufferSequence>
36 class buffers_adaptor
37 {
38     static_assert(net::is_mutable_buffer_sequence<
39             MutableBufferSequence>::value,
40         "MutableBufferSequence type requirements not met");
41 
42     using iter_type =
43         buffers_iterator_type<MutableBufferSequence>;
44 
45     template<bool>
46     class subrange;
47 
48     MutableBufferSequence bs_;
49     iter_type begin_;
50     iter_type out_;
51     iter_type end_;
52     std::size_t max_size_;
53     std::size_t in_pos_ = 0;    // offset in *begin_
54     std::size_t in_size_ = 0;   // size of input sequence
55     std::size_t out_pos_ = 0;   // offset in *out_
56     std::size_t out_end_ = 0;   // output end offset
57 
58     iter_type end_impl() const;
59 
60     buffers_adaptor(
61         buffers_adaptor const& other,
62         std::size_t nbegin,
63         std::size_t nout,
64         std::size_t nend);
65 
66 public:
67     /// The type of the underlying mutable buffer sequence
68     using value_type = MutableBufferSequence;
69 
70     /** Construct a buffers adaptor.
71 
72         @param buffers The mutable buffer sequence to wrap. A copy of
73         the object will be made, but ownership of the memory is not
74         transferred.
75     */
76     explicit
77     buffers_adaptor(MutableBufferSequence const& buffers);
78 
79     /** Constructor
80 
81         This constructs the buffer adaptor in-place from
82         a list of arguments.
83 
84         @param args Arguments forwarded to the buffers constructor.
85     */
86     template<class... Args>
87     explicit
88     buffers_adaptor(boost::in_place_init_t, Args&&... args);
89 
90     /// Copy Constructor
91     buffers_adaptor(buffers_adaptor const& other);
92 
93     /// Copy Assignment
94     buffers_adaptor& operator=(buffers_adaptor const&);
95 
96     /// Returns the original mutable buffer sequence
97     value_type const&
value() const98     value() const
99     {
100         return bs_;
101     }
102 
103     //--------------------------------------------------------------------------
104 
105 #if BOOST_BEAST_DOXYGEN
106     /// The ConstBufferSequence used to represent the readable bytes.
107     using const_buffers_type = __implementation_defined__;
108 
109     /// The MutableBufferSequence used to represent the writable bytes.
110     using mutable_buffers_type = __implementation_defined__;
111 
112 #else
113     using const_buffers_type = subrange<false>;
114 
115     using mutable_buffers_type = subrange<true>;
116 #endif
117 
118     /// Returns the number of readable bytes.
119     std::size_t
size() const120     size() const noexcept
121     {
122         return in_size_;
123     }
124 
125     /// Return the maximum number of bytes, both readable and writable, that can ever be held.
126     std::size_t
max_size() const127     max_size() const noexcept
128     {
129         return max_size_;
130     }
131 
132     /// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation.
133     std::size_t
capacity() const134     capacity() const noexcept
135     {
136         return max_size_;
137     }
138 
139     /// Returns a constant buffer sequence representing the readable bytes
140     const_buffers_type
141     data() const noexcept;
142 
143     /// Returns a constant buffer sequence representing the readable bytes
144     const_buffers_type
cdata() const145     cdata() const noexcept
146     {
147         return data();
148     }
149 
150     /// Returns a mutable buffer sequence representing the readable bytes.
151     mutable_buffers_type
152     data() noexcept;
153 
154     /** Returns a mutable buffer sequence representing writable bytes.
155 
156         Returns a mutable buffer sequence representing the writable
157         bytes containing exactly `n` bytes of storage. This function
158         does not allocate memory. Instead, the storage comes from
159         the underlying mutable buffer sequence.
160 
161         All buffer sequences previously obtained using @ref prepare are
162         invalidated. Buffer sequences previously obtained using @ref data
163         remain valid.
164 
165         @param n The desired number of bytes in the returned buffer
166         sequence.
167 
168         @throws std::length_error if `size() + n` exceeds `max_size()`.
169 
170         @esafe
171 
172         Strong guarantee.
173     */
174     mutable_buffers_type
175     prepare(std::size_t n);
176 
177     /** Append writable bytes to the readable bytes.
178 
179         Appends n bytes from the start of the writable bytes to the
180         end of the readable bytes. The remainder of the writable bytes
181         are discarded. If n is greater than the number of writable
182         bytes, all writable bytes are appended to the readable bytes.
183 
184         All buffer sequences previously obtained using @ref prepare are
185         invalidated. Buffer sequences previously obtained using @ref data
186         remain valid.
187 
188         @param n The number of bytes to append. If this number
189         is greater than the number of writable bytes, all
190         writable bytes are appended.
191 
192         @esafe
193 
194         No-throw guarantee.
195     */
196     void
197     commit(std::size_t n) noexcept;
198 
199     /** Remove bytes from beginning of the readable bytes.
200 
201         Removes n bytes from the beginning of the readable bytes.
202 
203         All buffers sequences previously obtained using
204         @ref data or @ref prepare are invalidated.
205 
206         @param n The number of bytes to remove. If this number
207         is greater than the number of readable bytes, all
208         readable bytes are removed.
209 
210         @esafe
211 
212         No-throw guarantee.
213     */
214     void
215     consume(std::size_t n) noexcept;
216 
217 private:
218 
219     subrange<true>
220     make_subrange(std::size_t pos, std::size_t n);
221 
222     subrange<false>
223     make_subrange(std::size_t pos, std::size_t n) const;
224 
225     friend struct buffers_adaptor_test_hook;
226 
227 };
228 
229 } // beast
230 } // boost
231 
232 #include <boost/beast/core/impl/buffers_adaptor.hpp>
233 
234 #endif
235