Line data Source code
1 : //
2 : // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.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/cppalliance/http_proto
8 : //
9 :
10 : #ifndef BOOST_HTTP_PROTO_BUFFERED_BASE_HPP
11 : #define BOOST_HTTP_PROTO_BUFFERED_BASE_HPP
12 :
13 : #include <boost/http_proto/detail/config.hpp>
14 : #include <cstddef>
15 :
16 : namespace boost {
17 : namespace http_proto {
18 :
19 : /** Base class for buffered algorithms
20 :
21 : Algorithms implementing @ref filter,
22 : @ref source, or @ref sink inherit from
23 : this common interface.
24 : */
25 : struct BOOST_HTTP_PROTO_DECL
26 : buffered_base
27 : {
28 : /** Allocator for buffered algorithms.
29 : */
30 : class allocator;
31 :
32 : /** Destructor.
33 : */
34 : virtual
35 : ~buffered_base();
36 :
37 : /** Initialize the algorithm.
38 :
39 : The derived class must be initialized
40 : before invoking any other members,
41 : except destruction.
42 : The default implementation does nothing.
43 : The purpose of this function is to
44 : allow the derived class to optionally
45 : allocate temporary storage using the
46 : specified allocator, which could offer
47 : advantages.
48 : <br>
49 : Subclasses are still required to operate
50 : correctly even when insufficient storage
51 : is available from the allocator. In this
52 : case they should simply allocate normally.
53 :
54 : @par Preconditions
55 : Initialization has not already occurred.
56 :
57 : @param a The allocator to use.
58 : */
59 : void
60 17 : init(allocator& a)
61 : {
62 17 : on_init(a);
63 14 : }
64 :
65 : /** Initialize the algorithm.
66 :
67 : The derived class must be initialized
68 : before invoking any other members,
69 : except destruction.
70 : The default implementation does nothing.
71 : The purpose of this function is to
72 : allow the derived class to optionally
73 : allocate temporary storage using the
74 : specified allocator, which could offer
75 : advantages.
76 : <br>
77 : Subclasses are still required to operate
78 : correctly even when insufficient storage
79 : is available from the allocator. In this
80 : case they should simply allocate normally.
81 :
82 : @par Preconditions
83 : Initialization has not already occurred.
84 :
85 : @throws std::invalid_argument `max_size > a.max_size()`
86 :
87 : @param a The allocator to use.
88 :
89 : @param max_size The largest allowed
90 : total amount of bytes for the
91 : allocator.
92 : */
93 : void
94 : init(
95 : allocator& a,
96 : std::size_t max_size);
97 :
98 : protected:
99 : /** Initialize the algorithm.
100 :
101 : The default implementation does nothing.
102 : The purpose of this function is to
103 : allow the derived class to optionally
104 : allocate temporary storage using the
105 : specified allocator, which could offer
106 : advantages.
107 : <br>
108 : Subclasses are still required to operate
109 : correctly even when insufficient storage
110 : is available from the allocator. In this
111 : case they should simply allocate normally.
112 :
113 : @par Preconditions
114 : Initialization has not already occurred.
115 :
116 : @param a The allocator to use.
117 : */
118 : virtual
119 : void
120 : on_init(allocator& a);
121 : };
122 :
123 : //------------------------------------------------
124 :
125 : /** Provides memory to buffered algorithms.
126 : */
127 : class buffered_base::allocator
128 : {
129 : public:
130 : /** Constructor
131 :
132 : Default constructed objects return
133 : zero from @ref max_size.
134 : */
135 : allocator() = default;
136 :
137 : /** Constructor
138 :
139 : This function constructs an allocator
140 : which uses the specified contiguous
141 : buffer. Calls to allocate will return
142 : parcels of the buffer from either the
143 : beginning or the end depending on the
144 : value of `downwards`.
145 :
146 : @par Preconditions
147 : @code
148 : p != nullptr || n == 0
149 : @endcode
150 :
151 : @par Exception Safety
152 : Throws nothing.
153 :
154 : @param p A pointer to contiguous storage.
155 : This may be `nullptr` if `n == 0`.
156 :
157 : @param n The number of valid bytes of
158 : storage pointed to by p. This may
159 : be zero.
160 :
161 : @param downwards When true, calls to
162 : allocate will return storage from
163 : the end of the memory pointed to
164 : by `p` rather than the beginning.
165 : */
166 12 : allocator(
167 : void* p,
168 : std::size_t n,
169 : bool downwards) noexcept
170 12 : : base_(static_cast<
171 : unsigned char*>(p))
172 12 : , size_(n)
173 12 : , down_(downwards)
174 : {
175 12 : }
176 :
177 : /** The maximum amount that can be successfully returned from reserve
178 : */
179 : std::size_t
180 38 : max_size() const noexcept
181 : {
182 38 : return size_;
183 : }
184 :
185 : /** Return the total number of bytes allocated
186 : */
187 : std::size_t
188 18 : size_used() const noexcept
189 : {
190 18 : return size_used_;
191 : }
192 :
193 : /** Return a pointer to at least n bytes of contiguous storage
194 :
195 : Allocated storage will be automatically
196 : deallocated when the @ref filter,
197 : @ref sink, or @ref source is destroyed.
198 :
199 : @throws std::invalid_argument `n > max_size()`
200 :
201 : @return A pointer to uninitialized storage.
202 :
203 : @param n The number of bytes.
204 : */
205 : BOOST_HTTP_PROTO_DECL
206 : void*
207 : allocate(std::size_t n);
208 :
209 : private:
210 : void
211 7 : remove(
212 : std::size_t n) noexcept
213 : {
214 7 : if(down_)
215 2 : base_ += n;
216 7 : size_ -= n;
217 7 : }
218 :
219 : void
220 7 : restore(
221 : std::size_t n) noexcept
222 : {
223 7 : if(down_)
224 2 : base_ -= n;
225 7 : size_ += n;
226 7 : }
227 :
228 : friend struct buffered_base;
229 :
230 : unsigned char* base_ = nullptr;
231 : std::size_t size_ = 0;
232 : std::size_t size_used_ = 0;
233 : bool down_ = false;
234 : };
235 :
236 : } // http_proto
237 : } // boost
238 :
239 : #endif
|