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