Line | Branch | Exec | Source |
---|---|---|---|
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/buffers | ||
8 | // | ||
9 | |||
10 | #ifndef BOOST_BUFFERS_ANY_DYNAMIC_BUFFER_HPP | ||
11 | #define BOOST_BUFFERS_ANY_DYNAMIC_BUFFER_HPP | ||
12 | |||
13 | #include <boost/buffers/detail/config.hpp> | ||
14 | #include <boost/buffers/const_buffer_span.hpp> | ||
15 | #include <boost/buffers/mutable_buffer_span.hpp> | ||
16 | #include <boost/buffers/range.hpp> | ||
17 | #include <boost/buffers/type_traits.hpp> | ||
18 | #include <cstdlib> | ||
19 | |||
20 | namespace boost { | ||
21 | namespace buffers { | ||
22 | |||
23 | /** An abstract, type-erased dynamic buffer. | ||
24 | */ | ||
25 | struct BOOST_SYMBOL_VISIBLE | ||
26 | any_dynamic_buffer | ||
27 | { | ||
28 | using const_buffers_type = | ||
29 | buffers::const_buffer_span; | ||
30 | |||
31 | using mutable_buffers_type = | ||
32 | buffers::mutable_buffer_span; | ||
33 | |||
34 | 8192 | virtual ~any_dynamic_buffer() = default; | |
35 | virtual std::size_t size() const = 0; | ||
36 | virtual std::size_t max_size() const = 0; | ||
37 | virtual std::size_t capacity() const = 0; | ||
38 | virtual const_buffers_type data() const = 0; | ||
39 | virtual mutable_buffers_type prepare(std::size_t) = 0; | ||
40 | virtual void commit(std::size_t) = 0; | ||
41 | virtual void consume(std::size_t) = 0; | ||
42 | }; | ||
43 | |||
44 | //----------------------------------------------- | ||
45 | |||
46 | /** A type-erased dynamic buffer. | ||
47 | */ | ||
48 | template< | ||
49 | class DynamicBuffer, | ||
50 | std::size_t N = 8> | ||
51 | class any_dynamic_buffer_impl | ||
52 | : public any_dynamic_buffer | ||
53 | { | ||
54 | DynamicBuffer b_; | ||
55 | buffers::const_buffer data_[N]; | ||
56 | buffers::mutable_buffer out_[N]; | ||
57 | std::size_t data_len_ = 0; | ||
58 | std::size_t out_len_ = 0; | ||
59 | |||
60 | template<class Buffers> | ||
61 | static | ||
62 | std::size_t | ||
63 | 69760 | unroll( | |
64 | Buffers const& bs, | ||
65 | value_type<Buffers>* dest, | ||
66 | std::size_t len) | ||
67 | { | ||
68 | 69760 | std::size_t i = 0; | |
69 |
2/2✓ Branch 3 taken 69760 times.
✓ Branch 4 taken 34880 times.
|
209280 | for(auto b : buffers::range(bs)) |
70 | { | ||
71 | 139520 | dest[i++] = b; | |
72 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69760 times.
|
139520 | if(i == len) |
73 | ✗ | break; | |
74 | } | ||
75 | 69760 | return i; | |
76 | } | ||
77 | |||
78 | public: | ||
79 | template<class DynamicBuffer_> | ||
80 | explicit | ||
81 | 4096 | any_dynamic_buffer_impl( | |
82 | DynamicBuffer_&& b) | ||
83 | 4096 | : b_(std::forward< | |
84 | 4096 | DynamicBuffer_>(b)) | |
85 | { | ||
86 | 4096 | } | |
87 | |||
88 | DynamicBuffer& | ||
89 | buffer() noexcept | ||
90 | { | ||
91 | return b_; | ||
92 | } | ||
93 | |||
94 | DynamicBuffer const& | ||
95 | buffer() const noexcept | ||
96 | { | ||
97 | return b_; | ||
98 | } | ||
99 | |||
100 | std::size_t | ||
101 | ✗ | size() const override | |
102 | { | ||
103 | ✗ | return b_.size(); | |
104 | } | ||
105 | |||
106 | std::size_t | ||
107 | ✗ | max_size() const override | |
108 | { | ||
109 | ✗ | return b_.max_size(); | |
110 | } | ||
111 | |||
112 | std::size_t | ||
113 | ✗ | capacity() const override | |
114 | { | ||
115 | ✗ | return b_.capacity(); | |
116 | } | ||
117 | |||
118 | const_buffers_type | ||
119 | 12288 | data() const override | |
120 | { | ||
121 | 24576 | return const_buffers_type( | |
122 | 12288 | data_, data_len_); | |
123 | } | ||
124 | |||
125 | auto | ||
126 | 11792 | prepare( | |
127 | std::size_t n) -> | ||
128 | mutable_buffers_type override | ||
129 | { | ||
130 | 11792 | out_len_ = unroll( | |
131 | 11792 | b_.prepare(n), out_, N); | |
132 | 23584 | return mutable_buffers_type( | |
133 | 11792 | out_, out_len_); | |
134 | } | ||
135 | |||
136 | void | ||
137 | 11792 | commit( | |
138 | std::size_t n) override | ||
139 | { | ||
140 | 11792 | b_.commit(n); | |
141 | 11792 | data_len_ = unroll( | |
142 | 11792 | b_.data(), data_, N); | |
143 | 11792 | } | |
144 | |||
145 | void | ||
146 | 11296 | consume( | |
147 | std::size_t n) override | ||
148 | { | ||
149 | 11296 | b_.consume(n); | |
150 | 11296 | data_len_ = unroll( | |
151 | 11296 | b_.data(), data_, N); | |
152 | 11296 | } | |
153 | }; | ||
154 | |||
155 | template< | ||
156 | class DynamicBuffer | ||
157 | , class = typename std::enable_if< | ||
158 | is_dynamic_buffer< | ||
159 | typename std::decay<DynamicBuffer>::type | ||
160 | >::value>::type | ||
161 | > | ||
162 | auto | ||
163 | 4096 | make_any(DynamicBuffer&& b) -> | |
164 | any_dynamic_buffer_impl<typename | ||
165 | std::decay<DynamicBuffer>::type> | ||
166 | { | ||
167 | return any_dynamic_buffer_impl<typename | ||
168 | std::decay<DynamicBuffer>::type>( | ||
169 | 4096 | std::forward<DynamicBuffer>(b)); | |
170 | } | ||
171 | |||
172 | } // buffers | ||
173 | } // boost | ||
174 | |||
175 | #endif | ||
176 |