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 7315 : params_iter_impl::
28 : params_iter_impl(
29 7315 : query_ref const& ref_) noexcept
30 7315 : : ref(ref_)
31 7315 : , index(0)
32 7315 : , pos(0)
33 : {
34 7315 : if(index < ref_.nparam())
35 4337 : setup();
36 7315 : }
37 :
38 : inline
39 12876 : params_iter_impl::
40 : params_iter_impl(
41 : query_ref const& ref_,
42 12876 : int) noexcept
43 12876 : : ref(ref_)
44 12876 : , index(ref_.nparam())
45 12876 : , pos(ref_.size())
46 : {
47 12876 : }
48 :
49 : inline
50 1700 : params_iter_impl::
51 : params_iter_impl(
52 : query_ref const& ref_,
53 : std::size_t pos_,
54 1700 : std::size_t index_) noexcept
55 1700 : : ref(ref_)
56 1700 : , index(index_)
57 1700 : , pos(pos_)
58 : {
59 1700 : BOOST_ASSERT(
60 : pos <= ref.size());
61 1700 : if(index < ref_.nparam())
62 1538 : setup();
63 1700 : }
64 :
65 : // set up state for key/value at pos
66 : inline
67 : void
68 10164 : params_iter_impl::
69 : setup() noexcept
70 : {
71 10164 : dk = 1;
72 10164 : dv = 0;
73 10164 : auto const end = ref.end();
74 10164 : BOOST_ASSERT(pos != ref.size());
75 10164 : auto p0 = ref.begin() + pos;
76 10164 : auto p = p0;
77 : // key
78 : for(;;)
79 : {
80 37870 : if( p == end ||
81 37312 : *p == '&')
82 : {
83 : // no value
84 927 : nk = 1 + p - p0;
85 927 : dk = nk - dk;
86 927 : nv = 0;
87 927 : return;
88 : }
89 36943 : if(*p == '=')
90 9237 : break;
91 27706 : if(*p == '%')
92 : {
93 2460 : BOOST_ASSERT(
94 : end - p >= 3);
95 2460 : dk += 2;
96 2460 : p += 2;
97 : }
98 27706 : ++p;
99 : }
100 9237 : nk = 1 + p - p0;
101 9237 : dk = nk - dk;
102 9237 : p0 = p;
103 :
104 : // value
105 : for(;;)
106 : {
107 51518 : ++p;
108 51518 : if( p == end ||
109 46803 : *p == '&')
110 : break;
111 42281 : if(*p == '%')
112 : {
113 5713 : BOOST_ASSERT(
114 : end - p >= 3);
115 5713 : dv += 2;
116 5713 : p += 2;
117 : }
118 : }
119 9237 : nv = p - p0;
120 9237 : dv = nv - dv - 1;
121 : }
122 :
123 : inline
124 : void
125 8242 : params_iter_impl::
126 : increment() noexcept
127 : {
128 8242 : BOOST_ASSERT(
129 : index < ref.nparam());
130 8242 : pos += nk + nv;
131 8242 : ++index;
132 8242 : if(index < ref.nparam())
133 4289 : setup();
134 8242 : }
135 :
136 : inline
137 : void
138 1374 : params_iter_impl::
139 : decrement() noexcept
140 : {
141 1374 : BOOST_ASSERT(index > 0);
142 1374 : --index;
143 1374 : dk = 1; // for '&' or '?'
144 1374 : dv = 1; // for '='
145 1374 : auto const begin = ref.begin();
146 1374 : BOOST_ASSERT(pos > 0);
147 1374 : auto p1 = begin + (pos - 1);
148 1374 : auto p = p1;
149 : // find key or '='
150 : for(;;)
151 : {
152 7660 : 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 7440 : 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 7346 : if(*p == '=')
173 : {
174 : // value
175 1060 : nv = p1 - p; // with '='
176 1060 : break;
177 : }
178 6286 : if(*p == '%')
179 147 : dv += 2;
180 : }
181 : // find key and value
182 : for(;;)
183 : {
184 5436 : if(p == begin)
185 : {
186 : // key and value
187 286 : nk = 1 + p1 - p - nv; // with '?'
188 286 : dk = nk - dk;
189 286 : dv = nv - dv;
190 286 : pos -= nk + nv;
191 286 : return;
192 : }
193 5150 : if(*--p == '&')
194 : {
195 : // key and value
196 774 : nk = p1 - p - nv; // with '&'
197 774 : dk = nk - dk;
198 774 : dv = nv - dv;
199 774 : pos -= nk + nv;
200 774 : return;
201 : }
202 4376 : if(*p == '=')
203 : {
204 : // value
205 36 : nv = p1 - p; // with '='
206 36 : dv += dk - 1;
207 36 : dk = 1;
208 : }
209 4340 : else if(*p == '%')
210 : {
211 60 : dk += 2;
212 : }
213 : }
214 : }
215 :
216 : inline
217 : param_pct_view
218 6656 : params_iter_impl::
219 : dereference() const noexcept
220 : {
221 6656 : BOOST_ASSERT(index < ref.nparam());
222 6656 : BOOST_ASSERT(pos < ref.size());
223 6656 : auto const p = ref.begin() + pos;
224 6656 : if(nv)
225 : return {
226 5801 : make_pct_string_view_unsafe(
227 5801 : p, nk - 1, dk),
228 : make_pct_string_view_unsafe(
229 5801 : p + nk, nv - 1, dv)};
230 : return {
231 : make_pct_string_view_unsafe(
232 855 : p, nk - 1, dk),
233 855 : no_value};
234 : }
235 :
236 : inline
237 : pct_string_view
238 1005 : params_iter_impl::
239 : key() const noexcept
240 : {
241 1005 : BOOST_ASSERT(index < ref.nparam());
242 1005 : BOOST_ASSERT(pos < ref.size());
243 1005 : auto const p = ref.begin() + pos;
244 1005 : return make_pct_string_view_unsafe(
245 1005 : p, nk - 1, dk);
246 : }
247 :
248 : } // detail
249 : } // urls
250 : } // boost
251 :
252 : #endif
|