Line data Source code
1 : //
2 : // Copyright (c) 2021 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/http_proto
8 : //
9 :
10 : #ifndef BOOST_HTTP_PROTO_IMPL_FIELDS_BASE_HPP
11 : #define BOOST_HTTP_PROTO_IMPL_FIELDS_BASE_HPP
12 :
13 : #include <boost/core/detail/string_view.hpp>
14 : #include <boost/assert.hpp>
15 :
16 : namespace boost {
17 : namespace http_proto {
18 :
19 : //------------------------------------------------
20 : //
21 : // iterator
22 : //
23 : //------------------------------------------------
24 :
25 : class fields_base::iterator
26 : {
27 : detail::header const* ph_ = nullptr;
28 : std::size_t i_ = 0;
29 :
30 : friend class fields_base;
31 :
32 1579 : iterator(
33 : detail::header const* ph,
34 : std::size_t i) noexcept
35 1579 : : ph_(ph)
36 1579 : , i_(i)
37 : {
38 1579 : }
39 :
40 : public:
41 : using value_type =
42 : fields_base::value_type;
43 : using reference =
44 : fields_base::reference;
45 : using pointer = reference;
46 : using difference_type =
47 : std::ptrdiff_t;
48 : using iterator_category =
49 : std::bidirectional_iterator_tag;
50 :
51 2 : iterator() = default;
52 : iterator(iterator const&) = default;
53 : iterator& operator=(
54 : iterator const&) = default;
55 :
56 : bool
57 1786 : operator==(
58 : iterator const& other) const noexcept
59 : {
60 : // If this assert goes off, it means you
61 : // are trying to compare iterators from
62 : // different containers, which is undefined!
63 1786 : BOOST_ASSERT(ph_ == other.ph_);
64 :
65 1786 : return i_ == other.i_;
66 : }
67 :
68 : bool
69 1721 : operator!=(
70 : iterator const& other) const noexcept
71 : {
72 1721 : return !(*this == other);
73 : }
74 :
75 : BOOST_HTTP_PROTO_DECL
76 : reference
77 : operator*() const noexcept;
78 :
79 : pointer
80 1707 : operator->() const noexcept
81 : {
82 1707 : return *(*this);
83 : }
84 :
85 : iterator&
86 1154 : operator++() noexcept
87 : {
88 1154 : BOOST_ASSERT(i_ < ph_->count);
89 1154 : ++i_;
90 1154 : return *this;
91 : }
92 :
93 : iterator
94 1 : operator++(int) noexcept
95 : {
96 1 : auto temp = *this;
97 1 : ++(*this);
98 1 : return temp;
99 : }
100 :
101 : iterator&
102 25 : operator--() noexcept
103 : {
104 25 : BOOST_ASSERT(i_ > 0);
105 25 : --i_;
106 25 : return *this;
107 : }
108 :
109 : iterator
110 1 : operator--(int) noexcept
111 : {
112 1 : auto temp = *this;
113 1 : --(*this);
114 1 : return temp;
115 : }
116 : };
117 :
118 : //------------------------------------------------
119 :
120 : class fields_base::reverse_iterator
121 : {
122 : detail::header const* ph_ = nullptr;
123 : std::size_t i_ = 0;
124 :
125 : friend class fields_base;
126 :
127 : reverse_iterator(
128 : detail::header const* ph,
129 : std::size_t i) noexcept
130 : : ph_(ph)
131 : , i_(i)
132 : {
133 : }
134 :
135 : public:
136 : using value_type =
137 : fields_base::value_type;
138 : using reference =
139 : fields_base::reference;
140 : using pointer = reference;
141 : using difference_type =
142 : std::ptrdiff_t;
143 : using iterator_category =
144 : std::bidirectional_iterator_tag;
145 :
146 2 : reverse_iterator() = default;
147 : reverse_iterator(reverse_iterator const&) = default;
148 : reverse_iterator& operator=(
149 : reverse_iterator const&) = default;
150 :
151 : explicit
152 5 : reverse_iterator(
153 : iterator it) noexcept
154 5 : : ph_(it.ph_)
155 5 : , i_(it.i_)
156 : {
157 5 : }
158 :
159 : bool
160 5 : operator==(
161 : reverse_iterator const& other) const noexcept
162 : {
163 : // If this assert goes off, it means you
164 : // are trying to compare iterators from
165 : // different containers, which is undefined!
166 5 : BOOST_ASSERT(ph_ == other.ph_);
167 :
168 5 : return i_ == other.i_;
169 : }
170 :
171 : bool
172 1 : operator!=(
173 : reverse_iterator const& other) const noexcept
174 : {
175 1 : return !(*this == other);
176 : }
177 :
178 : BOOST_HTTP_PROTO_DECL
179 : reference
180 : operator*() const noexcept;
181 :
182 : pointer
183 24 : operator->() const noexcept
184 : {
185 24 : return *(*this);
186 : }
187 :
188 : reverse_iterator&
189 3 : operator++() noexcept
190 : {
191 3 : BOOST_ASSERT(i_ > 0);
192 3 : --i_;
193 3 : return *this;
194 : }
195 :
196 : reverse_iterator
197 1 : operator++(int) noexcept
198 : {
199 1 : auto temp = *this;
200 1 : ++(*this);
201 1 : return temp;
202 : }
203 :
204 : reverse_iterator&
205 3 : operator--() noexcept
206 : {
207 3 : BOOST_ASSERT(i_ < ph_->count);
208 3 : ++i_;
209 3 : return *this;
210 : }
211 :
212 : reverse_iterator
213 1 : operator--(int) noexcept
214 : {
215 1 : auto temp = *this;
216 1 : --(*this);
217 1 : return temp;
218 : }
219 : };
220 :
221 : //------------------------------------------------
222 : //
223 : // subrange
224 : //
225 : //------------------------------------------------
226 :
227 : class fields_base::subrange
228 : {
229 : detail::header const* ph_ = nullptr;
230 : std::size_t i_ = 0;
231 :
232 : friend class fields_base;
233 : friend struct detail::header;
234 :
235 21 : subrange(
236 : detail::header const* ph,
237 : std::size_t i) noexcept
238 21 : : ph_(ph)
239 21 : , i_(i)
240 : {
241 21 : }
242 :
243 : public:
244 : class iterator;
245 : //class reverse_iterator;
246 : using const_iterator = iterator;
247 : using value_type = std::string;
248 : using reference = core::string_view;
249 : using const_reference = reference;
250 : using size_type = std::size_t;
251 : using difference_type = std::ptrdiff_t;
252 :
253 : /** Constructor
254 :
255 : Default-constructed subranges are empty.
256 : */
257 : subrange() noexcept = default;
258 :
259 : subrange(subrange const&) noexcept = default;
260 : subrange& operator=(
261 : subrange const&) noexcept = default;
262 :
263 : iterator begin() const noexcept;
264 : iterator end() const noexcept;
265 : };
266 :
267 : //------------------------------------------------
268 : //
269 : // subrange::iterator
270 : //
271 : //------------------------------------------------
272 :
273 : class fields_base::subrange::
274 : iterator
275 : {
276 : detail::header const* ph_ = nullptr;
277 : std::size_t i_ = 0;
278 :
279 : friend class fields_base::subrange;
280 :
281 : BOOST_HTTP_PROTO_DECL
282 : iterator(
283 : detail::header const* ph,
284 : std::size_t i) noexcept;
285 :
286 : // end
287 : BOOST_HTTP_PROTO_DECL
288 : iterator(
289 : detail::header const* ph) noexcept;
290 :
291 : public:
292 : using value_type = std::string;
293 : using reference = core::string_view;
294 : using pointer = void const*;
295 : using difference_type =
296 : std::ptrdiff_t;
297 : using iterator_category =
298 : std::forward_iterator_tag;
299 :
300 : iterator() = default;
301 : iterator(iterator const&) = default;
302 : iterator& operator=(
303 : iterator const&) = default;
304 :
305 : // conversion to regular iterator
306 : operator
307 : fields_base::
308 : iterator() const noexcept
309 : {
310 : return {ph_, i_};
311 : }
312 :
313 : bool
314 48 : operator==(
315 : iterator const& other) const noexcept
316 : {
317 : // If this assert goes off, it means you
318 : // are trying to compare iterators from
319 : // different containers, which is undefined!
320 48 : BOOST_ASSERT(ph_ == other.ph_);
321 :
322 48 : return i_ == other.i_;
323 : }
324 :
325 : bool
326 48 : operator!=(
327 : iterator const& other) const noexcept
328 : {
329 48 : return !(*this == other);
330 : }
331 :
332 : BOOST_HTTP_PROTO_DECL
333 : reference const
334 : operator*() const noexcept;
335 :
336 : reference const
337 : operator->() const noexcept
338 : {
339 : return *(*this);
340 : }
341 :
342 : BOOST_HTTP_PROTO_DECL
343 : iterator&
344 : operator++() noexcept;
345 :
346 : iterator
347 : operator++(int) noexcept
348 : {
349 : auto temp = *this;
350 : ++(*this);
351 : return temp;
352 : }
353 : };
354 :
355 : inline
356 : auto
357 21 : fields_base::
358 : subrange::
359 : begin() const noexcept ->
360 : iterator
361 : {
362 21 : return {ph_, i_};
363 : }
364 :
365 : inline
366 : auto
367 21 : fields_base::
368 : subrange::
369 : end() const noexcept ->
370 : iterator
371 : {
372 21 : return {ph_};
373 : }
374 :
375 : //------------------------------------------------
376 :
377 : inline
378 : fields_base::
379 : value_type::
380 : operator
381 : fields_base::
382 : reference() const noexcept
383 : {
384 : return reference{
385 : id, name, value};
386 : }
387 :
388 : //------------------------------------------------
389 :
390 : inline
391 : auto
392 721 : fields_base::
393 : begin() const noexcept ->
394 : iterator
395 : {
396 721 : return iterator(&h_, 0);
397 : }
398 :
399 : inline
400 : auto
401 858 : fields_base::
402 : end() const noexcept ->
403 : iterator
404 : {
405 858 : return iterator(&h_, h_.count);
406 : }
407 :
408 : inline
409 : auto
410 3 : fields_base::
411 : rbegin() const noexcept ->
412 : reverse_iterator
413 : {
414 3 : return reverse_iterator(end());
415 : }
416 :
417 : inline
418 : auto
419 2 : fields_base::
420 : rend() const noexcept ->
421 : reverse_iterator
422 : {
423 2 : return reverse_iterator(begin());
424 : }
425 :
426 : } // http_proto
427 : } // boost
428 :
429 : #endif
|