include/boost/http/detail/circular_buffer.hpp

93.8% Lines (15/16) 100.0% List of functions (5/5)
circular_buffer.hpp
f(x) Functions (5)
Line TLA Hits 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
8 //
9
10 #ifndef BOOST_HTTP_DETAIL_CIRCULAR_BUFFER_HPP
11 #define BOOST_HTTP_DETAIL_CIRCULAR_BUFFER_HPP
12
13 #include <boost/http/detail/config.hpp>
14 #include <boost/http/detail/except.hpp>
15
16 #include <boost/capy/buffers.hpp>
17
18 #include <array>
19 #include <cstddef>
20
21 namespace boost {
22 namespace http {
23 namespace detail {
24
25 /** A fixed-capacity circular buffer satisfying DynamicBuffer.
26
27 This class implements a circular ( ring ) buffer with
28 fixed capacity determined at construction. Unlike linear
29 buffers, data can wrap around from the end to the beginning,
30 enabling efficient FIFO operations without memory copies.
31
32 Buffer sequences returned from @ref data and @ref prepare
33 may contain up to two elements to represent wrapped regions.
34
35 @par Example
36 @code
37 char storage[1024];
38 circular_buffer cb( storage, sizeof( storage ) );
39
40 // Write data
41 auto mb = cb.prepare( 100 );
42 std::memcpy( mb.data(), "hello", 5 );
43 cb.commit( 5 );
44
45 // Read data
46 auto cb_data = cb.data();
47 // process cb_data...
48 cb.consume( 5 );
49 @endcode
50
51 @par Thread Safety
52 Distinct objects: Safe.
53 Shared objects: Unsafe.
54 */
55 class circular_buffer
56 {
57 unsigned char* base_ = nullptr;
58 std::size_t cap_ = 0;
59 std::size_t in_pos_ = 0;
60 std::size_t in_len_ = 0;
61 std::size_t out_size_ = 0;
62
63 public:
64 /// Indicates this is a DynamicBuffer adapter over external storage.
65 using is_circular_buffer_adapter = void;
66
67 /// The ConstBufferSequence type for readable bytes.
68 using const_buffers_type = std::array<capy::const_buffer, 2>;
69
70 /// The MutableBufferSequence type for writable bytes.
71 using mutable_buffers_type = std::array<capy::mutable_buffer, 2>;
72
73 /// Construct an empty circular buffer with zero capacity.
74 9051x circular_buffer() = default;
75
76 /** Construct a copy.
77
78 Copies the adapter state (position and length) but does
79 not deep-copy the backing storage. Both objects alias the
80 same external buffer.
81
82 @note The underlying storage must outlive all copies.
83 */
84 circular_buffer(
85 circular_buffer const&) = default;
86
87 /** Construct a circular buffer over existing storage.
88
89 @param base Pointer to the storage.
90 @param capacity Size of the storage in bytes.
91 */
92 4488x circular_buffer(
93 void* base,
94 std::size_t capacity) noexcept
95 4488x : base_(static_cast<
96 unsigned char*>(base))
97 4488x , cap_(capacity)
98 {
99 4488x }
100
101 /** Construct a circular buffer with initial readable bytes.
102
103 @param base Pointer to the storage.
104 @param capacity Size of the storage in bytes.
105 @param initial_size Number of bytes already present as
106 readable. Must not exceed @p capacity.
107
108 @throws std::invalid_argument if initial_size > capacity.
109 */
110 9522x circular_buffer(
111 void* base,
112 std::size_t capacity,
113 std::size_t initial_size)
114 9522x : base_(static_cast<
115 unsigned char*>(base))
116 9522x , cap_(capacity)
117 9522x , in_len_(initial_size)
118 {
119 9522x if(in_len_ > capacity)
120 detail::throw_invalid_argument();
121 9522x }
122
123 /** Assign by copying.
124
125 Copies the adapter state but does not deep-copy the
126 backing storage. Both objects alias the same external
127 buffer afterward.
128
129 @note The underlying storage must outlive all copies.
130 */
131 circular_buffer& operator=(
132 circular_buffer const&) = default;
133
134 /// Return the number of readable bytes.
135 std::size_t
136 181027x size() const noexcept
137 {
138 181027x return in_len_;
139 }
140
141 /// Return the maximum number of bytes the buffer can hold.
142 std::size_t
143 max_size() const noexcept
144 {
145 return cap_;
146 }
147
148 /// Return the number of writable bytes without reallocation.
149 std::size_t
150 162929x capacity() const noexcept
151 {
152 162929x return cap_ - in_len_;
153 }
154
155 /// Return a buffer sequence representing the readable bytes.
156 BOOST_HTTP_DECL
157 const_buffers_type
158 data() const noexcept;
159
160 /** Return a buffer sequence for writing.
161
162 Invalidates buffer sequences previously obtained
163 from @ref prepare.
164
165 @param n The desired number of writable bytes.
166
167 @return A mutable buffer sequence of size @p n.
168
169 @throws std::length_error if `size() + n > max_size()`.
170 */
171 BOOST_HTTP_DECL
172 mutable_buffers_type
173 prepare(std::size_t n);
174
175 /** Move bytes from the output to the input sequence.
176
177 Invalidates buffer sequences previously obtained
178 from @ref prepare. Buffer sequences from @ref data
179 remain valid.
180
181 @param n The number of bytes to commit. If greater
182 than the prepared size, all prepared bytes
183 are committed.
184 */
185 BOOST_HTTP_DECL
186 void
187 commit(std::size_t n) noexcept;
188
189 /** Remove bytes from the beginning of the input sequence.
190
191 Invalidates buffer sequences previously obtained
192 from @ref data. Buffer sequences from @ref prepare
193 remain valid.
194
195 @param n The number of bytes to consume. If greater
196 than @ref size(), all readable bytes are consumed.
197 */
198 BOOST_HTTP_DECL
199 void
200 consume(std::size_t n) noexcept;
201 };
202
203 } // detail
204 } // http
205 } // boost
206
207 #endif
208