Line data Source code
1 : // 2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 3 : // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) 4 : // 5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 : // 8 : // Official repository: https://github.com/boostorg/url 9 : // 10 : 11 : 12 : #include <boost/url/detail/config.hpp> 13 : #include "path.hpp" 14 : #include <boost/url/detail/segments_iter_impl.hpp> 15 : #include "boost/url/rfc/detail/path_rules.hpp" 16 : #include <boost/assert.hpp> 17 : 18 : namespace boost { 19 : namespace urls { 20 : namespace detail { 21 : 22 : // begin 23 2203 : segments_iter_impl:: 24 : segments_iter_impl( 25 2203 : detail::path_ref const& ref_) noexcept 26 2203 : : ref(ref_) 27 : { 28 2203 : pos = path_prefix(ref.buffer()); 29 2203 : update(); 30 2203 : } 31 : 32 : // end 33 1802 : segments_iter_impl:: 34 : segments_iter_impl( 35 : detail::path_ref const& ref_, 36 1802 : int) noexcept 37 : : ref(ref_) 38 1802 : , pos(ref.size()) 39 1802 : , next(ref.size()) 40 1802 : , index(ref.nseg()) 41 : { 42 1802 : } 43 : 44 595 : segments_iter_impl:: 45 : segments_iter_impl( 46 : url_impl const& u_, 47 : std::size_t pos_, 48 595 : std::size_t index_) noexcept 49 : : ref(u_) 50 : , pos(pos_) 51 595 : , index(index_) 52 : { 53 595 : if(index == 0) 54 : { 55 272 : pos = path_prefix(ref.buffer()); 56 : } 57 323 : else if(pos != ref.size()) 58 : { 59 199 : BOOST_ASSERT( 60 : ref.data()[pos] == '/'); 61 199 : ++pos; // skip '/' 62 : } 63 595 : update(); 64 595 : } 65 : 66 : void 67 2798 : segments_iter_impl:: 68 : update() noexcept 69 : { 70 2798 : auto const end = ref.end(); 71 : char const* const p0 = 72 2798 : ref.data() + pos; 73 2798 : dn = 0; 74 2798 : auto p = p0; 75 10449 : while(p != end) 76 : { 77 9213 : if(*p == '/') 78 1562 : break; 79 7651 : if(*p != '%') 80 : { 81 7286 : ++p; 82 7286 : continue; 83 : } 84 365 : p += 3; 85 365 : dn += 2; 86 : } 87 2798 : next = p - ref.data(); 88 2798 : dn = p - p0 - dn; 89 : s_ = make_pct_string_view_unsafe( 90 2798 : p0, p - p0, dn); 91 2798 : } 92 : 93 : void 94 2753 : segments_iter_impl:: 95 : increment() noexcept 96 : { 97 2753 : BOOST_ASSERT( 98 : index != ref.nseg()); 99 2753 : ++index; 100 2753 : pos = next; 101 2753 : if(index == ref.nseg()) 102 1130 : return; 103 : // "/" segment 104 1623 : auto const end = ref.end(); 105 1623 : auto p = ref.data() + pos; 106 1623 : BOOST_ASSERT(p != end); 107 1623 : BOOST_ASSERT(*p == '/'); 108 1623 : dn = 0; 109 1623 : ++p; // skip '/' 110 1623 : auto const p0 = p; 111 7151 : while(p != end) 112 : { 113 6465 : if(*p == '/') 114 937 : break; 115 5528 : if(*p != '%') 116 : { 117 5416 : ++p; 118 5416 : continue; 119 : } 120 112 : p += 3; 121 112 : dn += 2; 122 : } 123 1623 : next = p - ref.data(); 124 1623 : dn = p - p0 - dn; 125 : s_ = make_pct_string_view_unsafe( 126 1623 : p0, p - p0, dn); 127 : } 128 : 129 : void 130 1553 : segments_iter_impl:: 131 : decrement() noexcept 132 : { 133 1553 : BOOST_ASSERT(index != 0); 134 1553 : --index; 135 1553 : if(index == 0) 136 : { 137 521 : next = pos; 138 521 : pos = path_prefix(ref.buffer()); 139 521 : s_ = core::string_view( 140 521 : ref.data() + pos, 141 521 : next - pos); 142 521 : BOOST_ASSERT(! s_.ends_with('/')); 143 521 : return; 144 : } 145 1032 : auto const begin = ref.data() + 146 1032 : path_prefix(ref.buffer()); 147 1032 : next = pos; 148 1032 : auto p = ref.data() + next; 149 1032 : auto const p1 = p; 150 1032 : BOOST_ASSERT(p != begin); 151 1032 : dn = 0; 152 3182 : while(p != begin) 153 : { 154 3182 : --p; 155 3182 : if(*p == '/') 156 : { 157 1032 : ++dn; 158 1032 : break; 159 : } 160 2150 : if(*p == '%') 161 28 : dn += 2; 162 : } 163 1032 : dn = p1 - p - dn; 164 1032 : pos = p - ref.data(); 165 : s_ = make_pct_string_view_unsafe( 166 1032 : p + 1, p1 - p - 1, dn); 167 : } 168 : 169 : } // detail 170 : } // url 171 : } // boost 172 :