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