include/boost/http/detail/flat_buffer.hpp

91.7% Lines (22/24) 100.0% List of functions (6/6)
flat_buffer.hpp
f(x) Functions (6)
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_FLAT_BUFFER_HPP
11 #define BOOST_HTTP_DETAIL_FLAT_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 <cstddef>
19
20 namespace boost {
21 namespace http {
22 namespace detail {
23
24 /** A fixed-capacity linear buffer satisfying DynamicBuffer.
25
26 This class provides a contiguous buffer with fixed capacity
27 determined at construction. Buffer sequences returned from
28 @ref data and @ref prepare always contain exactly one element,
29 making it suitable for APIs requiring contiguous memory.
30
31 @par Example
32 @code
33 char storage[1024];
34 flat_buffer fb( storage, sizeof( storage ) );
35
36 // Write data
37 auto mb = fb.prepare( 100 );
38 std::memcpy( mb.data(), "hello", 5 );
39 fb.commit( 5 );
40
41 // Read data
42 auto data = fb.data();
43 // process data...
44 fb.consume( 5 );
45 @endcode
46
47 @par Thread Safety
48 Distinct objects: Safe.
49 Shared objects: Unsafe.
50
51 @see circular_buffer
52 */
53 class flat_buffer
54 {
55 unsigned char* data_ = nullptr;
56 std::size_t cap_ = 0;
57 std::size_t in_pos_ = 0;
58 std::size_t in_size_ = 0;
59 std::size_t out_size_ = 0;
60
61 public:
62 /// Indicates this is a DynamicBuffer adapter over external storage.
63 using is_circular_buffer_adapter = void;
64
65 /// The ConstBufferSequence type for readable bytes.
66 using const_buffers_type = capy::const_buffer;
67
68 /// The MutableBufferSequence type for writable bytes.
69 using mutable_buffers_type = capy::mutable_buffer;
70
71 /// Construct an empty flat buffer with zero capacity.
72 2175x flat_buffer() = default;
73
74 /** Construct a flat buffer over existing storage.
75
76 @param data Pointer to the storage.
77 @param capacity Size of the storage in bytes.
78 @param initial_size Number of bytes already present as
79 readable. Must not exceed @p capacity.
80
81 @throws std::invalid_argument if initial_size > capacity.
82 */
83 10647x flat_buffer(
84 void* data,
85 std::size_t capacity,
86 std::size_t initial_size = 0)
87 10647x : data_(static_cast<
88 unsigned char*>(data))
89 10647x , cap_(capacity)
90 10647x , in_size_(initial_size)
91 {
92 10647x if(in_size_ > cap_)
93 detail::throw_invalid_argument();
94 10647x }
95
96 /// Construct a copy.
97 flat_buffer(
98 flat_buffer const&) = default;
99
100 /// Assign by copying.
101 flat_buffer& operator=(
102 flat_buffer const&) = default;
103
104 /// Return the number of readable bytes.
105 std::size_t
106 54566x size() const noexcept
107 {
108 54566x return in_size_;
109 }
110
111 /// Return the maximum number of bytes the buffer can hold.
112 std::size_t
113 max_size() const noexcept
114 {
115 return cap_;
116 }
117
118 /// Return the number of writable bytes without reallocation.
119 std::size_t
120 99018x capacity() const noexcept
121 {
122 99018x return cap_ - (in_pos_ + in_size_);
123 }
124
125 /// Return a buffer sequence representing the readable bytes.
126 const_buffers_type
127 data() const noexcept
128 {
129 return const_buffers_type(
130 data_ + in_pos_, in_size_);
131 }
132
133 /** Return a buffer sequence for writing.
134
135 Invalidates buffer sequences previously obtained
136 from @ref prepare.
137
138 @param n The desired number of writable bytes.
139
140 @return A mutable buffer sequence of size @p n.
141
142 @throws std::invalid_argument if `n > capacity()`.
143 */
144 mutable_buffers_type
145 39830x prepare(std::size_t n)
146 {
147 39830x if( n > capacity() )
148 detail::throw_invalid_argument();
149
150 39830x out_size_ = n;
151 79660x return mutable_buffers_type(
152 39830x data_ + in_pos_ + in_size_, n);
153 }
154
155 /** Move bytes from the output to the input sequence.
156
157 Invalidates buffer sequences previously obtained
158 from @ref prepare. Buffer sequences from @ref data
159 remain valid.
160
161 @param n The number of bytes to commit. If greater
162 than the prepared size, all prepared bytes
163 are committed.
164 */
165 void
166 39046x commit(
167 std::size_t n) noexcept
168 {
169 39046x if(n < out_size_)
170 39030x in_size_ += n;
171 else
172 16x in_size_ += out_size_;
173 39046x out_size_ = 0;
174 39046x }
175
176 /** Remove bytes from the beginning of the input sequence.
177
178 Invalidates buffer sequences previously obtained
179 from @ref data. Buffer sequences from @ref prepare
180 remain valid.
181
182 @param n The number of bytes to consume. If greater
183 than @ref size(), all readable bytes are consumed.
184 */
185 void
186 consume(
187 std::size_t n) noexcept
188 {
189 if(n < in_size_)
190 {
191 in_pos_ += n;
192 in_size_ -= n;
193 }
194 else
195 {
196 in_pos_ = 0;
197 in_size_ = 0;
198 }
199 }
200 };
201
202 } // detail
203 } // http
204 } // boost
205
206 #endif
207