GCC Code Coverage Report


Directory: libs/http_proto/
File: src/detail/workspace.cpp
Date: 2025-09-21 18:08:15
Exec Total Coverage
Lines: 54 89 60.7%
Functions: 8 11 72.7%
Branches: 12 30 40.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2025 Mohammad Nejati
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/http_proto
9 //
10
11 #include <boost/http_proto/detail/workspace.hpp>
12 #include <boost/http_proto/detail/except.hpp>
13 #include <boost/assert.hpp>
14 #include <boost/core/exchange.hpp>
15 #include <utility>
16
17 namespace boost {
18 namespace http_proto {
19 namespace detail {
20
21 2022 workspace::
22 any::
23 ~any() = default;
24
25 1078 workspace::
26 ~workspace()
27 {
28 1078 clear();
29
1/2
✓ Branch 0 taken 1078 times.
✗ Branch 1 not taken.
1078 delete[] begin_;
30 1078 }
31
32 1078 workspace::
33 workspace(
34 1078 std::size_t n)
35 1078 : begin_(new unsigned char[n])
36 1078 , front_(begin_)
37 1078 , head_(begin_ + n)
38 1078 , back_(head_)
39 1078 , end_(head_)
40 {
41 1078 }
42
43 workspace::
44 workspace(
45 workspace&& other) noexcept
46 : begin_(boost::exchange(other.begin_, nullptr))
47 , front_(boost::exchange(other.front_, nullptr))
48 , head_(boost::exchange(other.head_, nullptr))
49 , back_(boost::exchange(other.back_, nullptr))
50 , end_(boost::exchange(other.end_, nullptr))
51 {
52 }
53
54 workspace&
55 workspace::
56 operator=(
57 workspace&& other) noexcept
58 {
59 if(this != &other)
60 {
61 delete[] begin_;
62
63 begin_ = boost::exchange(other.begin_, nullptr);
64 front_ = boost::exchange(other.front_, nullptr);
65 head_ = boost::exchange(other.head_, nullptr);
66 back_ = boost::exchange(other.back_, nullptr);
67 end_ = boost::exchange(other.end_, nullptr);
68 }
69 return *this;
70 }
71
72 void
73 workspace::
74 allocate(
75 std::size_t n)
76 {
77 // Cannot be empty
78 if(n == 0)
79 detail::throw_invalid_argument();
80
81 // Already allocated
82 if(begin_ != nullptr)
83 detail::throw_logic_error();
84
85 begin_ = new unsigned char[n];
86 front_ = begin_;
87 head_ = begin_ + n;
88 back_ = head_;
89 end_ = head_;
90 }
91
92 void
93 21990 workspace::
94 clear() noexcept
95 {
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21990 times.
21990 if(! begin_)
97 return;
98
99 21990 auto const end =
100 reinterpret_cast<
101 any const*>(back_);
102 21990 auto p =
103 reinterpret_cast<
104 any const*>(head_);
105
2/2
✓ Branch 0 taken 1011 times.
✓ Branch 1 taken 21990 times.
23001 while(p != end)
106 {
107 1011 auto next = p->next;
108 1011 p->~any();
109 1011 p = next;
110 }
111 21990 front_ = begin_;
112 21990 head_ = end_;
113 21990 back_ = end_;
114 }
115
116 unsigned char*
117 28770 workspace::
118 reserve_front(
119 std::size_t n)
120 {
121 // Requested size exceeds available space.
122 // Note you can never reserve the last byte.
123
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28770 times.
28770 if(n >= size())
124 detail::throw_length_error();
125
126 28770 auto const p = front_;
127 28770 front_ += n ;
128 28770 return p;
129 }
130
131 unsigned char*
132 368 workspace::
133 try_reserve_front(
134 std::size_t n) noexcept
135 {
136 // Requested size exceeds available space.
137 // Note you can never reserve the last byte.
138
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 368 times.
368 if(n >= size())
139 return nullptr;
140
141 368 auto const p = front_;
142 368 front_ += n ;
143 368 return p;
144 }
145
146 unsigned char*
147 10006 workspace::
148 reserve_back(
149 std::size_t n)
150 {
151 // // can't reserve after acquire
152 // if(head_ != end_)
153 // detail::throw_logic_error();
154
155 // can't reserve twice
156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10006 times.
10006 if(back_ != end_)
157 detail::throw_logic_error();
158
159 // over capacity
160 10006 std::size_t const lim =
161 10006 head_ - front_;
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10006 times.
10006 if(n >= lim)
163 detail::throw_length_error();
164
165 10006 head_ -= n;
166 10006 back_ = head_;
167 10006 return back_;
168 }
169
170 // https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html
171 unsigned char*
172 1011 workspace::
173 bump_down(
174 std::size_t size,
175 std::size_t align)
176 {
177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1011 times.
1011 BOOST_ASSERT(align > 0);
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1011 times.
1011 BOOST_ASSERT(
179 (align & (align - 1)) == 0);
180
181 1011 auto ip0 = reinterpret_cast<
182 1011 std::uintptr_t>(front_);
183 1011 auto ip = reinterpret_cast<
184 1011 std::uintptr_t>(head_);
185
186 // If you get an exception here, it
187 // means that a buffer was too small
188 // for your workload. Increase the
189 // buffer size.
190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1011 times.
1011 if(size > ip - ip0)
191 detail::throw_length_error();
192
193 1011 ip -= size;
194 1011 ip &= ~(align - 1);
195
196 // If you get an exception here, it
197 // means that a buffer was too small
198 // for your workload. Increase the
199 // buffer size.
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1011 times.
1011 if(ip < ip0)
201 detail::throw_length_error();
202
203 return reinterpret_cast<
204 1011 unsigned char*>(ip);
205 }
206
207 } // detail
208 } // http_proto
209 } // boost
210