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

source code of boost/libs/url/src/detail/params_iter_impl.cpp