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_ALGORITHM_HPP
11 : #define BOOST_BUFFERS_ALGORITHM_HPP
12 :
13 : #include <boost/buffers/detail/config.hpp>
14 : #include <boost/buffers/buffer_size.hpp>
15 : #include <boost/buffers/const_buffer.hpp>
16 : #include <boost/buffers/mutable_buffer.hpp>
17 : #include <boost/buffers/range.hpp>
18 : #include <boost/buffers/tag_invoke.hpp>
19 : #include <boost/buffers/type_traits.hpp>
20 :
21 : namespace boost {
22 : namespace buffers {
23 :
24 : template<class BufferSequence>
25 : void
26 : tag_invoke(
27 : prefix_tag const&,
28 : BufferSequence const&,
29 : std::size_t) = delete;
30 :
31 : template<class BufferSequence>
32 : void
33 : tag_invoke(
34 : suffix_tag const&,
35 : BufferSequence const&,
36 : std::size_t) = delete;
37 :
38 : /** Returns the type of a prefix of a buffer sequence.
39 : */
40 : template<class BufferSequence>
41 : using prefix_type = decltype(
42 : tag_invoke(
43 : prefix_tag{},
44 : std::declval<BufferSequence const&>(),
45 : std::size_t{}));
46 :
47 : /** Returns the type of a suffix of a buffer sequence.
48 : */
49 : template<class BufferSequence>
50 : using suffix_type = decltype(
51 : tag_invoke(
52 : suffix_tag{},
53 : std::declval<BufferSequence const&>(),
54 : std::size_t{}));
55 :
56 : namespace detail {
57 :
58 : struct prefix_impl
59 : {
60 : template<class BufferSequence>
61 : prefix_type<BufferSequence>
62 527920 : operator()(
63 : BufferSequence const& b,
64 : std::size_t n) const
65 : {
66 : static_assert(
67 : is_const_buffer_sequence<
68 : BufferSequence>::value,
69 : "Type requirements not met");
70 :
71 1055840 : return tag_invoke(
72 527920 : prefix_tag{}, b, n);
73 : }
74 : };
75 :
76 : struct sans_suffix_impl
77 : {
78 : template<class BufferSequence>
79 : prefix_type<BufferSequence>
80 514 : operator()(
81 : BufferSequence const& b,
82 : std::size_t n) const
83 : {
84 514 : auto const n0 = buffer_size(b);
85 514 : if(n < n0)
86 964 : return tag_invoke(
87 482 : prefix_tag{}, b, n0 - n);
88 64 : return tag_invoke(
89 32 : prefix_tag{}, b, 0);
90 : }
91 : };
92 :
93 : struct suffix_impl
94 : {
95 : template<class BufferSequence>
96 : suffix_type<BufferSequence>
97 280606 : operator()(
98 : BufferSequence const& b,
99 : std::size_t n) const
100 : {
101 : static_assert(
102 : is_const_buffer_sequence<
103 : BufferSequence>::value,
104 : "Type requirements not met");
105 :
106 561212 : return tag_invoke(
107 280606 : suffix_tag{}, b, n);
108 : }
109 : };
110 :
111 : struct sans_prefix_impl
112 : {
113 : template<class BufferSequence>
114 : suffix_type<BufferSequence>
115 280468 : operator()(
116 : BufferSequence const& b,
117 : std::size_t n) const
118 : {
119 : static_assert(
120 : is_const_buffer_sequence<
121 : BufferSequence>::value,
122 : "Type requirements not met");
123 :
124 280468 : auto const n0 = buffer_size(b);
125 280468 : if(n < n0)
126 560868 : return tag_invoke(
127 280434 : suffix_tag{}, b, n0 - n);
128 68 : return tag_invoke(
129 34 : suffix_tag{}, b, 0);
130 : }
131 : };
132 :
133 : struct front_impl
134 : {
135 : template<
136 : class MutableBufferSequence
137 : , class = typename std::enable_if<
138 : is_mutable_buffer_sequence<
139 : MutableBufferSequence>::value
140 : >::type>
141 : mutable_buffer
142 : operator()(
143 : MutableBufferSequence const& bs) const noexcept
144 : {
145 : auto const it = begin(bs);
146 : if(it != end(bs))
147 : return *it;
148 : return {};
149 : }
150 :
151 : template<
152 : class ConstBufferSequence
153 : , class = typename std::enable_if<
154 : ! is_mutable_buffer_sequence<
155 : ConstBufferSequence>::value
156 : >::type>
157 : const_buffer
158 : operator()(
159 : ConstBufferSequence const& bs) const noexcept
160 : {
161 : static_assert(
162 : is_const_buffer_sequence<
163 : ConstBufferSequence>::value,
164 : "Type requirements not met");
165 :
166 : auto const it = bs.begin();
167 : if(it != bs.end())
168 : return *it;
169 : return {};
170 : }
171 : };
172 :
173 : } // detail
174 :
175 : /** Return a prefix of the buffer sequence.
176 : */
177 : constexpr detail::prefix_impl prefix{};
178 :
179 : /** Return a suffix of the buffer sequence.
180 : */
181 : constexpr detail::suffix_impl suffix{};
182 :
183 : /** Return a suffix of the buffer sequence.
184 : */
185 : constexpr detail::sans_prefix_impl sans_prefix{};
186 :
187 : /** Return a prefix of the buffer sequence.
188 : */
189 : constexpr detail::sans_suffix_impl sans_suffix{};
190 :
191 : /** Return the first buffer in a sequence.
192 : */
193 : constexpr detail::front_impl front{};
194 :
195 : } // buffers
196 : } // boost
197 :
198 : #endif
|