TLA 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 : #ifndef BOOST_URL_DETAIL_IMPL_PARAMS_ITER_IMPL_HPP
11 : #define BOOST_URL_DETAIL_IMPL_PARAMS_ITER_IMPL_HPP
12 :
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 : inline
27 HIT 662 : params_iter_impl::
28 : params_iter_impl(
29 662 : query_ref const& ref_) noexcept
30 662 : : ref(ref_)
31 662 : , index(0)
32 662 : , pos(0)
33 : {
34 662 : if(index < ref_.nparam())
35 609 : setup();
36 662 : }
37 :
38 : inline
39 726 : params_iter_impl::
40 : params_iter_impl(
41 : query_ref const& ref_,
42 726 : int) noexcept
43 726 : : ref(ref_)
44 726 : , index(ref_.nparam())
45 726 : , pos(ref_.size())
46 : {
47 726 : }
48 :
49 : inline
50 142 : params_iter_impl::
51 : params_iter_impl(
52 : query_ref const& ref_,
53 : std::size_t pos_,
54 142 : std::size_t index_) noexcept
55 142 : : ref(ref_)
56 142 : , index(index_)
57 142 : , pos(pos_)
58 : {
59 142 : BOOST_ASSERT(
60 : pos <= ref.size());
61 142 : if(index < ref_.nparam())
62 134 : setup();
63 142 : }
64 :
65 : // set up state for key/value at pos
66 : inline
67 : void
68 2410 : params_iter_impl::
69 : setup() noexcept
70 : {
71 2410 : dk = 1;
72 2410 : dv = 0;
73 2410 : auto const end = ref.end();
74 2410 : BOOST_ASSERT(pos != ref.size());
75 2410 : auto p0 = ref.begin() + pos;
76 2410 : auto p = p0;
77 : // key
78 : for(;;)
79 : {
80 9470 : if( p == end ||
81 9408 : *p == '&')
82 : {
83 : // no value
84 348 : nk = 1 + p - p0;
85 348 : dk = nk - dk;
86 348 : nv = 0;
87 348 : return;
88 : }
89 9122 : if(*p == '=')
90 2062 : break;
91 7060 : if(*p == '%')
92 : {
93 238 : BOOST_ASSERT(
94 : end - p >= 3);
95 238 : dk += 2;
96 238 : p += 2;
97 : }
98 7060 : ++p;
99 : }
100 2062 : nk = 1 + p - p0;
101 2062 : dk = nk - dk;
102 2062 : p0 = p;
103 :
104 : // value
105 : for(;;)
106 : {
107 8498 : ++p;
108 8498 : if( p == end ||
109 7874 : *p == '&')
110 : break;
111 6436 : if(*p == '%')
112 : {
113 192 : BOOST_ASSERT(
114 : end - p >= 3);
115 192 : dv += 2;
116 192 : p += 2;
117 : }
118 : }
119 2062 : nv = p - p0;
120 2062 : dv = nv - dv - 1;
121 : }
122 :
123 : inline
124 : void
125 2299 : params_iter_impl::
126 : increment() noexcept
127 : {
128 2299 : BOOST_ASSERT(
129 : index < ref.nparam());
130 2299 : pos += nk + nv;
131 2299 : ++index;
132 2299 : if(index < ref.nparam())
133 1667 : setup();
134 2299 : }
135 :
136 : inline
137 : void
138 1370 : params_iter_impl::
139 : decrement() noexcept
140 : {
141 1370 : BOOST_ASSERT(index > 0);
142 1370 : --index;
143 1370 : dk = 1; // for '&' or '?'
144 1370 : dv = 1; // for '='
145 1370 : auto const begin = ref.begin();
146 1370 : BOOST_ASSERT(pos > 0);
147 1370 : auto p1 = begin + (pos - 1);
148 1370 : auto p = p1;
149 : // find key or '='
150 : for(;;)
151 : {
152 7634 : if(p == begin)
153 : {
154 : // key
155 220 : nk = 1 + p1 - p; // with '?'
156 220 : dk = nk - dv;
157 220 : nv = 0;
158 220 : dv = 0;
159 220 : pos -= nk;
160 220 : return;
161 : }
162 7414 : else if(*--p == '&')
163 : {
164 : // key
165 94 : nk = p1 - p; // with '&'
166 94 : dk = nk - dv;
167 94 : nv = 0;
168 94 : dv = 0;
169 94 : pos -= nk;
170 94 : return;
171 : }
172 7320 : if(*p == '=')
173 : {
174 : // value
175 1056 : nv = p1 - p; // with '='
176 1056 : break;
177 : }
178 6264 : if(*p == '%')
179 144 : dv += 2;
180 : }
181 : // find key and value
182 : for(;;)
183 : {
184 5414 : if(p == begin)
185 : {
186 : // key and value
187 284 : nk = 1 + p1 - p - nv; // with '?'
188 284 : dk = nk - dk;
189 284 : dv = nv - dv;
190 284 : pos -= nk + nv;
191 284 : return;
192 : }
193 5130 : if(*--p == '&')
194 : {
195 : // key and value
196 772 : nk = p1 - p - nv; // with '&'
197 772 : dk = nk - dk;
198 772 : dv = nv - dv;
199 772 : pos -= nk + nv;
200 772 : return;
201 : }
202 4358 : if(*p == '=')
203 : {
204 : // value
205 36 : nv = p1 - p; // with '='
206 36 : dv += dk - 1;
207 36 : dk = 1;
208 : }
209 4322 : else if(*p == '%')
210 : {
211 60 : dk += 2;
212 : }
213 : }
214 : }
215 :
216 : inline
217 : param_pct_view
218 1522 : params_iter_impl::
219 : dereference() const noexcept
220 : {
221 1522 : BOOST_ASSERT(index < ref.nparam());
222 1522 : BOOST_ASSERT(pos < ref.size());
223 1522 : auto const p = ref.begin() + pos;
224 1522 : if(nv)
225 : return {
226 1187 : make_pct_string_view_unsafe(
227 1187 : p, nk - 1, dk),
228 : make_pct_string_view_unsafe(
229 1187 : p + nk, nv - 1, dv)};
230 : return {
231 : make_pct_string_view_unsafe(
232 335 : p, nk - 1, dk),
233 335 : no_value};
234 : }
235 :
236 : inline
237 : pct_string_view
238 850 : params_iter_impl::
239 : key() const noexcept
240 : {
241 850 : BOOST_ASSERT(index < ref.nparam());
242 850 : BOOST_ASSERT(pos < ref.size());
243 850 : auto const p = ref.begin() + pos;
244 850 : return make_pct_string_view_unsafe(
245 850 : p, nk - 1, dk);
246 : }
247 :
248 : } // detail
249 : } // urls
250 : } // boost
251 :
252 : #endif
|