GCC Code Coverage Report


Directory: libs/http_proto/include/boost/http_proto/
File: boost/http_proto/detail/workspace.hpp
Date: 2023-01-15 07:18:31
Exec Total Coverage
Lines: 60 62 96.8%
Functions: 25 25 100.0%
Branches: 9 14 64.3%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 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_DETAIL_WORKSPACE_HPP
11 #define BOOST_HTTP_PROTO_DETAIL_WORKSPACE_HPP
12
13 #include <boost/http_proto/detail/except.hpp>
14 #include <boost/assert.hpp>
15 #include <cstdlib>
16 #include <new>
17 #include <utility>
18 #include <stddef.h> // ::max_align_t
19
20 namespace boost {
21 namespace http_proto {
22 namespace detail {
23
24 class workspace
25 {
26 76 struct any
27 {
28 any* next = nullptr;
29
30 BOOST_HTTP_PROTO_DECL
31 virtual ~any() = 0;
32 };
33
34 template<class T>
35 struct alignas(alignof(::max_align_t))
36 any_t : any
37 {
38 T t_;
39
40 any_t() = delete;
41 any_t(any_t&&) = default;
42
43 explicit
44 28 any_t(
45 T&& t)
46 28 : t_(std::move(t))
47 {
48 28 }
49
50 explicit
51 6 any_t(
52 T const& t)
53 6 : t_(t)
54 {
55 6 }
56 };
57
58 template<class T>
59 struct alignas(alignof(::max_align_t))
60 any_n : any
61 {
62 std::size_t n_ = 0;
63
64 21 any_n() = default;
65
66 42 ~any_n()
67 {
68 182 for(std::size_t i = n_;
69
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 21 times.
182 i-- > 0;)
70 140 data()[i].~T();
71 }
72
73 21 any_n(
74 std::size_t n,
75 T const& t)
76 21 : any_n()
77 {
78
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 21 times.
91 while(n_ < n)
79 {
80 70 new(&data()[n_]) T(t);
81 70 ++n_;
82 }
83 21 }
84
85 T*
86 161 data() noexcept
87 {
88 return
89 reinterpret_cast<T*>(
90 161 this + 1);
91 }
92 };
93
94 unsigned char* begin_ = nullptr;
95 unsigned char* end_ = nullptr;
96 unsigned char* head_ = nullptr;
97
98 public:
99 workspace() = default;
100
101 15 ~workspace()
102 15 {
103 15 clear();
104
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 delete[] begin_;
105 15 }
106
107 explicit
108 15 workspace(
109 std::size_t n)
110 15 : begin_(new unsigned char[n])
111 15 , end_(begin_ + n)
112 15 , head_(end_)
113 {
114 15 }
115
116 void*
117 8 data() noexcept
118 {
119 8 return begin_;
120 }
121
122 std::size_t
123 35 size() const noexcept
124 {
125 35 return head_ - begin_;
126 }
127
128 BOOST_HTTP_PROTO_DECL
129 void
130 clear() noexcept;
131
132 BOOST_HTTP_PROTO_DECL
133 void*
134 reserve(std::size_t n);
135
136 template<class T>
137 auto
138 34 push(T&& t) ->
139 typename std::decay<T>::type&
140 {
141
142 using U = any_t<typename
143 std::decay<T>::type>;
144 34 auto p = ::new(bump_down(
145 sizeof(U), alignof(U))) U(
146 34 std::forward<T>(t));
147 34 p->next = reinterpret_cast<
148 34 any*>(head_);
149 34 head_ = reinterpret_cast<
150 unsigned char*>(p);
151 34 return p->t_;
152 }
153
154 template<class T>
155 T*
156 21 push_array(
157 std::size_t n,
158 T const& t)
159 {
160 using U = any_n<T>;
161 21 auto p = ::new(bump_down(
162 21 sizeof(U) + n * sizeof(T),
163 alignof(::max_align_t))) U(n, t);
164 21 p->next = reinterpret_cast<
165 21 any*>(head_);
166 21 head_ = reinterpret_cast<
167 unsigned char*>(p);
168 21 return p->data();
169 }
170
171 private:
172 // https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html
173 void*
174 38 bump_down(
175 std::size_t size,
176 std::size_t align)
177 {
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 BOOST_ASSERT(align > 0);
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 BOOST_ASSERT(
180 (align & (align - 1)) == 0);
181
182 38 auto ip0 = reinterpret_cast<
183 38 std::uintptr_t>(begin_);
184 38 auto ip = reinterpret_cast<
185 38 std::uintptr_t>(head_);
186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if(size > ip - ip0)
187 detail::throw_bad_alloc();
188 38 ip -= size;
189 38 ip &= ~(align - 1);
190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if(ip < ip0)
191 detail::throw_bad_alloc();
192 38 return reinterpret_cast<void*>(ip);
193 }
194 };
195
196 } // detail
197 } // http_proto
198 } // boost
199
200 #endif
201