99.13% Lines (114/115)
100.00% Functions (6/6)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | |||||
| 3 | // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) | 3 | // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) | |||||
| 4 | // | 4 | // | |||||
| 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 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) | 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 7 | // | 7 | // | |||||
| 8 | // Official repository: https://github.com/boostorg/url | 8 | // Official repository: https://github.com/boostorg/url | |||||
| 9 | // | 9 | // | |||||
| 10 | 10 | |||||||
| 11 | #ifndef BOOST_URL_DETAIL_IMPL_SEGMENTS_ITER_IMPL_HPP | 11 | #ifndef BOOST_URL_DETAIL_IMPL_SEGMENTS_ITER_IMPL_HPP | |||||
| 12 | #define BOOST_URL_DETAIL_IMPL_SEGMENTS_ITER_IMPL_HPP | 12 | #define BOOST_URL_DETAIL_IMPL_SEGMENTS_ITER_IMPL_HPP | |||||
| 13 | 13 | |||||||
| 14 | #include <boost/url/detail/decode.hpp> | 14 | #include <boost/url/detail/decode.hpp> | |||||
| 15 | #include <boost/url/detail/path.hpp> | 15 | #include <boost/url/detail/path.hpp> | |||||
| 16 | #include <boost/assert.hpp> | 16 | #include <boost/assert.hpp> | |||||
| 17 | 17 | |||||||
| 18 | namespace boost { | 18 | namespace boost { | |||||
| 19 | namespace urls { | 19 | namespace urls { | |||||
| 20 | namespace detail { | 20 | namespace detail { | |||||
| 21 | 21 | |||||||
| 22 | // begin | 22 | // begin | |||||
| 23 | inline | 23 | inline | |||||
| HITCBC | 24 | 9364 | segments_iter_impl:: | 24 | 9364 | segments_iter_impl:: | ||
| 25 | segments_iter_impl( | 25 | segments_iter_impl( | |||||
| HITCBC | 26 | 9364 | detail::path_ref const& ref_) noexcept | 26 | 9364 | detail::path_ref const& ref_) noexcept | ||
| HITCBC | 27 | 9364 | : ref(ref_) | 27 | 9364 | : ref(ref_) | ||
| 28 | { | 28 | { | |||||
| HITCBC | 29 | 9364 | pos = path_prefix(ref.buffer()); | 29 | 9364 | pos = path_prefix(ref.buffer()); | ||
| 30 | // begin() starts after any malleable prefix but remembers decoded chars skipped | 30 | // begin() starts after any malleable prefix but remembers decoded chars skipped | |||||
| HITCBC | 31 | 9364 | decoded_prefix = pos; | 31 | 9364 | decoded_prefix = pos; | ||
| HITCBC | 32 | 9364 | update(); | 32 | 9364 | update(); | ||
| HITCBC | 33 | 9364 | } | 33 | 9364 | } | ||
| 34 | 34 | |||||||
| 35 | // end | 35 | // end | |||||
| 36 | inline | 36 | inline | |||||
| HITCBC | 37 | 16416 | segments_iter_impl:: | 37 | 16416 | segments_iter_impl:: | ||
| 38 | segments_iter_impl( | 38 | segments_iter_impl( | |||||
| 39 | detail::path_ref const& ref_, | 39 | detail::path_ref const& ref_, | |||||
| HITCBC | 40 | 16416 | int) noexcept | 40 | 16416 | int) noexcept | ||
| HITCBC | 41 | 16416 | : ref(ref_) | 41 | 16416 | : ref(ref_) | ||
| HITCBC | 42 | 16416 | , pos(ref.size()) | 42 | 16416 | , pos(ref.size()) | ||
| HITCBC | 43 | 16416 | , next(ref.size()) | 43 | 16416 | , next(ref.size()) | ||
| HITCBC | 44 | 16416 | , index(ref.nseg()) | 44 | 16416 | , index(ref.nseg()) | ||
| 45 | { | 45 | { | |||||
| 46 | // end() carries the total decoded length for O(1) range math | 46 | // end() carries the total decoded length for O(1) range math | |||||
| HITCBC | 47 | 16416 | decoded_prefix = ref.decoded_size(); | 47 | 16416 | decoded_prefix = ref.decoded_size(); | ||
| HITCBC | 48 | 16416 | } | 48 | 16416 | } | ||
| 49 | 49 | |||||||
| 50 | inline | 50 | inline | |||||
| HITCBC | 51 | 2313 | segments_iter_impl:: | 51 | 2313 | segments_iter_impl:: | ||
| 52 | segments_iter_impl( | 52 | segments_iter_impl( | |||||
| 53 | url_impl const& u_, | 53 | url_impl const& u_, | |||||
| 54 | std::size_t pos_, | 54 | std::size_t pos_, | |||||
| HITCBC | 55 | 2313 | std::size_t index_) noexcept | 55 | 2313 | std::size_t index_) noexcept | ||
| HITCBC | 56 | 2313 | : ref(u_) | 56 | 2313 | : ref(u_) | ||
| HITCBC | 57 | 2313 | , pos(pos_) | 57 | 2313 | , pos(pos_) | ||
| HITCBC | 58 | 2313 | , index(index_) | 58 | 2313 | , index(index_) | ||
| 59 | { | 59 | { | |||||
| HITCBC | 60 | 2313 | auto const total = ref.nseg(); | 60 | 2313 | auto const total = ref.nseg(); | ||
| HITCBC | 61 | 2313 | if(index >= total) | 61 | 2313 | if(index >= total) | ||
| 62 | { | 62 | { | |||||
| HITCBC | 63 | 961 | pos = ref.size(); | 63 | 961 | pos = ref.size(); | ||
| HITCBC | 64 | 961 | next = ref.size(); | 64 | 961 | next = ref.size(); | ||
| HITCBC | 65 | 961 | decoded_prefix = ref.decoded_size(); | 65 | 961 | decoded_prefix = ref.decoded_size(); | ||
| 66 | // iterator equal to end: nothing to decode | 66 | // iterator equal to end: nothing to decode | |||||
| HITCBC | 67 | 961 | dn = 0; | 67 | 961 | dn = 0; | ||
| HITCBC | 68 | 961 | return; | 68 | 961 | return; | ||
| 69 | } | 69 | } | |||||
| 70 | 70 | |||||||
| HITCBC | 71 | 1352 | if(index == 0) | 71 | 1352 | if(index == 0) | ||
| 72 | { | 72 | { | |||||
| HITCBC | 73 | 763 | pos = path_prefix(ref.buffer()); | 73 | 763 | pos = path_prefix(ref.buffer()); | ||
| 74 | // first segment inherits the prefix size (including leading '/') | 74 | // first segment inherits the prefix size (including leading '/') | |||||
| HITCBC | 75 | 763 | decoded_prefix = pos; | 75 | 763 | decoded_prefix = pos; | ||
| HITCBC | 76 | 763 | update(); | 76 | 763 | update(); | ||
| HITCBC | 77 | 763 | return; | 77 | 763 | return; | ||
| 78 | } | 78 | } | |||||
| 79 | 79 | |||||||
| HITCBC | 80 | 589 | BOOST_ASSERT(pos <= ref.size()); | 80 | 589 | BOOST_ASSERT(pos <= ref.size()); | ||
| 81 | // compute decoded prefix by scanning once up to the encoded offset | 81 | // compute decoded prefix by scanning once up to the encoded offset | |||||
| HITCBC | 82 | 589 | decoded_prefix = detail::decode_bytes_unsafe( | 82 | 589 | decoded_prefix = detail::decode_bytes_unsafe( | ||
| 83 | core::string_view(ref.data(), pos)); | 83 | core::string_view(ref.data(), pos)); | |||||
| HITCBC | 84 | 589 | if(pos != ref.size()) | 84 | 589 | if(pos != ref.size()) | ||
| 85 | { | 85 | { | |||||
| HITCBC | 86 | 589 | BOOST_ASSERT( | 86 | 589 | BOOST_ASSERT( | ||
| 87 | ref.data()[pos] == '/'); | 87 | ref.data()[pos] == '/'); | |||||
| HITCBC | 88 | 589 | ++pos; // skip '/' | 88 | 589 | ++pos; // skip '/' | ||
| HITCBC | 89 | 589 | update(); | 89 | 589 | update(); | ||
| HITCBC | 90 | 589 | --pos; | 90 | 589 | --pos; | ||
| HITCBC | 91 | 589 | return; | 91 | 589 | return; | ||
| 92 | } | 92 | } | |||||
| 93 | 93 | |||||||
| MISUBC | 94 | ✗ | update(); | 94 | ✗ | update(); | ||
| 95 | } | 95 | } | |||||
| 96 | 96 | |||||||
| 97 | inline | 97 | inline | |||||
| 98 | void | 98 | void | |||||
| HITCBC | 99 | 12695 | segments_iter_impl:: | 99 | 12695 | segments_iter_impl:: | ||
| 100 | update() noexcept | 100 | update() noexcept | |||||
| 101 | { | 101 | { | |||||
| HITCBC | 102 | 12695 | BOOST_ASSERT( | 102 | 12695 | BOOST_ASSERT( | ||
| 103 | pos == 0 || | 103 | pos == 0 || | |||||
| 104 | ref.data()[pos - 1] == '/'); | 104 | ref.data()[pos - 1] == '/'); | |||||
| HITCBC | 105 | 12695 | auto const end = ref.end(); | 105 | 12695 | auto const end = ref.end(); | ||
| 106 | char const* const p0 = | 106 | char const* const p0 = | |||||
| HITCBC | 107 | 12695 | ref.data() + pos; | 107 | 12695 | ref.data() + pos; | ||
| HITCBC | 108 | 12695 | dn = 0; | 108 | 12695 | dn = 0; | ||
| HITCBC | 109 | 12695 | auto p = p0; | 109 | 12695 | auto p = p0; | ||
| HITCBC | 110 | 56663 | while(p != end) | 110 | 56663 | while(p != end) | ||
| 111 | { | 111 | { | |||||
| HITCBC | 112 | 49262 | if(*p == '/') | 112 | 49262 | if(*p == '/') | ||
| HITCBC | 113 | 5294 | break; | 113 | 5294 | break; | ||
| HITCBC | 114 | 43968 | if(*p != '%') | 114 | 43968 | if(*p != '%') | ||
| 115 | { | 115 | { | |||||
| HITCBC | 116 | 39695 | ++p; | 116 | 39695 | ++p; | ||
| HITCBC | 117 | 39695 | continue; | 117 | 39695 | continue; | ||
| 118 | } | 118 | } | |||||
| HITCBC | 119 | 4273 | p += 3; | 119 | 4273 | p += 3; | ||
| HITCBC | 120 | 4273 | dn += 2; | 120 | 4273 | dn += 2; | ||
| 121 | } | 121 | } | |||||
| HITCBC | 122 | 12695 | next = p - ref.data(); | 122 | 12695 | next = p - ref.data(); | ||
| HITCBC | 123 | 12695 | dn = p - p0 - dn; | 123 | 12695 | dn = p - p0 - dn; | ||
| HITCBC | 124 | 12695 | s_ = make_pct_string_view_unsafe( | 124 | 12695 | s_ = make_pct_string_view_unsafe( | ||
| HITCBC | 125 | 12695 | p0, p - p0, dn); | 125 | 12695 | p0, p - p0, dn); | ||
| HITCBC | 126 | 12695 | } | 126 | 12695 | } | ||
| 127 | 127 | |||||||
| 128 | inline | 128 | inline | |||||
| 129 | void | 129 | void | |||||
| HITCBC | 130 | 10857 | segments_iter_impl:: | 130 | 10857 | segments_iter_impl:: | ||
| 131 | increment() noexcept | 131 | increment() noexcept | |||||
| 132 | { | 132 | { | |||||
| HITCBC | 133 | 10857 | BOOST_ASSERT( | 133 | 10857 | BOOST_ASSERT( | ||
| 134 | index != ref.nseg()); | 134 | index != ref.nseg()); | |||||
| HITCBC | 135 | 10857 | auto const old_index = index; | 135 | 10857 | auto const old_index = index; | ||
| HITCBC | 136 | 10857 | auto const old_dn = dn; | 136 | 10857 | auto const old_dn = dn; | ||
| 137 | // add decoded length of previous segment | 137 | // add decoded length of previous segment | |||||
| HITCBC | 138 | 10857 | decoded_prefix += old_dn; | 138 | 10857 | decoded_prefix += old_dn; | ||
| HITCBC | 139 | 10857 | if(old_index > 0) | 139 | 10857 | if(old_index > 0) | ||
| 140 | // account for the '/' separator we just crossed | 140 | // account for the '/' separator we just crossed | |||||
| HITCBC | 141 | 6005 | ++decoded_prefix; | 141 | 6005 | ++decoded_prefix; | ||
| HITCBC | 142 | 10857 | ++index; | 142 | 10857 | ++index; | ||
| HITCBC | 143 | 10857 | pos = next; | 143 | 10857 | pos = next; | ||
| HITCBC | 144 | 10857 | if(index == ref.nseg()) | 144 | 10857 | if(index == ref.nseg()) | ||
| HITCBC | 145 | 4765 | return; | 145 | 4765 | return; | ||
| 146 | // "/" segment | 146 | // "/" segment | |||||
| HITCBC | 147 | 6092 | auto const end = ref.end(); | 147 | 6092 | auto const end = ref.end(); | ||
| HITCBC | 148 | 6092 | auto p = ref.data() + pos; | 148 | 6092 | auto p = ref.data() + pos; | ||
| HITCBC | 149 | 6092 | BOOST_ASSERT(p != end); | 149 | 6092 | BOOST_ASSERT(p != end); | ||
| HITCBC | 150 | 6092 | BOOST_ASSERT(*p == '/'); | 150 | 6092 | BOOST_ASSERT(*p == '/'); | ||
| HITCBC | 151 | 6092 | dn = 0; | 151 | 6092 | dn = 0; | ||
| HITCBC | 152 | 6092 | ++p; // skip '/' | 152 | 6092 | ++p; // skip '/' | ||
| HITCBC | 153 | 6092 | auto const p0 = p; | 153 | 6092 | auto const p0 = p; | ||
| HITCBC | 154 | 31779 | while(p != end) | 154 | 31779 | while(p != end) | ||
| 155 | { | 155 | { | |||||
| HITCBC | 156 | 28672 | if(*p == '/') | 156 | 28672 | if(*p == '/') | ||
| HITCBC | 157 | 2985 | break; | 157 | 2985 | break; | ||
| HITCBC | 158 | 25687 | if(*p != '%') | 158 | 25687 | if(*p != '%') | ||
| 159 | { | 159 | { | |||||
| HITCBC | 160 | 24649 | ++p; | 160 | 24649 | ++p; | ||
| HITCBC | 161 | 24649 | continue; | 161 | 24649 | continue; | ||
| 162 | } | 162 | } | |||||
| HITCBC | 163 | 1038 | p += 3; | 163 | 1038 | p += 3; | ||
| HITCBC | 164 | 1038 | dn += 2; | 164 | 1038 | dn += 2; | ||
| 165 | } | 165 | } | |||||
| HITCBC | 166 | 6092 | next = p - ref.data(); | 166 | 6092 | next = p - ref.data(); | ||
| HITCBC | 167 | 6092 | dn = p - p0 - dn; | 167 | 6092 | dn = p - p0 - dn; | ||
| HITCBC | 168 | 6092 | s_ = make_pct_string_view_unsafe( | 168 | 6092 | s_ = make_pct_string_view_unsafe( | ||
| HITCBC | 169 | 6092 | p0, p - p0, dn); | 169 | 6092 | p0, p - p0, dn); | ||
| 170 | } | 170 | } | |||||
| 171 | 171 | |||||||
| 172 | inline | 172 | inline | |||||
| 173 | void | 173 | void | |||||
| HITCBC | 174 | 1979 | segments_iter_impl:: | 174 | 1979 | segments_iter_impl:: | ||
| 175 | decrement() noexcept | 175 | decrement() noexcept | |||||
| 176 | { | 176 | { | |||||
| HITCBC | 177 | 1979 | BOOST_ASSERT(index != 0); | 177 | 1979 | BOOST_ASSERT(index != 0); | ||
| HITCBC | 178 | 1979 | auto const current_dn = dn; | 178 | 1979 | auto const current_dn = dn; | ||
| HITCBC | 179 | 1979 | auto const current_index = index; | 179 | 1979 | auto const current_index = index; | ||
| 180 | // remove the decoded length of the segment we're leaving | 180 | // remove the decoded length of the segment we're leaving | |||||
| HITCBC | 181 | 1979 | decoded_prefix -= current_dn; | 181 | 1979 | decoded_prefix -= current_dn; | ||
| HITCBC | 182 | 1979 | if(current_index > 0 && decoded_prefix > 0) | 182 | 1979 | if(current_index > 0 && decoded_prefix > 0) | ||
| 183 | // drop the '/' separator when stepping left of it | 183 | // drop the '/' separator when stepping left of it | |||||
| HITCBC | 184 | 1979 | --decoded_prefix; | 184 | 1979 | --decoded_prefix; | ||
| HITCBC | 185 | 1979 | --index; | 185 | 1979 | --index; | ||
| HITCBC | 186 | 1979 | if(index == 0) | 186 | 1979 | if(index == 0) | ||
| 187 | { | 187 | { | |||||
| HITCBC | 188 | 794 | pos = path_prefix(ref.buffer()); | 188 | 794 | pos = path_prefix(ref.buffer()); | ||
| HITCBC | 189 | 794 | decoded_prefix = pos; | 189 | 794 | decoded_prefix = pos; | ||
| HITCBC | 190 | 794 | update(); | 190 | 794 | update(); | ||
| HITCBC | 191 | 794 | BOOST_ASSERT(! s_.ends_with('/')); | 191 | 794 | BOOST_ASSERT(! s_.ends_with('/')); | ||
| HITCBC | 192 | 794 | return; | 192 | 794 | return; | ||
| 193 | } | 193 | } | |||||
| 194 | // scan backwards to find the '/' before | 194 | // scan backwards to find the '/' before | |||||
| 195 | // the previous segment | 195 | // the previous segment | |||||
| HITCBC | 196 | 1185 | auto const begin = ref.data() + | 196 | 1185 | auto const begin = ref.data() + | ||
| HITCBC | 197 | 1185 | path_prefix(ref.buffer()); | 197 | 1185 | path_prefix(ref.buffer()); | ||
| HITCBC | 198 | 1185 | auto p = ref.data() + pos; | 198 | 1185 | auto p = ref.data() + pos; | ||
| HITCBC | 199 | 1185 | BOOST_ASSERT(p != begin); | 199 | 1185 | BOOST_ASSERT(p != begin); | ||
| HITCBC | 200 | 4738 | while(p != begin) | 200 | 4738 | while(p != begin) | ||
| 201 | { | 201 | { | |||||
| HITCBC | 202 | 4738 | --p; | 202 | 4738 | --p; | ||
| HITCBC | 203 | 4738 | if(*p == '/') | 203 | 4738 | if(*p == '/') | ||
| HITCBC | 204 | 1185 | break; | 204 | 1185 | break; | ||
| 205 | } | 205 | } | |||||
| HITCBC | 206 | 1185 | pos = p - ref.data() + 1; | 206 | 1185 | pos = p - ref.data() + 1; | ||
| HITCBC | 207 | 1185 | update(); | 207 | 1185 | update(); | ||
| HITCBC | 208 | 1185 | --pos; | 208 | 1185 | --pos; | ||
| 209 | } | 209 | } | |||||
| 210 | 210 | |||||||
| 211 | } // detail | 211 | } // detail | |||||
| 212 | } // urls | 212 | } // urls | |||||
| 213 | } // boost | 213 | } // boost | |||||
| 214 | 214 | |||||||
| 215 | #endif | 215 | #endif | |||||