Line | Branch | Exec | Source |
---|---|---|---|
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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1786 times.
|
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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1154 times.
|
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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
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 | ||
430 |