]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // Copyright (c) 2016-2017 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_IPP | |
11 | #define BOOST_BEAST_IMPL_BUFFERS_PREFIX_IPP | |
12 | ||
13 | #include <algorithm> | |
14 | #include <cstdint> | |
15 | #include <iterator> | |
16 | #include <stdexcept> | |
17 | #include <type_traits> | |
18 | #include <utility> | |
19 | ||
20 | namespace boost { | |
21 | namespace beast { | |
22 | ||
23 | namespace detail { | |
24 | ||
25 | inline | |
26 | boost::asio::const_buffer | |
27 | buffers_prefix(std::size_t size, | |
28 | boost::asio::const_buffer buffer) | |
29 | { | |
30 | return {buffer.data(), | |
31 | (std::min)(size, buffer.size())}; | |
32 | } | |
33 | ||
34 | inline | |
35 | boost::asio::mutable_buffer | |
36 | buffers_prefix(std::size_t size, | |
37 | boost::asio::mutable_buffer buffer) | |
38 | { | |
39 | return {buffer.data(), | |
40 | (std::min)(size, buffer.size())}; | |
41 | } | |
42 | ||
43 | } // detail | |
44 | ||
45 | template<class BufferSequence> | |
46 | class buffers_prefix_view<BufferSequence>::const_iterator | |
47 | { | |
48 | friend class buffers_prefix_view<BufferSequence>; | |
49 | ||
50 | buffers_prefix_view const* b_ = nullptr; | |
51 | std::size_t remain_; | |
52 | iter_type it_; | |
53 | ||
54 | public: | |
55 | using value_type = typename std::conditional< | |
11fdf7f2 | 56 | boost::is_convertible<typename |
b32b8144 FG |
57 | std::iterator_traits<iter_type>::value_type, |
58 | boost::asio::mutable_buffer>::value, | |
59 | boost::asio::mutable_buffer, | |
60 | boost::asio::const_buffer>::type; | |
61 | using pointer = value_type const*; | |
62 | using reference = value_type; | |
63 | using difference_type = std::ptrdiff_t; | |
64 | using iterator_category = | |
65 | std::bidirectional_iterator_tag; | |
66 | ||
67 | const_iterator() = default; | |
68 | const_iterator(const_iterator&& other) = default; | |
69 | const_iterator(const_iterator const& other) = default; | |
70 | const_iterator& operator=(const_iterator&& other) = default; | |
71 | const_iterator& operator=(const_iterator const& other) = default; | |
72 | ||
73 | bool | |
74 | operator==(const_iterator const& other) const | |
75 | { | |
76 | return b_ == other.b_ && it_ == other.it_; | |
77 | } | |
78 | ||
79 | bool | |
80 | operator!=(const_iterator const& other) const | |
81 | { | |
82 | return !(*this == other); | |
83 | } | |
84 | ||
85 | reference | |
86 | operator*() const | |
87 | { | |
88 | return detail::buffers_prefix(remain_, *it_); | |
89 | } | |
90 | ||
91 | pointer | |
92 | operator->() const = delete; | |
93 | ||
94 | const_iterator& | |
95 | operator++() | |
96 | { | |
97 | remain_ -= boost::asio::buffer_size(*it_++); | |
98 | return *this; | |
99 | } | |
100 | ||
101 | const_iterator | |
102 | operator++(int) | |
103 | { | |
104 | auto temp = *this; | |
105 | remain_ -= boost::asio::buffer_size(*it_++); | |
106 | return temp; | |
107 | } | |
108 | ||
109 | const_iterator& | |
110 | operator--() | |
111 | { | |
112 | remain_ += boost::asio::buffer_size(*--it_); | |
113 | return *this; | |
114 | } | |
115 | ||
116 | const_iterator | |
117 | operator--(int) | |
118 | { | |
119 | auto temp = *this; | |
120 | remain_ += boost::asio::buffer_size(*--it_); | |
121 | return temp; | |
122 | } | |
123 | ||
124 | private: | |
125 | const_iterator(buffers_prefix_view const& b, | |
126 | std::true_type) | |
127 | : b_(&b) | |
128 | , remain_(0) | |
129 | , it_(b_->end_) | |
130 | { | |
131 | } | |
132 | ||
133 | const_iterator(buffers_prefix_view const& b, | |
134 | std::false_type) | |
135 | : b_(&b) | |
136 | , remain_(b_->size_) | |
137 | , it_(boost::asio::buffer_sequence_begin(b_->bs_)) | |
138 | { | |
139 | } | |
140 | }; | |
141 | ||
142 | template<class BufferSequence> | |
143 | void | |
144 | buffers_prefix_view<BufferSequence>:: | |
145 | setup(std::size_t size) | |
146 | { | |
147 | size_ = 0; | |
148 | end_ = boost::asio::buffer_sequence_begin(bs_); | |
149 | auto const last = bs_.end(); | |
150 | while(end_ != last) | |
151 | { | |
152 | auto const len = | |
153 | boost::asio::buffer_size(*end_++); | |
154 | if(len >= size) | |
155 | { | |
156 | size_ += size; | |
157 | break; | |
158 | } | |
159 | size -= len; | |
160 | size_ += len; | |
161 | } | |
162 | } | |
163 | ||
164 | template<class BufferSequence> | |
165 | buffers_prefix_view<BufferSequence>:: | |
166 | buffers_prefix_view(buffers_prefix_view&& other) | |
167 | : buffers_prefix_view(std::move(other), | |
168 | std::distance<iter_type>( | |
169 | boost::asio::buffer_sequence_begin(other.bs_), | |
170 | other.end_)) | |
171 | { | |
172 | } | |
173 | ||
174 | template<class BufferSequence> | |
175 | buffers_prefix_view<BufferSequence>:: | |
176 | buffers_prefix_view(buffers_prefix_view const& other) | |
177 | : buffers_prefix_view(other, | |
178 | std::distance<iter_type>( | |
179 | boost::asio::buffer_sequence_begin(other.bs_), | |
180 | other.end_)) | |
181 | { | |
182 | } | |
183 | ||
184 | template<class BufferSequence> | |
185 | auto | |
186 | buffers_prefix_view<BufferSequence>:: | |
187 | operator=(buffers_prefix_view&& other) -> | |
188 | buffers_prefix_view& | |
189 | { | |
190 | auto const dist = std::distance<iter_type>( | |
191 | boost::asio::buffer_sequence_begin(other.bs_), | |
192 | other.end_); | |
193 | bs_ = std::move(other.bs_); | |
194 | size_ = other.size_; | |
195 | end_ = std::next( | |
196 | boost::asio::buffer_sequence_begin(bs_), | |
197 | dist); | |
198 | return *this; | |
199 | } | |
200 | ||
201 | template<class BufferSequence> | |
202 | auto | |
203 | buffers_prefix_view<BufferSequence>:: | |
204 | operator=(buffers_prefix_view const& other) -> | |
205 | buffers_prefix_view& | |
206 | { | |
207 | auto const dist = std::distance<iter_type>( | |
208 | boost::asio::buffer_sequence_begin(other.bs_), | |
209 | other.end_); | |
210 | bs_ = other.bs_; | |
211 | size_ = other.size_; | |
212 | end_ = std::next( | |
213 | boost::asio::buffer_sequence_begin(bs_), | |
214 | dist); | |
215 | return *this; | |
216 | } | |
217 | ||
218 | template<class BufferSequence> | |
219 | buffers_prefix_view<BufferSequence>:: | |
220 | buffers_prefix_view(std::size_t size, | |
221 | BufferSequence const& bs) | |
222 | : bs_(bs) | |
223 | { | |
224 | setup(size); | |
225 | } | |
226 | ||
227 | template<class BufferSequence> | |
228 | template<class... Args> | |
229 | buffers_prefix_view<BufferSequence>:: | |
230 | buffers_prefix_view(std::size_t size, | |
231 | boost::in_place_init_t, Args&&... args) | |
232 | : bs_(std::forward<Args>(args)...) | |
233 | { | |
234 | setup(size); | |
235 | } | |
236 | ||
237 | template<class BufferSequence> | |
238 | inline | |
239 | auto | |
240 | buffers_prefix_view<BufferSequence>::begin() const -> | |
241 | const_iterator | |
242 | { | |
243 | return const_iterator{*this, std::false_type{}}; | |
244 | } | |
245 | ||
246 | template<class BufferSequence> | |
247 | inline | |
248 | auto | |
249 | buffers_prefix_view<BufferSequence>::end() const -> | |
250 | const_iterator | |
251 | { | |
252 | return const_iterator{*this, std::true_type{}}; | |
253 | } | |
254 | ||
255 | } // beast | |
256 | } // boost | |
257 | ||
258 | #endif |