Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4 : //
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)
7 : //
8 : // Official repository: https://github.com/boostorg/url
9 : //
10 :
11 :
12 : #include <boost/url/detail/config.hpp>
13 : #include "path.hpp"
14 : #include <boost/url/detail/segments_iter_impl.hpp>
15 : #include "boost/url/rfc/detail/path_rules.hpp"
16 : #include <boost/assert.hpp>
17 :
18 : namespace boost {
19 : namespace urls {
20 : namespace detail {
21 :
22 : // begin
23 2183 : segments_iter_impl::
24 : segments_iter_impl(
25 2183 : detail::path_ref const& ref_) noexcept
26 2183 : : ref(ref_)
27 : {
28 2183 : pos = path_prefix(ref.buffer());
29 2183 : update();
30 2183 : }
31 :
32 : // end
33 1789 : segments_iter_impl::
34 : segments_iter_impl(
35 : detail::path_ref const& ref_,
36 1789 : int) noexcept
37 1789 : : ref(ref_)
38 1789 : , pos(ref.size())
39 1789 : , next(ref.size())
40 1789 : , index(ref.nseg())
41 : {
42 1789 : }
43 :
44 595 : segments_iter_impl::
45 : segments_iter_impl(
46 : url_impl const& u_,
47 : std::size_t pos_,
48 595 : std::size_t index_) noexcept
49 595 : : ref(u_)
50 595 : , pos(pos_)
51 595 : , index(index_)
52 : {
53 595 : if(index == 0)
54 : {
55 272 : pos = path_prefix(ref.buffer());
56 : }
57 323 : else if(pos != ref.size())
58 : {
59 199 : BOOST_ASSERT(
60 : ref.data()[pos] == '/');
61 199 : ++pos; // skip '/'
62 : }
63 595 : update();
64 595 : }
65 :
66 : void
67 2778 : segments_iter_impl::
68 : update() noexcept
69 : {
70 2778 : auto const end = ref.end();
71 : char const* const p0 =
72 2778 : ref.data() + pos;
73 2778 : dn = 0;
74 2778 : auto p = p0;
75 10261 : while(p != end)
76 : {
77 9038 : if(*p == '/')
78 1555 : break;
79 7483 : if(*p != '%')
80 : {
81 7118 : ++p;
82 7118 : continue;
83 : }
84 365 : p += 3;
85 365 : dn += 2;
86 : }
87 2778 : next = p - ref.data();
88 2778 : dn = p - p0 - dn;
89 2778 : s_ = make_pct_string_view_unsafe(
90 2778 : p0, p - p0, dn);
91 2778 : }
92 :
93 : void
94 2750 : segments_iter_impl::
95 : increment() noexcept
96 : {
97 2750 : BOOST_ASSERT(
98 : index != ref.nseg());
99 2750 : ++index;
100 2750 : pos = next;
101 2750 : if(index == ref.nseg())
102 1129 : return;
103 : // "/" segment
104 1621 : auto const end = ref.end();
105 1621 : auto p = ref.data() + pos;
106 1621 : BOOST_ASSERT(p != end);
107 1621 : BOOST_ASSERT(*p == '/');
108 1621 : dn = 0;
109 1621 : ++p; // skip '/'
110 1621 : auto const p0 = p;
111 7124 : while(p != end)
112 : {
113 6439 : if(*p == '/')
114 936 : break;
115 5503 : if(*p != '%')
116 : {
117 5393 : ++p;
118 5393 : continue;
119 : }
120 110 : p += 3;
121 110 : dn += 2;
122 : }
123 1621 : next = p - ref.data();
124 1621 : dn = p - p0 - dn;
125 1621 : s_ = make_pct_string_view_unsafe(
126 1621 : p0, p - p0, dn);
127 : }
128 :
129 : void
130 1537 : segments_iter_impl::
131 : decrement() noexcept
132 : {
133 1537 : BOOST_ASSERT(index != 0);
134 1537 : --index;
135 1537 : if(index == 0)
136 : {
137 511 : next = pos;
138 511 : pos = path_prefix(ref.buffer());
139 511 : s_ = core::string_view(
140 511 : ref.data() + pos,
141 511 : next - pos);
142 511 : BOOST_ASSERT(! s_.ends_with('/'));
143 511 : return;
144 : }
145 1026 : auto const begin = ref.data() +
146 1026 : path_prefix(ref.buffer());
147 1026 : next = pos;
148 1026 : auto p = ref.data() + next;
149 1026 : auto const p1 = p;
150 1026 : BOOST_ASSERT(p != begin);
151 1026 : dn = 0;
152 3132 : while(p != begin)
153 : {
154 3132 : --p;
155 3132 : if(*p == '/')
156 : {
157 1026 : ++dn;
158 1026 : break;
159 : }
160 2106 : if(*p == '%')
161 28 : dn += 2;
162 : }
163 1026 : dn = p1 - p - dn;
164 1026 : pos = p - ref.data();
165 1026 : s_ = make_pct_string_view_unsafe(
166 1026 : p + 1, p1 - p - 1, dn);
167 : }
168 :
169 : } // detail
170 : } // url
171 : } // boost
172 :
|