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 : : ref(ref_) 30 : , 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 : : 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 : : ref(ref_) 53 : , 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 : 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 : return make_pct_string_view_unsafe( 237 812 : p, nk - 1, dk); 238 : } 239 : 240 : } // detail 241 : } // url 242 : } // boost 243 :