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