libs/capy/include/boost/capy/buffers/circular_dynamic_buffer.hpp

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