Line data 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/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 4096 : 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 34880 : unroll(
64 : Buffers const& bs,
65 : value_type<Buffers>* dest,
66 : std::size_t len)
67 : {
68 34880 : std::size_t i = 0;
69 104640 : for(auto b : buffers::range(bs))
70 : {
71 69760 : dest[i++] = b;
72 69760 : if(i == len)
73 0 : break;
74 : }
75 34880 : 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 0 : size() const override
102 : {
103 0 : return b_.size();
104 : }
105 :
106 : std::size_t
107 0 : max_size() const override
108 : {
109 0 : return b_.max_size();
110 : }
111 :
112 : std::size_t
113 0 : capacity() const override
114 : {
115 0 : 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
|