GCC Code Coverage Report


Directory: libs/beast2/
File: include/boost/beast2/server/fixed_array.hpp
Date: 2025-11-13 15:50:44
Exec Total Coverage
Lines: 0 29 0.0%
Functions: 0 8 0.0%
Branches: 0 14 0.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2022 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/cppalliance/beast2
8 //
9
10 #ifndef BOOST_BEAST2_SERVER_FIXED_ARRAY_HPP
11 #define BOOST_BEAST2_SERVER_FIXED_ARRAY_HPP
12
13 #include <boost/beast2/detail/config.hpp>
14 #include <boost/core/span.hpp>
15 #include <boost/assert.hpp>
16 #include <cstddef>
17 #include <cstdlib>
18 #include <memory>
19 #include <new>
20 #include <stdexcept>
21 #include <utility>
22
23 template<class T>
24 class fixed_array;
25
26 /** A type-erased fixed_array
27 */
28 class any_fixed_array
29 {
30 public:
31 /** Destructor
32
33 All elements are destroyed in reverse order.
34 */
35 ~any_fixed_array()
36 {
37 if(t_)
38 destroy_(this);
39 }
40
41 /** Constructor
42 */
43 any_fixed_array() = default;
44
45 /** Constructor
46
47 Ownership of all elements in the moved-from object is transferred.
48 */
49 any_fixed_array(
50 any_fixed_array&& other) noexcept
51 : any_fixed_array()
52 {
53 swap(*this, other);
54 }
55
56 /** Constructor
57
58 Ownership of all elements in the moved-from object is transferred.
59
60 @par Postconditions
61 @code
62 other.size() == 0 && other.capacity() == 0
63 @endcode
64 */
65 template<class T>
66 any_fixed_array(
67 fixed_array<T>&& other) noexcept
68 : t_(other.t_)
69 , n_(other.n_)
70 , cap_(other.cap_)
71 , destroy_(&destroy<T>)
72 {
73 other.t_ = nullptr;
74 other.n_ = 0;
75 other.cap_ = 0;
76 }
77
78 /** Constructor
79
80 Ownership of all elements in the moved-from object is transferred.
81
82 @par Postconditions
83 @code
84 other.size() == 0 && other.capacity() == 0
85 @endcode
86 */
87 any_fixed_array&
88 operator=(
89 any_fixed_array&& other) noexcept
90 {
91 any_fixed_array temp;
92 swap(*this, temp);
93 swap(other, *this);
94 return *this;
95 }
96
97 /** Return the number of elements
98 */
99 std::size_t size() const noexcept
100 {
101 return n_;
102 }
103
104 /** Return a typed span of elements
105
106 This function returns the span of elements contained in the array.
107 The specified type `T` must match the type of element used
108 to construct the array, or else the behavior is undefined.
109
110 @tparam T The type of element used to construct the array.
111 */
112 template<class T>
113 boost::span<T>
114 to_span() noexcept
115 {
116 return { reinterpret_cast<T*>(t_), n_ };
117 }
118
119 /** Swap objects
120 */
121 friend void swap(
122 any_fixed_array& a0,
123 any_fixed_array& a1) noexcept
124 {
125 std::swap(a0.t_, a1.t_);
126 std::swap(a0.n_, a1.n_);
127 std::swap(a0.cap_, a1.cap_);
128 std::swap(a0.destroy_, a1.destroy_);
129 }
130
131 private:
132 template<class T>
133 friend class fixed_array;
134
135 template<class T>
136 static void destroy(any_fixed_array* p)
137 {
138 fixed_array<T> v(*p);
139 }
140
141 void* t_ = nullptr;
142 std::size_t n_ = 0;
143 std::size_t cap_ = 0;
144 void(*destroy_)(any_fixed_array*) = 0;
145 };
146
147 //------------------------------------------------
148
149 /** An append-only array with a fixed capacity
150
151 This container is used to hold elements which
152 are all constructed at once, where the elements
153 do not require move constructability or assignability.
154 */
155 template<class T>
156 class fixed_array
157 {
158 public:
159 using value_type = T;
160 using reference = T&;
161 using pointer = T*;
162 using iterator = T*;
163 using const_reference = T const&;
164 using const_pointer = T const*;
165 using const_iterator = T const*;
166 using difference_type = std::ptrdiff_t;
167 using size_type = std::size_t;
168
169 ~fixed_array()
170 {
171 if(! t_)
172 return;
173 while(n_--)
174 t_[n_].~T();
175 std::allocator<T>{}.deallocate(t_, cap_);
176 }
177
178 /** Constructor
179
180 The moved-from object will have zero
181 capacity and zero size.
182 */
183 fixed_array(fixed_array&& other) noexcept
184 {
185 t_ = other.t_;
186 n_ = other.n_;
187 cap_ = other.cap_;
188 other.t_ = nullptr;
189 other.n_ = 0;
190 other.cap_ = 0;
191 }
192
193 /** Constructor
194
195 The array will have the specified capacity.
196
197 @par Postconditions
198 ```
199 size() == 0 && capacity() == cap
200 ```
201 */
202 explicit
203 fixed_array(std::size_t cap)
204 : t_(std::allocator<T>{}.allocate(cap))
205 , n_(0)
206 , cap_(cap)
207 {
208 }
209
210 std::size_t
211 capacity() const noexcept
212 {
213 return cap_;
214 }
215
216 std::size_t
217 size() const noexcept
218 {
219 return n_;
220 }
221
222 bool
223 is_full() const noexcept
224 {
225 return n_ >= cap_;
226 }
227
228 /** Return a pointer to the beginning of the array
229 */
230 T* data() noexcept
231 {
232 return t_;
233 }
234
235 /** Return a pointer to the beginning of the array
236 */
237 T const* data() const noexcept
238 {
239 return t_;
240 }
241
242 reference operator[](std::size_t i)
243 {
244 BOOST_ASSERT(i < n_);
245 return t_[i];
246 }
247
248 const_reference operator[](std::size_t i) const
249 {
250 BOOST_ASSERT(i < n_);
251 return t_[i];
252 }
253
254 reference at(std::size_t i)
255 {
256 if(i < n_)
257 return t_[i];
258 // VFALCO use detail::throw_out_of_range when it is available
259 throw std::out_of_range("i >= size()");
260 }
261
262 const_reference at(std::size_t i) const
263 {
264 if(i < n_)
265 return t_[i];
266 // VFALCO use detail::throw_out_of_range when it is available
267 throw std::out_of_range("i >= size()");
268 }
269
270 template<class... Args>
271 T& emplace_back(Args&&... args)
272 {
273 if(is_full())
274 // VFALCO use detail::throw_out_of_range when it is available
275 throw std::out_of_range("full");
276 auto p = t_ + n_;
277 ::new(p) T(std::forward<Args>(args)...);
278 ++n_;
279 return *p;
280 }
281
282 const_iterator
283 begin() const noexcept
284 {
285 return t_;
286 }
287
288 const_iterator
289 end() const noexcept
290 {
291 return t_ + n_;
292 }
293
294 iterator
295 begin() noexcept
296 {
297 return t_;
298 }
299
300 iterator
301 end() noexcept
302 {
303 return t_ + n_;
304 }
305
306 private:
307 #if 0
308 //#if __cplusplus < 201703L // gcc nonconforming
309 static_assert(
310 alignof(T) <=
311 alignof(std::max_align_t),
312 "T must not be overaligned");
313 //#endif
314 #endif
315
316 friend class any_fixed_array;
317
318 fixed_array(
319 any_fixed_array& v) noexcept
320 : t_(reinterpret_cast<T*>(v.t_))
321 , n_(v.n_)
322 , cap_(v.cap_)
323 {
324 }
325
326 T* t_ = nullptr;
327 std::size_t n_;
328 std::size_t cap_;
329 };
330
331 #endif
332