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 604 : params_iter_impl::
27 : params_iter_impl(
28 604 : query_ref const& ref_) noexcept
29 604 : : ref(ref_)
30 604 : , index(0)
31 604 : , pos(0)
32 : {
33 604 : if(index < ref_.nparam())
34 555 : setup();
35 604 : }
36 :
37 654 : params_iter_impl::
38 : params_iter_impl(
39 : query_ref const& ref_,
40 654 : int) noexcept
41 654 : : ref(ref_)
42 654 : , index(ref_.nparam())
43 654 : , pos(ref_.size())
44 : {
45 654 : }
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 2282 : params_iter_impl::
65 : setup() noexcept
66 : {
67 2282 : dk = 1;
68 2282 : dv = 0;
69 2282 : auto const end = ref.end();
70 2282 : BOOST_ASSERT(pos != ref.size());
71 2282 : auto p0 = ref.begin() + pos;
72 2282 : auto p = p0;
73 : // key
74 : for(;;)
75 : {
76 8906 : if( p == end ||
77 8847 : *p == '&')
78 : {
79 : // no value
80 333 : nk = 1 + p - p0;
81 333 : dk = nk - dk;
82 333 : nv = 0;
83 333 : return;
84 : }
85 8573 : if(*p == '=')
86 1949 : break;
87 6624 : if(*p == '%')
88 : {
89 228 : BOOST_ASSERT(
90 : end - p >= 3);
91 228 : dk += 2;
92 228 : p += 2;
93 : }
94 6624 : ++p;
95 : }
96 1949 : nk = 1 + p - p0;
97 1949 : dk = nk - dk;
98 1949 : p0 = p;
99 :
100 : // value
101 : for(;;)
102 : {
103 7842 : ++p;
104 7842 : if( p == end ||
105 7274 : *p == '&')
106 : break;
107 5893 : if(*p == '%')
108 : {
109 198 : BOOST_ASSERT(
110 : end - p >= 3);
111 198 : dv += 2;
112 198 : p += 2;
113 : }
114 : }
115 1949 : nv = p - p0;
116 1949 : dv = nv - dv - 1;
117 : }
118 :
119 : void
120 2176 : params_iter_impl::
121 : increment() noexcept
122 : {
123 2176 : BOOST_ASSERT(
124 : index < ref.nparam());
125 2176 : pos += nk + nv;
126 2176 : ++index;
127 2176 : if(index < ref.nparam())
128 1602 : setup();
129 2176 : }
130 :
131 : void
132 1312 : params_iter_impl::
133 : decrement() noexcept
134 : {
135 1312 : BOOST_ASSERT(index > 0);
136 1312 : --index;
137 1312 : dk = 1; // for '&' or '?'
138 1312 : dv = 1; // for '='
139 1312 : auto const begin = ref.begin();
140 1312 : BOOST_ASSERT(pos > 0);
141 1312 : auto p1 = begin + (pos - 1);
142 1312 : auto p = p1;
143 : // find key or '='
144 : for(;;)
145 : {
146 7566 : if(p == begin)
147 : {
148 : // key
149 216 : nk = 1 + p1 - p; // with '?'
150 216 : dk = nk - dv;
151 216 : nv = 0;
152 216 : dv = 0;
153 216 : pos -= nk;
154 216 : return;
155 : }
156 7350 : 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 7256 : if(*p == '=')
167 : {
168 : // value
169 1002 : nv = p1 - p; // with '='
170 1002 : break;
171 : }
172 6254 : if(*p == '%')
173 176 : dv += 2;
174 : }
175 : // find key and value
176 : for(;;)
177 : {
178 5238 : if(p == begin)
179 : {
180 : // key and value
181 248 : nk = 1 + p1 - p - nv; // with '?'
182 248 : dk = nk - dk;
183 248 : dv = nv - dv;
184 248 : pos -= nk + nv;
185 248 : return;
186 : }
187 4990 : if(*--p == '&')
188 : {
189 : // key and value
190 754 : nk = p1 - p - nv; // with '&'
191 754 : dk = nk - dk;
192 754 : dv = nv - dv;
193 754 : pos -= nk + nv;
194 754 : return;
195 : }
196 4236 : if(*p == '=')
197 : {
198 : // value
199 0 : nv = p1 - p; // with '='
200 0 : dv += dk;
201 0 : dk = 0;
202 : }
203 4236 : else if(*p == '%')
204 : {
205 60 : dk += 2;
206 : }
207 : }
208 : }
209 :
210 : param_pct_view
211 1401 : params_iter_impl::
212 : dereference() const noexcept
213 : {
214 1401 : BOOST_ASSERT(index < ref.nparam());
215 1401 : BOOST_ASSERT(pos < ref.size());
216 1401 : auto const p = ref.begin() + pos;
217 1401 : if(nv)
218 : return {
219 1082 : make_pct_string_view_unsafe(
220 1082 : p, nk - 1, dk),
221 : make_pct_string_view_unsafe(
222 1082 : p + nk, nv - 1, dv)};
223 : return {
224 : make_pct_string_view_unsafe(
225 319 : p, nk - 1, dk),
226 319 : 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 :
|