]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-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 | ||
8 | #ifndef BEAST_IMPL_CONSUMING_BUFFERS_IPP | |
9 | #define BEAST_IMPL_CONSUMING_BUFFERS_IPP | |
10 | ||
11 | #include <beast/core/buffer_concepts.hpp> | |
12 | #include <boost/asio/buffer.hpp> | |
13 | #include <algorithm> | |
14 | #include <cstdint> | |
15 | #include <iterator> | |
16 | #include <type_traits> | |
17 | #include <utility> | |
18 | ||
19 | namespace beast { | |
20 | ||
21 | template<class BufferSequence> | |
22 | class consuming_buffers<BufferSequence>::const_iterator | |
23 | { | |
24 | friend class consuming_buffers<BufferSequence>; | |
25 | ||
26 | using iter_type = | |
27 | typename BufferSequence::const_iterator; | |
28 | ||
29 | iter_type it_; | |
30 | consuming_buffers const* b_ = nullptr; | |
31 | ||
32 | public: | |
33 | using value_type = typename std::conditional< | |
34 | std::is_convertible<typename | |
35 | std::iterator_traits<iter_type>::value_type, | |
36 | boost::asio::mutable_buffer>::value, | |
37 | boost::asio::mutable_buffer, | |
38 | boost::asio::const_buffer>::type; | |
39 | using pointer = value_type const*; | |
40 | using reference = value_type; | |
41 | using difference_type = std::ptrdiff_t; | |
42 | using iterator_category = | |
43 | std::bidirectional_iterator_tag; | |
44 | ||
45 | const_iterator() = default; | |
46 | const_iterator(const_iterator&& other) = default; | |
47 | const_iterator(const_iterator const& other) = default; | |
48 | const_iterator& operator=(const_iterator&& other) = default; | |
49 | const_iterator& operator=(const_iterator const& other) = default; | |
50 | ||
51 | bool | |
52 | operator==(const_iterator const& other) const | |
53 | { | |
54 | return b_ == other.b_ && it_ == other.it_; | |
55 | } | |
56 | ||
57 | bool | |
58 | operator!=(const_iterator const& other) const | |
59 | { | |
60 | return !(*this == other); | |
61 | } | |
62 | ||
63 | reference | |
64 | operator*() const | |
65 | { | |
66 | return it_ == b_->begin_ | |
67 | ? value_type{*it_} + b_->skip_ | |
68 | : *it_; | |
69 | } | |
70 | ||
71 | pointer | |
72 | operator->() const = delete; | |
73 | ||
74 | const_iterator& | |
75 | operator++() | |
76 | { | |
77 | ++it_; | |
78 | return *this; | |
79 | } | |
80 | ||
81 | const_iterator | |
82 | operator++(int) | |
83 | { | |
84 | auto temp = *this; | |
85 | ++(*this); | |
86 | return temp; | |
87 | } | |
88 | ||
89 | const_iterator& | |
90 | operator--() | |
91 | { | |
92 | --it_; | |
93 | return *this; | |
94 | } | |
95 | ||
96 | const_iterator | |
97 | operator--(int) | |
98 | { | |
99 | auto temp = *this; | |
100 | --(*this); | |
101 | return temp; | |
102 | } | |
103 | ||
104 | private: | |
105 | const_iterator(consuming_buffers const& b, | |
106 | iter_type it) | |
107 | : it_(it) | |
108 | , b_(&b) | |
109 | { | |
110 | } | |
111 | }; | |
112 | ||
113 | template<class BufferSequence> | |
114 | consuming_buffers<BufferSequence>:: | |
115 | consuming_buffers(consuming_buffers&& other) | |
116 | : consuming_buffers(std::move(other), | |
117 | std::distance<iter_type>( | |
118 | other.bs_.begin(), other.begin_)) | |
119 | { | |
120 | } | |
121 | ||
122 | template<class BufferSequence> | |
123 | consuming_buffers<BufferSequence>:: | |
124 | consuming_buffers(consuming_buffers const& other) | |
125 | : consuming_buffers(other, | |
126 | std::distance<iter_type>( | |
127 | other.bs_.begin(), other.begin_)) | |
128 | { | |
129 | } | |
130 | ||
131 | template<class BufferSequence> | |
132 | auto | |
133 | consuming_buffers<BufferSequence>:: | |
134 | operator=(consuming_buffers&& other) -> | |
135 | consuming_buffers& | |
136 | { | |
137 | auto const nbegin = std::distance<iter_type>( | |
138 | other.bs_.begin(), other.begin_); | |
139 | bs_ = std::move(other.bs_); | |
140 | begin_ = std::next(bs_.begin(), nbegin); | |
141 | skip_ = other.skip_; | |
142 | return *this; | |
143 | } | |
144 | ||
145 | template<class BufferSequence> | |
146 | auto | |
147 | consuming_buffers<BufferSequence>:: | |
148 | operator=(consuming_buffers const& other) -> | |
149 | consuming_buffers& | |
150 | { | |
151 | auto const nbegin = std::distance<iter_type>( | |
152 | other.bs_.begin(), other.begin_); | |
153 | bs_ = other.bs_; | |
154 | begin_ = std::next(bs_.begin(), nbegin); | |
155 | skip_ = other.skip_; | |
156 | return *this; | |
157 | } | |
158 | ||
159 | template<class BufferSequence> | |
160 | consuming_buffers<BufferSequence>:: | |
161 | consuming_buffers(BufferSequence const& bs) | |
162 | : bs_(bs) | |
163 | , begin_(bs_.begin()) | |
164 | { | |
165 | static_assert( | |
166 | is_BufferSequence<BufferSequence, value_type>::value, | |
167 | "BufferSequence requirements not met"); | |
168 | } | |
169 | ||
170 | template<class BufferSequence> | |
171 | inline | |
172 | auto | |
173 | consuming_buffers<BufferSequence>:: | |
174 | begin() const -> | |
175 | const_iterator | |
176 | { | |
177 | return const_iterator{*this, begin_}; | |
178 | } | |
179 | ||
180 | template<class BufferSequence> | |
181 | inline | |
182 | auto | |
183 | consuming_buffers<BufferSequence>:: | |
184 | end() const -> | |
185 | const_iterator | |
186 | { | |
187 | return const_iterator{*this, bs_.end()}; | |
188 | } | |
189 | ||
190 | template<class BufferSequence> | |
191 | void | |
192 | consuming_buffers<BufferSequence>:: | |
193 | consume(std::size_t n) | |
194 | { | |
195 | using boost::asio::buffer_size; | |
196 | for(;n > 0 && begin_ != bs_.end(); ++begin_) | |
197 | { | |
198 | auto const len = | |
199 | buffer_size(*begin_) - skip_; | |
200 | if(n < len) | |
201 | { | |
202 | skip_ += n; | |
203 | break; | |
204 | } | |
205 | n -= len; | |
206 | skip_ = 0; | |
207 | } | |
208 | } | |
209 | ||
210 | } // beast | |
211 | ||
212 | #endif |