1  
//
1  
//
2  
// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/http
7  
// Official repository: https://github.com/cppalliance/http
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_HTTP_IMPL_FIELDS_BASE_HPP
10  
#ifndef BOOST_HTTP_IMPL_FIELDS_BASE_HPP
11  
#define BOOST_HTTP_IMPL_FIELDS_BASE_HPP
11  
#define BOOST_HTTP_IMPL_FIELDS_BASE_HPP
12  

12  

13  
#include <boost/core/detail/string_view.hpp>
13  
#include <boost/core/detail/string_view.hpp>
14  
#include <boost/assert.hpp>
14  
#include <boost/assert.hpp>
15  

15  

16  
namespace boost {
16  
namespace boost {
17  
namespace http {
17  
namespace http {
18  

18  

19  
//------------------------------------------------
19  
//------------------------------------------------
20  
//
20  
//
21  
// iterator
21  
// iterator
22  
//
22  
//
23  
//------------------------------------------------
23  
//------------------------------------------------
24  

24  

25  
class fields_base::iterator
25  
class fields_base::iterator
26  
{
26  
{
27  
    detail::header const* ph_ = nullptr;
27  
    detail::header const* ph_ = nullptr;
28  
    std::size_t i_ = 0;
28  
    std::size_t i_ = 0;
29  

29  

30  
    friend class fields_base;
30  
    friend class fields_base;
31  

31  

32  
    iterator(
32  
    iterator(
33  
        detail::header const* ph,
33  
        detail::header const* ph,
34  
        std::size_t i) noexcept
34  
        std::size_t i) noexcept
35  
        : ph_(ph)
35  
        : ph_(ph)
36  
        , i_(i)
36  
        , i_(i)
37  
    {
37  
    {
38  
    }
38  
    }
39  

39  

40  
public:
40  
public:
41  
    using value_type =
41  
    using value_type =
42  
        fields_base::value_type;
42  
        fields_base::value_type;
43  
    using reference =
43  
    using reference =
44  
        fields_base::reference;
44  
        fields_base::reference;
45  
    using pointer = reference;
45  
    using pointer = reference;
46  
    using difference_type =
46  
    using difference_type =
47  
        std::ptrdiff_t;
47  
        std::ptrdiff_t;
48  
    using iterator_category =
48  
    using iterator_category =
49  
        std::bidirectional_iterator_tag;
49  
        std::bidirectional_iterator_tag;
50  

50  

51  
    iterator() = default;
51  
    iterator() = default;
52  
    iterator(iterator const&) = default;
52  
    iterator(iterator const&) = default;
53  
    iterator& operator=(
53  
    iterator& operator=(
54  
        iterator const&) = default;
54  
        iterator const&) = default;
55  

55  

56  
    bool
56  
    bool
57  
    operator==(
57  
    operator==(
58  
        iterator const& other) const noexcept
58  
        iterator const& other) const noexcept
59  
    {
59  
    {
60  
        // If this assert goes off, it means you
60  
        // If this assert goes off, it means you
61  
        // are trying to compare iterators from
61  
        // are trying to compare iterators from
62  
        // different containers, which is undefined!
62  
        // different containers, which is undefined!
63  
        BOOST_ASSERT(ph_ == other.ph_);
63  
        BOOST_ASSERT(ph_ == other.ph_);
64  

64  

65  
        return i_ == other.i_;
65  
        return i_ == other.i_;
66  
    }
66  
    }
67  

67  

68  
    bool
68  
    bool
69  
    operator!=(
69  
    operator!=(
70  
        iterator const& other) const noexcept
70  
        iterator const& other) const noexcept
71  
    {
71  
    {
72  
        return !(*this == other);
72  
        return !(*this == other);
73  
    }
73  
    }
74  

74  

75  
    BOOST_HTTP_DECL
75  
    BOOST_HTTP_DECL
76  
    reference
76  
    reference
77  
    operator*() const noexcept;
77  
    operator*() const noexcept;
78  

78  

79  
    pointer
79  
    pointer
80  
    operator->() const noexcept
80  
    operator->() const noexcept
81  
    {
81  
    {
82  
        return *(*this);
82  
        return *(*this);
83  
    }
83  
    }
84  

84  

85  
    iterator&
85  
    iterator&
86  
    operator++() noexcept
86  
    operator++() noexcept
87  
    {
87  
    {
88  
        BOOST_ASSERT(i_ < ph_->count);
88  
        BOOST_ASSERT(i_ < ph_->count);
89  
        ++i_;
89  
        ++i_;
90  
        return *this;
90  
        return *this;
91  
    }
91  
    }
92  

92  

93  
    iterator
93  
    iterator
94  
    operator++(int) noexcept
94  
    operator++(int) noexcept
95  
    {
95  
    {
96  
        auto temp = *this;
96  
        auto temp = *this;
97  
        ++(*this);
97  
        ++(*this);
98  
        return temp;
98  
        return temp;
99  
    }
99  
    }
100  

100  

101  
    iterator&
101  
    iterator&
102  
    operator--() noexcept
102  
    operator--() noexcept
103  
    {
103  
    {
104  
        BOOST_ASSERT(i_ > 0);
104  
        BOOST_ASSERT(i_ > 0);
105  
        --i_;
105  
        --i_;
106  
        return *this;
106  
        return *this;
107  
    }
107  
    }
108  

108  

109  
    iterator
109  
    iterator
110  
    operator--(int) noexcept
110  
    operator--(int) noexcept
111  
    {
111  
    {
112  
        auto temp = *this;
112  
        auto temp = *this;
113  
        --(*this);
113  
        --(*this);
114  
        return temp;
114  
        return temp;
115  
    }
115  
    }
116  
};
116  
};
117  

117  

118  
//------------------------------------------------
118  
//------------------------------------------------
119  

119  

120  
class fields_base::reverse_iterator
120  
class fields_base::reverse_iterator
121  
{
121  
{
122  
    detail::header const* ph_ = nullptr;
122  
    detail::header const* ph_ = nullptr;
123  
    std::size_t i_ = 0;
123  
    std::size_t i_ = 0;
124  

124  

125  
    friend class fields_base;
125  
    friend class fields_base;
126  

126  

127  
    reverse_iterator(
127  
    reverse_iterator(
128  
        detail::header const* ph,
128  
        detail::header const* ph,
129  
        std::size_t i) noexcept
129  
        std::size_t i) noexcept
130  
        : ph_(ph)
130  
        : ph_(ph)
131  
        , i_(i)
131  
        , i_(i)
132  
    {
132  
    {
133  
    }
133  
    }
134  

134  

135  
public:
135  
public:
136  
    using value_type =
136  
    using value_type =
137  
        fields_base::value_type;
137  
        fields_base::value_type;
138  
    using reference =
138  
    using reference =
139  
        fields_base::reference;
139  
        fields_base::reference;
140  
    using pointer = reference;
140  
    using pointer = reference;
141  
    using difference_type =
141  
    using difference_type =
142  
        std::ptrdiff_t;
142  
        std::ptrdiff_t;
143  
    using iterator_category =
143  
    using iterator_category =
144  
        std::bidirectional_iterator_tag;
144  
        std::bidirectional_iterator_tag;
145  

145  

146  
    reverse_iterator() = default;
146  
    reverse_iterator() = default;
147  
    reverse_iterator(reverse_iterator const&) = default;
147  
    reverse_iterator(reverse_iterator const&) = default;
148  
    reverse_iterator& operator=(
148  
    reverse_iterator& operator=(
149  
        reverse_iterator const&) = default;
149  
        reverse_iterator const&) = default;
150  

150  

151  
    explicit
151  
    explicit
152  
    reverse_iterator(
152  
    reverse_iterator(
153  
        iterator it) noexcept
153  
        iterator it) noexcept
154  
        : ph_(it.ph_)
154  
        : ph_(it.ph_)
155  
        , i_(it.i_)
155  
        , i_(it.i_)
156  
    {
156  
    {
157  
    }
157  
    }
158  

158  

159  
    bool
159  
    bool
160  
    operator==(
160  
    operator==(
161  
        reverse_iterator const& other) const noexcept
161  
        reverse_iterator const& other) const noexcept
162  
    {
162  
    {
163  
        // If this assert goes off, it means you
163  
        // If this assert goes off, it means you
164  
        // are trying to compare iterators from
164  
        // are trying to compare iterators from
165  
        // different containers, which is undefined!
165  
        // different containers, which is undefined!
166  
        BOOST_ASSERT(ph_ == other.ph_);
166  
        BOOST_ASSERT(ph_ == other.ph_);
167  

167  

168  
        return i_ == other.i_;
168  
        return i_ == other.i_;
169  
    }
169  
    }
170  

170  

171  
    bool
171  
    bool
172  
    operator!=(
172  
    operator!=(
173  
        reverse_iterator const& other) const noexcept
173  
        reverse_iterator const& other) const noexcept
174  
    {
174  
    {
175  
        return !(*this == other);
175  
        return !(*this == other);
176  
    }
176  
    }
177  

177  

178  
    BOOST_HTTP_DECL
178  
    BOOST_HTTP_DECL
179  
    reference
179  
    reference
180  
    operator*() const noexcept;
180  
    operator*() const noexcept;
181  

181  

182  
    pointer
182  
    pointer
183  
    operator->() const noexcept
183  
    operator->() const noexcept
184  
    {
184  
    {
185  
        return *(*this);
185  
        return *(*this);
186  
    }
186  
    }
187  

187  

188  
    reverse_iterator&
188  
    reverse_iterator&
189  
    operator++() noexcept
189  
    operator++() noexcept
190  
    {
190  
    {
191  
        BOOST_ASSERT(i_ > 0);
191  
        BOOST_ASSERT(i_ > 0);
192  
        --i_;
192  
        --i_;
193  
        return *this;
193  
        return *this;
194  
    }
194  
    }
195  

195  

196  
    reverse_iterator
196  
    reverse_iterator
197  
    operator++(int) noexcept
197  
    operator++(int) noexcept
198  
    {
198  
    {
199  
        auto temp = *this;
199  
        auto temp = *this;
200  
        ++(*this);
200  
        ++(*this);
201  
        return temp;
201  
        return temp;
202  
    }
202  
    }
203  

203  

204  
    reverse_iterator&
204  
    reverse_iterator&
205  
    operator--() noexcept
205  
    operator--() noexcept
206  
    {
206  
    {
207  
        BOOST_ASSERT(i_ < ph_->count);
207  
        BOOST_ASSERT(i_ < ph_->count);
208  
        ++i_;
208  
        ++i_;
209  
        return *this;
209  
        return *this;
210  
    }
210  
    }
211  

211  

212  
    reverse_iterator
212  
    reverse_iterator
213  
    operator--(int) noexcept
213  
    operator--(int) noexcept
214  
    {
214  
    {
215  
        auto temp = *this;
215  
        auto temp = *this;
216  
        --(*this);
216  
        --(*this);
217  
        return temp;
217  
        return temp;
218  
    }
218  
    }
219  
};
219  
};
220  

220  

221  
//------------------------------------------------
221  
//------------------------------------------------
222  
//
222  
//
223  
// subrange
223  
// subrange
224  
//
224  
//
225  
//------------------------------------------------
225  
//------------------------------------------------
226  

226  

227  
class fields_base::subrange
227  
class fields_base::subrange
228  
{
228  
{
229  
    detail::header const* ph_ = nullptr;
229  
    detail::header const* ph_ = nullptr;
230  
    std::size_t i_ = 0;
230  
    std::size_t i_ = 0;
231  

231  

232  
    friend class fields_base;
232  
    friend class fields_base;
233  
    friend struct detail::header;
233  
    friend struct detail::header;
234  

234  

235  
    subrange(
235  
    subrange(
236  
        detail::header const* ph,
236  
        detail::header const* ph,
237  
        std::size_t i) noexcept
237  
        std::size_t i) noexcept
238  
        : ph_(ph)
238  
        : ph_(ph)
239  
        , i_(i)
239  
        , i_(i)
240  
    {
240  
    {
241  
    }
241  
    }
242  

242  

243  
public:
243  
public:
244  
    class iterator;
244  
    class iterator;
245  
    //class reverse_iterator;
245  
    //class reverse_iterator;
246  
    using const_iterator = iterator;
246  
    using const_iterator = iterator;
247  
    using value_type = std::string;
247  
    using value_type = std::string;
248  
    using reference = core::string_view;
248  
    using reference = core::string_view;
249  
    using const_reference = reference;
249  
    using const_reference = reference;
250  
    using size_type = std::size_t;
250  
    using size_type = std::size_t;
251  
    using difference_type = std::ptrdiff_t;
251  
    using difference_type = std::ptrdiff_t;
252  

252  

253  
    /** Constructor
253  
    /** Constructor
254  

254  

255  
        Default-constructed subranges are empty.
255  
        Default-constructed subranges are empty.
256  
    */
256  
    */
257  
    subrange() noexcept = default;
257  
    subrange() noexcept = default;
258  

258  

259  
    subrange(subrange const&) noexcept = default;
259  
    subrange(subrange const&) noexcept = default;
260  
    subrange& operator=(
260  
    subrange& operator=(
261  
        subrange const&) noexcept = default;
261  
        subrange const&) noexcept = default;
262  

262  

263  
    iterator begin() const noexcept;
263  
    iterator begin() const noexcept;
264  
    iterator end() const noexcept;
264  
    iterator end() const noexcept;
265  
};
265  
};
266  

266  

267  
//------------------------------------------------
267  
//------------------------------------------------
268  
//
268  
//
269  
// subrange::iterator
269  
// subrange::iterator
270  
//
270  
//
271  
//------------------------------------------------
271  
//------------------------------------------------
272  

272  

273  
class fields_base::subrange::
273  
class fields_base::subrange::
274  
    iterator
274  
    iterator
275  
{
275  
{
276  
    detail::header const* ph_ = nullptr;
276  
    detail::header const* ph_ = nullptr;
277  
    std::size_t i_ = 0;
277  
    std::size_t i_ = 0;
278  

278  

279  
    friend class fields_base::subrange;
279  
    friend class fields_base::subrange;
280  

280  

281  
    BOOST_HTTP_DECL
281  
    BOOST_HTTP_DECL
282  
    iterator(
282  
    iterator(
283  
        detail::header const* ph,
283  
        detail::header const* ph,
284  
        std::size_t i) noexcept;
284  
        std::size_t i) noexcept;
285  

285  

286  
    // end
286  
    // end
287  
    BOOST_HTTP_DECL
287  
    BOOST_HTTP_DECL
288  
    iterator(
288  
    iterator(
289  
        detail::header const* ph) noexcept;
289  
        detail::header const* ph) noexcept;
290  

290  

291  
public:
291  
public:
292  
    using value_type = std::string;
292  
    using value_type = std::string;
293  
    using reference = core::string_view;
293  
    using reference = core::string_view;
294  
    using pointer = void const*;
294  
    using pointer = void const*;
295  
    using difference_type =
295  
    using difference_type =
296  
        std::ptrdiff_t;
296  
        std::ptrdiff_t;
297  
    using iterator_category =
297  
    using iterator_category =
298  
        std::forward_iterator_tag;
298  
        std::forward_iterator_tag;
299  

299  

300  
    iterator() = default;
300  
    iterator() = default;
301  
    iterator(iterator const&) = default;
301  
    iterator(iterator const&) = default;
302  
    iterator& operator=(
302  
    iterator& operator=(
303  
        iterator const&) = default;
303  
        iterator const&) = default;
304  

304  

305  
    // conversion to regular iterator
305  
    // conversion to regular iterator
306  
    operator
306  
    operator
307  
    fields_base::
307  
    fields_base::
308  
    iterator() const noexcept
308  
    iterator() const noexcept
309  
    {
309  
    {
310  
        return {ph_, i_};
310  
        return {ph_, i_};
311  
    }
311  
    }
312  

312  

313  
    bool
313  
    bool
314  
    operator==(
314  
    operator==(
315  
        iterator const& other) const noexcept
315  
        iterator const& other) const noexcept
316  
    {
316  
    {
317  
        // If this assert goes off, it means you
317  
        // If this assert goes off, it means you
318  
        // are trying to compare iterators from
318  
        // are trying to compare iterators from
319  
        // different containers, which is undefined!
319  
        // different containers, which is undefined!
320  
        BOOST_ASSERT(ph_ == other.ph_);
320  
        BOOST_ASSERT(ph_ == other.ph_);
321  

321  

322  
        return i_ == other.i_;
322  
        return i_ == other.i_;
323  
    }
323  
    }
324  

324  

325  
    bool
325  
    bool
326  
    operator!=(
326  
    operator!=(
327  
        iterator const& other) const noexcept
327  
        iterator const& other) const noexcept
328  
    {
328  
    {
329  
        return !(*this == other);
329  
        return !(*this == other);
330  
    }
330  
    }
331  

331  

332  
    BOOST_HTTP_DECL
332  
    BOOST_HTTP_DECL
333  
    reference const
333  
    reference const
334  
    operator*() const noexcept;
334  
    operator*() const noexcept;
335  

335  

336  
    reference const
336  
    reference const
337  
    operator->() const noexcept
337  
    operator->() const noexcept
338  
    {
338  
    {
339  
        return *(*this);
339  
        return *(*this);
340  
    }
340  
    }
341  

341  

342  
    BOOST_HTTP_DECL
342  
    BOOST_HTTP_DECL
343  
    iterator&
343  
    iterator&
344  
    operator++() noexcept;
344  
    operator++() noexcept;
345  

345  

346  
    iterator
346  
    iterator
347  
    operator++(int) noexcept
347  
    operator++(int) noexcept
348  
    {
348  
    {
349  
        auto temp = *this;
349  
        auto temp = *this;
350  
        ++(*this);
350  
        ++(*this);
351  
        return temp;
351  
        return temp;
352  
    }
352  
    }
353  
};
353  
};
354  

354  

355  
inline
355  
inline
356  
auto
356  
auto
357  
fields_base::
357  
fields_base::
358  
subrange::
358  
subrange::
359  
begin() const noexcept ->
359  
begin() const noexcept ->
360  
    iterator
360  
    iterator
361  
{
361  
{
362  
    return {ph_, i_};
362  
    return {ph_, i_};
363  
}
363  
}
364  

364  

365  
inline
365  
inline
366  
auto
366  
auto
367  
fields_base::
367  
fields_base::
368  
subrange::
368  
subrange::
369  
end() const noexcept ->
369  
end() const noexcept ->
370  
    iterator
370  
    iterator
371  
{
371  
{
372  
    return {ph_};
372  
    return {ph_};
373  
}
373  
}
374  

374  

375  
//------------------------------------------------
375  
//------------------------------------------------
376  

376  

377  
inline
377  
inline
378  
fields_base::
378  
fields_base::
379  
value_type::
379  
value_type::
380  
operator
380  
operator
381  
fields_base::
381  
fields_base::
382  
reference() const noexcept
382  
reference() const noexcept
383  
{
383  
{
384  
    return reference{
384  
    return reference{
385  
        id, name, value};
385  
        id, name, value};
386  
}
386  
}
387  

387  

388  
//------------------------------------------------
388  
//------------------------------------------------
389  

389  

390  
inline
390  
inline
391  
auto
391  
auto
392  
fields_base::
392  
fields_base::
393  
begin() const noexcept ->
393  
begin() const noexcept ->
394  
    iterator
394  
    iterator
395  
{
395  
{
396  
    return iterator(&h_, 0);
396  
    return iterator(&h_, 0);
397  
}
397  
}
398  

398  

399  
inline
399  
inline
400  
auto
400  
auto
401  
fields_base::
401  
fields_base::
402  
end() const noexcept ->
402  
end() const noexcept ->
403  
    iterator
403  
    iterator
404  
{
404  
{
405  
    return iterator(&h_, h_.count);
405  
    return iterator(&h_, h_.count);
406  
}
406  
}
407  

407  

408  
inline
408  
inline
409  
auto
409  
auto
410  
fields_base::
410  
fields_base::
411  
rbegin() const noexcept ->
411  
rbegin() const noexcept ->
412  
    reverse_iterator
412  
    reverse_iterator
413  
{
413  
{
414  
    return reverse_iterator(end());
414  
    return reverse_iterator(end());
415  
}
415  
}
416  

416  

417  
inline
417  
inline
418  
auto
418  
auto
419  
fields_base::
419  
fields_base::
420  
rend() const noexcept ->
420  
rend() const noexcept ->
421  
    reverse_iterator
421  
    reverse_iterator
422  
{
422  
{
423  
    return reverse_iterator(begin());
423  
    return reverse_iterator(begin());
424  
}
424  
}
425  

425  

426  
} // http
426  
} // http
427  
} // boost
427  
} // boost
428  

428  

429  
#endif
429  
#endif