1//
2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/boostorg/beast
8//
9
10#ifndef BOOST_BEAST_IMPL_BUFFERS_PREFIX_HPP
11#define BOOST_BEAST_IMPL_BUFFERS_PREFIX_HPP
12
13#include <boost/beast/core/buffer_traits.hpp>
14#include <boost/config/workaround.hpp>
15#include <algorithm>
16#include <cstdint>
17#include <iterator>
18#include <stdexcept>
19#include <type_traits>
20#include <utility>
21
22namespace boost {
23namespace beast {
24
25template<class Buffers>
26class buffers_prefix_view<Buffers>::const_iterator
27{
28 friend class buffers_prefix_view<Buffers>;
29
30 buffers_prefix_view const* b_ = nullptr;
31 std::size_t remain_ = 0;
32 iter_type it_{};
33
34public:
35#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
36 using value_type = typename std::conditional<
37 boost::is_convertible<typename
38 std::iterator_traits<iter_type>::value_type,
39 net::mutable_buffer>::value,
40 net::mutable_buffer,
41 net::const_buffer>::type;
42#else
43 using value_type = buffers_type<Buffers>;
44#endif
45
46 BOOST_STATIC_ASSERT(std::is_same<
47 typename const_iterator::value_type,
48 typename buffers_prefix_view::value_type>::value);
49
50 using pointer = value_type const*;
51 using reference = value_type;
52 using difference_type = std::ptrdiff_t;
53 using iterator_category =
54 std::bidirectional_iterator_tag;
55
56 const_iterator() = default;
57 const_iterator(
58 const_iterator const& other) = default;
59 const_iterator& operator=(
60 const_iterator const& other) = default;
61
62 bool
63 operator==(const_iterator const& other) const
64 {
65 return b_ == other.b_ && it_ == other.it_;
66 }
67
68 bool
69 operator!=(const_iterator const& other) const
70 {
71 return !(*this == other);
72 }
73
74 reference
75 operator*() const
76 {
77 value_type v(*it_);
78 if(remain_ < v.size())
79 return {v.data(), remain_};
80 return v;
81 }
82
83 pointer
84 operator->() const = delete;
85
86 const_iterator&
87 operator++()
88 {
89 value_type const v = *it_++;
90 remain_ -= v.size();
91 return *this;
92 }
93
94 const_iterator
95 operator++(int)
96 {
97 auto temp = *this;
98 value_type const v = *it_++;
99 remain_ -= v.size();
100 return temp;
101 }
102
103 const_iterator&
104 operator--()
105 {
106 value_type const v = *--it_;
107 remain_ += v.size();
108 return *this;
109 }
110
111 const_iterator
112 operator--(int)
113 {
114 auto temp = *this;
115 value_type const v = *--it_;
116 remain_ += v.size();
117 return temp;
118 }
119
120private:
121 const_iterator(
122 buffers_prefix_view const& b,
123 std::true_type)
124 : b_(&b)
125 , remain_(b.remain_)
126 , it_(b_->end_)
127 {
128 }
129
130 const_iterator(
131 buffers_prefix_view const& b,
132 std::false_type)
133 : b_(&b)
134 , remain_(b_->size_)
135 , it_(net::buffer_sequence_begin(b_->bs_))
136 {
137 }
138};
139
140//------------------------------------------------------------------------------
141
142template<class Buffers>
143void
144buffers_prefix_view<Buffers>::
145setup(std::size_t size)
146{
147 size_ = 0;
148 remain_ = 0;
149 end_ = net::buffer_sequence_begin(bs_);
150 auto const last = bs_.end();
151 while(end_ != last)
152 {
153 auto const len = buffer_bytes(*end_++);
154 if(len >= size)
155 {
156 size_ += size;
157
158 // by design, this subtraction can wrap
159 BOOST_STATIC_ASSERT(std::is_unsigned<
160 decltype(remain_)>::value);
161 remain_ = size - len;
162 break;
163 }
164 size -= len;
165 size_ += len;
166 }
167}
168
169template<class Buffers>
170buffers_prefix_view<Buffers>::
171buffers_prefix_view(
172 buffers_prefix_view const& other,
173 std::size_t dist)
174 : bs_(other.bs_)
175 , size_(other.size_)
176 , remain_(other.remain_)
177 , end_(std::next(bs_.begin(), dist))
178{
179}
180
181template<class Buffers>
182buffers_prefix_view<Buffers>::
183buffers_prefix_view(buffers_prefix_view const& other)
184 : buffers_prefix_view(other,
185 std::distance<iter_type>(
186 net::buffer_sequence_begin(other.bs_),
187 other.end_))
188{
189}
190
191template<class Buffers>
192auto
193buffers_prefix_view<Buffers>::
194operator=(buffers_prefix_view const& other) ->
195 buffers_prefix_view&
196{
197 auto const dist = std::distance<iter_type>(
198 net::buffer_sequence_begin(other.bs_),
199 other.end_);
200 bs_ = other.bs_;
201 size_ = other.size_;
202 remain_ = other.remain_;
203 end_ = std::next(
204 net::buffer_sequence_begin(bs_),
205 dist);
206 return *this;
207}
208
209template<class Buffers>
210buffers_prefix_view<Buffers>::
211buffers_prefix_view(
212 std::size_t size,
213 Buffers const& bs)
214 : bs_(bs)
215{
216 setup(size);
217}
218
219template<class Buffers>
220template<class... Args>
221buffers_prefix_view<Buffers>::
222buffers_prefix_view(
223 std::size_t size,
224 boost::in_place_init_t,
225 Args&&... args)
226 : bs_(std::forward<Args>(args)...)
227{
228 setup(size);
229}
230
231template<class Buffers>
232auto
233buffers_prefix_view<Buffers>::
234begin() const ->
235 const_iterator
236{
237 return const_iterator{
238 *this, std::false_type{}};
239}
240
241template<class Buffers>
242auto
243buffers_prefix_view<Buffers>::
244end() const ->
245 const_iterator
246{
247 return const_iterator{
248 *this, std::true_type{}};
249}
250
251//------------------------------------------------------------------------------
252
253template<>
254class buffers_prefix_view<net::const_buffer>
255 : public net::const_buffer
256{
257public:
258 using net::const_buffer::const_buffer;
259 buffers_prefix_view(buffers_prefix_view const&) = default;
260 buffers_prefix_view& operator=(buffers_prefix_view const&) = default;
261
262 buffers_prefix_view(
263 std::size_t size,
264 net::const_buffer buffer)
265 : net::const_buffer(
266 buffer.data(),
267 std::min<std::size_t>(a: size, b: buffer.size())
268 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
269 , buffer.get_debug_check()
270 #endif
271 )
272 {
273 }
274
275 template<class... Args>
276 buffers_prefix_view(
277 std::size_t size,
278 boost::in_place_init_t,
279 Args&&... args)
280 : buffers_prefix_view(size,
281 net::const_buffer(
282 std::forward<Args>(args)...))
283 {
284 }
285};
286
287//------------------------------------------------------------------------------
288
289template<>
290class buffers_prefix_view<net::mutable_buffer>
291 : public net::mutable_buffer
292{
293public:
294 using net::mutable_buffer::mutable_buffer;
295 buffers_prefix_view(buffers_prefix_view const&) = default;
296 buffers_prefix_view& operator=(buffers_prefix_view const&) = default;
297
298 buffers_prefix_view(
299 std::size_t size,
300 net::mutable_buffer buffer)
301 : net::mutable_buffer(
302 buffer.data(),
303 std::min<std::size_t>(a: size, b: buffer.size())
304 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
305 , buffer.get_debug_check()
306 #endif
307 )
308 {
309 }
310
311 template<class... Args>
312 buffers_prefix_view(
313 std::size_t size,
314 boost::in_place_init_t,
315 Args&&... args)
316 : buffers_prefix_view(size,
317 net::mutable_buffer(
318 std::forward<Args>(args)...))
319 {
320 }
321};
322
323} // beast
324} // boost
325
326#endif
327

source code of boost/libs/beast/include/boost/beast/core/impl/buffers_prefix.hpp