Line | Branch | Exec | Source |
---|---|---|---|
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 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
|
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 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
|
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 | ||
240 |