Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
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)
6 : //
7 : // Official repository: https://github.com/boostorg/url
8 : //
9 :
10 :
11 : #include <boost/url/detail/config.hpp>
12 : #include <boost/url/detail/params_iter_impl.hpp>
13 : #include <boost/assert.hpp>
14 :
15 : namespace boost {
16 : namespace urls {
17 : namespace detail {
18 :
19 : /* index zero-based index of param
20 : pos offset from start 0 = '?'
21 : nk size of key with '?' or '&'
22 : nv size of value with '='
23 : dk decoded key size no '?' or '&'
24 : dv decoded value size no '='
25 : */
26 612 : params_iter_impl::
27 : params_iter_impl(
28 612 : query_ref const& ref_) noexcept
29 612 : : ref(ref_)
30 612 : , index(0)
31 612 : , pos(0)
32 : {
33 612 : if(index < ref_.nparam())
34 561 : setup();
35 612 : }
36 :
37 660 : params_iter_impl::
38 : params_iter_impl(
39 : query_ref const& ref_,
40 660 : int) noexcept
41 660 : : ref(ref_)
42 660 : , index(ref_.nparam())
43 660 : , pos(ref_.size())
44 : {
45 660 : }
46 :
47 133 : params_iter_impl::
48 : params_iter_impl(
49 : query_ref const& ref_,
50 : std::size_t pos_,
51 133 : std::size_t index_) noexcept
52 133 : : ref(ref_)
53 133 : , index(index_)
54 133 : , pos(pos_)
55 : {
56 133 : BOOST_ASSERT(
57 : pos <= ref.size());
58 133 : if(index < ref_.nparam())
59 125 : setup();
60 133 : }
61 :
62 : // set up state for key/value at pos
63 : void
64 2290 : params_iter_impl::
65 : setup() noexcept
66 : {
67 2290 : dk = 1;
68 2290 : dv = 0;
69 2290 : auto const end = ref.end();
70 2290 : BOOST_ASSERT(pos != ref.size());
71 2290 : auto p0 = ref.begin() + pos;
72 2290 : auto p = p0;
73 : // key
74 : for(;;)
75 : {
76 8929 : if( p == end ||
77 8868 : *p == '&')
78 : {
79 : // no value
80 335 : nk = 1 + p - p0;
81 335 : dk = nk - dk;
82 335 : nv = 0;
83 335 : return;
84 : }
85 8594 : if(*p == '=')
86 1955 : break;
87 6639 : if(*p == '%')
88 : {
89 228 : BOOST_ASSERT(
90 : end - p >= 3);
91 228 : dk += 2;
92 228 : p += 2;
93 : }
94 6639 : ++p;
95 : }
96 1955 : nk = 1 + p - p0;
97 1955 : dk = nk - dk;
98 1955 : p0 = p;
99 :
100 : // value
101 : for(;;)
102 : {
103 7871 : ++p;
104 7871 : if( p == end ||
105 7298 : *p == '&')
106 : break;
107 5916 : if(*p == '%')
108 : {
109 198 : BOOST_ASSERT(
110 : end - p >= 3);
111 198 : dv += 2;
112 198 : p += 2;
113 : }
114 : }
115 1955 : nv = p - p0;
116 1955 : dv = nv - dv - 1;
117 : }
118 :
119 : void
120 2190 : params_iter_impl::
121 : increment() noexcept
122 : {
123 2190 : BOOST_ASSERT(
124 : index < ref.nparam());
125 2190 : pos += nk + nv;
126 2190 : ++index;
127 2190 : if(index < ref.nparam())
128 1604 : setup();
129 2190 : }
130 :
131 : void
132 1326 : params_iter_impl::
133 : decrement() noexcept
134 : {
135 1326 : BOOST_ASSERT(index > 0);
136 1326 : --index;
137 1326 : dk = 1; // for '&' or '?'
138 1326 : dv = 1; // for '='
139 1326 : auto const begin = ref.begin();
140 1326 : BOOST_ASSERT(pos > 0);
141 1326 : auto p1 = begin + (pos - 1);
142 1326 : auto p = p1;
143 : // find key or '='
144 : for(;;)
145 : {
146 7614 : if(p == begin)
147 : {
148 : // key
149 220 : nk = 1 + p1 - p; // with '?'
150 220 : dk = nk - dv;
151 220 : nv = 0;
152 220 : dv = 0;
153 220 : pos -= nk;
154 220 : return;
155 : }
156 7394 : else if(*--p == '&')
157 : {
158 : // key
159 94 : nk = p1 - p; // with '&'
160 94 : dk = nk - dv;
161 94 : nv = 0;
162 94 : dv = 0;
163 94 : pos -= nk;
164 94 : return;
165 : }
166 7300 : if(*p == '=')
167 : {
168 : // value
169 1012 : nv = p1 - p; // with '='
170 1012 : break;
171 : }
172 6288 : if(*p == '%')
173 176 : dv += 2;
174 : }
175 : // find key and value
176 : for(;;)
177 : {
178 5270 : if(p == begin)
179 : {
180 : // key and value
181 256 : nk = 1 + p1 - p - nv; // with '?'
182 256 : dk = nk - dk;
183 256 : dv = nv - dv;
184 256 : pos -= nk + nv;
185 256 : return;
186 : }
187 5014 : if(*--p == '&')
188 : {
189 : // key and value
190 756 : nk = p1 - p - nv; // with '&'
191 756 : dk = nk - dk;
192 756 : dv = nv - dv;
193 756 : pos -= nk + nv;
194 756 : return;
195 : }
196 4258 : if(*p == '=')
197 : {
198 : // value
199 0 : nv = p1 - p; // with '='
200 0 : dv += dk;
201 0 : dk = 0;
202 : }
203 4258 : else if(*p == '%')
204 : {
205 60 : dk += 2;
206 : }
207 : }
208 : }
209 :
210 : param_pct_view
211 1415 : params_iter_impl::
212 : dereference() const noexcept
213 : {
214 1415 : BOOST_ASSERT(index < ref.nparam());
215 1415 : BOOST_ASSERT(pos < ref.size());
216 1415 : auto const p = ref.begin() + pos;
217 1415 : if(nv)
218 : return {
219 1092 : make_pct_string_view_unsafe(
220 1092 : p, nk - 1, dk),
221 : make_pct_string_view_unsafe(
222 1092 : p + nk, nv - 1, dv)};
223 : return {
224 : make_pct_string_view_unsafe(
225 323 : p, nk - 1, dk),
226 323 : no_value};
227 : }
228 :
229 : pct_string_view
230 812 : params_iter_impl::
231 : key() const noexcept
232 : {
233 812 : BOOST_ASSERT(index < ref.nparam());
234 812 : BOOST_ASSERT(pos < ref.size());
235 812 : auto const p = ref.begin() + pos;
236 812 : return make_pct_string_view_unsafe(
237 812 : p, nk - 1, dk);
238 : }
239 :
240 : } // detail
241 : } // url
242 : } // boost
243 :
|