1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_URL_IMPL_SEGMENTS_BASE_HPP
11  
#ifndef BOOST_URL_IMPL_SEGMENTS_BASE_HPP
12  
#define BOOST_URL_IMPL_SEGMENTS_BASE_HPP
12  
#define BOOST_URL_IMPL_SEGMENTS_BASE_HPP
13  

13  

14  
#include <boost/url/detail/segments_iter_impl.hpp>
14  
#include <boost/url/detail/segments_iter_impl.hpp>
15  
#include <boost/url/encoding_opts.hpp>
15  
#include <boost/url/encoding_opts.hpp>
16  
#include <boost/assert.hpp>
16  
#include <boost/assert.hpp>
17  
#include <iterator>
17  
#include <iterator>
18  
#include <ostream>
18  
#include <ostream>
19  

19  

20  
namespace boost {
20  
namespace boost {
21  
namespace urls {
21  
namespace urls {
22  
namespace detail {
22  
namespace detail {
23  
struct segments_iter_access;
23  
struct segments_iter_access;
24  
}
24  
}
25  

25  

26  
class segments_base::iterator
26  
class segments_base::iterator
27  
{
27  
{
28  
    detail::segments_iter_impl it_;
28  
    detail::segments_iter_impl it_;
29  

29  

30  
    friend class segments_base;
30  
    friend class segments_base;
31  
    friend class segments_ref;
31  
    friend class segments_ref;
32  
    friend struct detail::segments_iter_access;
32  
    friend struct detail::segments_iter_access;
33  

33  

34  
    iterator(detail::path_ref const&) noexcept;
34  
    iterator(detail::path_ref const&) noexcept;
35  
    iterator(detail::path_ref const&, int) noexcept;
35  
    iterator(detail::path_ref const&, int) noexcept;
36  

36  

37  
    iterator(
37  
    iterator(
38  
        detail::segments_iter_impl const& it) noexcept
38  
        detail::segments_iter_impl const& it) noexcept
39  
        : it_(it)
39  
        : it_(it)
40  
    {
40  
    {
41  
    }
41  
    }
42  

42  

43  
public:
43  
public:
44  
    using value_type = segments_base::value_type;
44  
    using value_type = segments_base::value_type;
45  
    using reference = segments_base::reference;
45  
    using reference = segments_base::reference;
46  
    using pointer = reference;
46  
    using pointer = reference;
47  
    using difference_type =
47  
    using difference_type =
48  
        segments_base::difference_type;
48  
        segments_base::difference_type;
49  
    using iterator_category =
49  
    using iterator_category =
50  
        std::bidirectional_iterator_tag;
50  
        std::bidirectional_iterator_tag;
51  

51  

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

56  

57  
    reference
57  
    reference
58  
    operator*() const
58  
    operator*() const
59  
    {
59  
    {
60  
        encoding_opts opt;
60  
        encoding_opts opt;
61  
        opt.space_as_plus = false;
61  
        opt.space_as_plus = false;
62  
        return it_.dereference().decode(opt);
62  
        return it_.dereference().decode(opt);
63  
    }
63  
    }
64  

64  

65  
    // the return value is too expensive
65  
    // the return value is too expensive
66  
    pointer operator->() const = delete;
66  
    pointer operator->() const = delete;
67  

67  

68  
    iterator&
68  
    iterator&
69  
    operator++() noexcept
69  
    operator++() noexcept
70  
    {
70  
    {
71  
        it_.increment();
71  
        it_.increment();
72  
        return *this;
72  
        return *this;
73  
    }
73  
    }
74  

74  

75  
    iterator&
75  
    iterator&
76  
    operator--() noexcept
76  
    operator--() noexcept
77  
    {
77  
    {
78  
        it_.decrement();
78  
        it_.decrement();
79  
        return *this;
79  
        return *this;
80  
    }
80  
    }
81  

81  

82  
    iterator
82  
    iterator
83  
    operator++(int) noexcept
83  
    operator++(int) noexcept
84  
    {
84  
    {
85  
        auto tmp = *this;
85  
        auto tmp = *this;
86  
        ++*this;
86  
        ++*this;
87  
        return tmp;
87  
        return tmp;
88  
    }
88  
    }
89  

89  

90  
    iterator
90  
    iterator
91  
    operator--(int) noexcept
91  
    operator--(int) noexcept
92  
    {
92  
    {
93  
        auto tmp = *this;
93  
        auto tmp = *this;
94  
        --*this;
94  
        --*this;
95  
        return tmp;
95  
        return tmp;
96  
    }
96  
    }
97  

97  

98  
    bool
98  
    bool
99  
    operator==(
99  
    operator==(
100  
        iterator const& other) const noexcept
100  
        iterator const& other) const noexcept
101  
    {
101  
    {
102  
        return it_.equal(other.it_);
102  
        return it_.equal(other.it_);
103  
    }
103  
    }
104  

104  

105  
    bool
105  
    bool
106  
    operator!=(
106  
    operator!=(
107  
        iterator const& other) const noexcept
107  
        iterator const& other) const noexcept
108  
    {
108  
    {
109  
        return ! it_.equal(other.it_);
109  
        return ! it_.equal(other.it_);
110  
    }
110  
    }
111  
};
111  
};
112  

112  

113  
//------------------------------------------------
113  
//------------------------------------------------
114  

114  

115  
inline
115  
inline
116  
segments_base::
116  
segments_base::
117  
iterator::
117  
iterator::
118  
iterator(
118  
iterator(
119  
    detail::path_ref const& ref) noexcept
119  
    detail::path_ref const& ref) noexcept
120  
    : it_(ref)
120  
    : it_(ref)
121  
{
121  
{
122  
}
122  
}
123  

123  

124  
inline
124  
inline
125  
segments_base::
125  
segments_base::
126  
iterator::
126  
iterator::
127  
iterator(
127  
iterator(
128  
    detail::path_ref const& ref,
128  
    detail::path_ref const& ref,
129  
    int) noexcept
129  
    int) noexcept
130  
    : it_(ref, 0)
130  
    : it_(ref, 0)
131  
{
131  
{
132  
}
132  
}
133  

133  

134  
//------------------------------------------------
134  
//------------------------------------------------
135  
//
135  
//
136  
// segments_base
136  
// segments_base
137  
//
137  
//
138  
//------------------------------------------------
138  
//------------------------------------------------
139  

139  

140  
inline
140  
inline
141  
segments_base::
141  
segments_base::
142  
segments_base(
142  
segments_base(
143  
    detail::path_ref const& ref) noexcept
143  
    detail::path_ref const& ref) noexcept
144  
    : ref_(ref)
144  
    : ref_(ref)
145  
{
145  
{
146  
}
146  
}
147  

147  

148  
inline
148  
inline
149  
pct_string_view
149  
pct_string_view
150  
segments_base::
150  
segments_base::
151  
buffer() const noexcept
151  
buffer() const noexcept
152  
{
152  
{
153  
    return ref_.buffer();
153  
    return ref_.buffer();
154  
}
154  
}
155  

155  

156  
inline
156  
inline
157  
bool
157  
bool
158  
segments_base::
158  
segments_base::
159  
is_absolute() const noexcept
159  
is_absolute() const noexcept
160  
{
160  
{
161  
    return ref_.buffer().starts_with('/');
161  
    return ref_.buffer().starts_with('/');
162  
}
162  
}
163  

163  

164  
inline
164  
inline
165  
bool
165  
bool
166  
segments_base::
166  
segments_base::
167  
empty() const noexcept
167  
empty() const noexcept
168  
{
168  
{
169  
    return ref_.nseg() == 0;
169  
    return ref_.nseg() == 0;
170  
}
170  
}
171  

171  

172  
inline
172  
inline
173  
std::size_t
173  
std::size_t
174  
segments_base::
174  
segments_base::
175  
size() const noexcept
175  
size() const noexcept
176  
{
176  
{
177  
    return ref_.nseg();
177  
    return ref_.nseg();
178  
}
178  
}
179  

179  

180  
inline
180  
inline
181  
std::string
181  
std::string
182  
segments_base::
182  
segments_base::
183  
front() const noexcept
183  
front() const noexcept
184  
{
184  
{
185  
    BOOST_ASSERT(! empty());
185  
    BOOST_ASSERT(! empty());
186  
    return *begin();
186  
    return *begin();
187  
}
187  
}
188  

188  

189  
inline
189  
inline
190  
std::string
190  
std::string
191  
segments_base::
191  
segments_base::
192  
back() const noexcept
192  
back() const noexcept
193  
{
193  
{
194  
    BOOST_ASSERT(! empty());
194  
    BOOST_ASSERT(! empty());
195  
    return *--end();
195  
    return *--end();
196  
}
196  
}
197  

197  

198  
inline
198  
inline
199  
auto
199  
auto
200  
segments_base::
200  
segments_base::
201  
begin() const noexcept ->
201  
begin() const noexcept ->
202  
    iterator
202  
    iterator
203  
{
203  
{
204  
    return iterator(ref_);
204  
    return iterator(ref_);
205  
}
205  
}
206  

206  

207  
inline
207  
inline
208  
auto
208  
auto
209  
segments_base::
209  
segments_base::
210  
end() const noexcept ->
210  
end() const noexcept ->
211  
    iterator
211  
    iterator
212  
{
212  
{
213  
    return iterator(ref_, 0);
213  
    return iterator(ref_, 0);
214  
}
214  
}
215  

215  

216  
//------------------------------------------------
216  
//------------------------------------------------
217  

217  

218  
inline
218  
inline
219  
std::ostream&
219  
std::ostream&
220  
operator<<(
220  
operator<<(
221  
    std::ostream& os,
221  
    std::ostream& os,
222  
    segments_base const& ps)
222  
    segments_base const& ps)
223  
{
223  
{
224  
    os << ps.buffer();
224  
    os << ps.buffer();
225  
    return os;
225  
    return os;
226  
}
226  
}
227  

227  

228  
} // urls
228  
} // urls
229  
} // boost
229  
} // boost
230  

230  

231  
#endif
231  
#endif