include/boost/capy/buffers/circular_dynamic_buffer.hpp

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