include/boost/url/detail/impl/params_iter_impl.hpp

100.0% Lines (124/124) 100.0% Functions (8/8)
include/boost/url/detail/impl/params_iter_impl.hpp
Line TLA Hits 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 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
253