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 2203 : segments_iter_impl::
24 : segments_iter_impl(
25 2203 : detail::path_ref const& ref_) noexcept
26 2203 : : ref(ref_)
27 : {
28 2203 : pos = path_prefix(ref.buffer());
29 2203 : update();
30 2203 : }
31 :
32 : // end
33 1802 : segments_iter_impl::
34 : segments_iter_impl(
35 : detail::path_ref const& ref_,
36 1802 : int) noexcept
37 1802 : : ref(ref_)
38 1802 : , pos(ref.size())
39 1802 : , next(ref.size())
40 1802 : , index(ref.nseg())
41 : {
42 1802 : }
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 2798 : segments_iter_impl::
68 : update() noexcept
69 : {
70 2798 : auto const end = ref.end();
71 : char const* const p0 =
72 2798 : ref.data() + pos;
73 2798 : dn = 0;
74 2798 : auto p = p0;
75 10449 : while(p != end)
76 : {
77 9213 : if(*p == '/')
78 1562 : break;
79 7651 : if(*p != '%')
80 : {
81 7286 : ++p;
82 7286 : continue;
83 : }
84 365 : p += 3;
85 365 : dn += 2;
86 : }
87 2798 : next = p - ref.data();
88 2798 : dn = p - p0 - dn;
89 2798 : s_ = make_pct_string_view_unsafe(
90 2798 : p0, p - p0, dn);
91 2798 : }
92 :
93 : void
94 2753 : segments_iter_impl::
95 : increment() noexcept
96 : {
97 2753 : BOOST_ASSERT(
98 : index != ref.nseg());
99 2753 : ++index;
100 2753 : pos = next;
101 2753 : if(index == ref.nseg())
102 1130 : return;
103 : // "/" segment
104 1623 : auto const end = ref.end();
105 1623 : auto p = ref.data() + pos;
106 1623 : BOOST_ASSERT(p != end);
107 1623 : BOOST_ASSERT(*p == '/');
108 1623 : dn = 0;
109 1623 : ++p; // skip '/'
110 1623 : auto const p0 = p;
111 7151 : while(p != end)
112 : {
113 6465 : if(*p == '/')
114 937 : break;
115 5528 : if(*p != '%')
116 : {
117 5416 : ++p;
118 5416 : continue;
119 : }
120 112 : p += 3;
121 112 : dn += 2;
122 : }
123 1623 : next = p - ref.data();
124 1623 : dn = p - p0 - dn;
125 1623 : s_ = make_pct_string_view_unsafe(
126 1623 : p0, p - p0, dn);
127 : }
128 :
129 : void
130 1553 : segments_iter_impl::
131 : decrement() noexcept
132 : {
133 1553 : BOOST_ASSERT(index != 0);
134 1553 : --index;
135 1553 : if(index == 0)
136 : {
137 521 : next = pos;
138 521 : pos = path_prefix(ref.buffer());
139 521 : s_ = core::string_view(
140 521 : ref.data() + pos,
141 521 : next - pos);
142 521 : BOOST_ASSERT(! s_.ends_with('/'));
143 521 : return;
144 : }
145 1032 : auto const begin = ref.data() +
146 1032 : path_prefix(ref.buffer());
147 1032 : next = pos;
148 1032 : auto p = ref.data() + next;
149 1032 : auto const p1 = p;
150 1032 : BOOST_ASSERT(p != begin);
151 1032 : dn = 0;
152 3182 : while(p != begin)
153 : {
154 3182 : --p;
155 3182 : if(*p == '/')
156 : {
157 1032 : ++dn;
158 1032 : break;
159 : }
160 2150 : if(*p == '%')
161 28 : dn += 2;
162 : }
163 1032 : dn = p1 - p - dn;
164 1032 : pos = p - ref.data();
165 1032 : s_ = make_pct_string_view_unsafe(
166 1032 : p + 1, p1 - p - 1, dn);
167 : }
168 :
169 : } // detail
170 : } // url
171 : } // boost
172 :
|