100.00% Lines (39/39)
100.00% Functions (4/4)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) | 2 | // Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) | |||||
| 3 | // | 3 | // | |||||
| 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 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) | 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 6 | // | 6 | // | |||||
| 7 | // Official repository: https://github.com/boostorg/url | 7 | // Official repository: https://github.com/boostorg/url | |||||
| 8 | // | 8 | // | |||||
| 9 | 9 | |||||||
| 10 | #ifndef BOOST_URL_DETAIL_SEGMENTS_RANGE_HPP | 10 | #ifndef BOOST_URL_DETAIL_SEGMENTS_RANGE_HPP | |||||
| 11 | #define BOOST_URL_DETAIL_SEGMENTS_RANGE_HPP | 11 | #define BOOST_URL_DETAIL_SEGMENTS_RANGE_HPP | |||||
| 12 | 12 | |||||||
| 13 | #include <boost/url/detail/config.hpp> | 13 | #include <boost/url/detail/config.hpp> | |||||
| 14 | #include <boost/url/detail/url_impl.hpp> | 14 | #include <boost/url/detail/url_impl.hpp> | |||||
| 15 | #include <boost/url/segments_base.hpp> | 15 | #include <boost/url/segments_base.hpp> | |||||
| 16 | #include <boost/url/segments_encoded_base.hpp> | 16 | #include <boost/url/segments_encoded_base.hpp> | |||||
| 17 | #include <boost/core/detail/string_view.hpp> | 17 | #include <boost/core/detail/string_view.hpp> | |||||
| 18 | #include <boost/assert.hpp> | 18 | #include <boost/assert.hpp> | |||||
| 19 | 19 | |||||||
| 20 | namespace boost { | 20 | namespace boost { | |||||
| 21 | namespace urls { | 21 | namespace urls { | |||||
| 22 | namespace detail { | 22 | namespace detail { | |||||
| 23 | 23 | |||||||
| 24 | struct segments_iter_access | 24 | struct segments_iter_access | |||||
| 25 | { | 25 | { | |||||
| 26 | static | 26 | static | |||||
| 27 | segments_iter_impl const& | 27 | segments_iter_impl const& | |||||
| HITCBC | 28 | 40 | impl(segments_base::iterator const& it) noexcept | 28 | 40 | impl(segments_base::iterator const& it) noexcept | ||
| 29 | { | 29 | { | |||||
| HITCBC | 30 | 40 | return it.it_; | 30 | 40 | return it.it_; | ||
| 31 | } | 31 | } | |||||
| 32 | 32 | |||||||
| 33 | static | 33 | static | |||||
| 34 | segments_iter_impl const& | 34 | segments_iter_impl const& | |||||
| HITCBC | 35 | 6 | impl(segments_encoded_base::iterator const& it) noexcept | 35 | 6 | impl(segments_encoded_base::iterator const& it) noexcept | ||
| 36 | { | 36 | { | |||||
| HITCBC | 37 | 6 | return it.it_; | 37 | 6 | return it.it_; | ||
| 38 | } | 38 | } | |||||
| 39 | }; | 39 | }; | |||||
| 40 | 40 | |||||||
| 41 | inline | 41 | inline | |||||
| 42 | path_ref | 42 | path_ref | |||||
| HITCBC | 43 | 23 | make_subref_from_impls( | 43 | 23 | make_subref_from_impls( | ||
| 44 | segments_iter_impl const& first, | 44 | segments_iter_impl const& first, | |||||
| 45 | segments_iter_impl const& last) noexcept | 45 | segments_iter_impl const& last) noexcept | |||||
| 46 | { | 46 | { | |||||
| HITCBC | 47 | 23 | BOOST_ASSERT(first.ref.alias_of(last.ref)); | 47 | 23 | BOOST_ASSERT(first.ref.alias_of(last.ref)); | ||
| HITCBC | 48 | 23 | path_ref const& ref = first.ref; | 48 | 23 | path_ref const& ref = first.ref; | ||
| 49 | 49 | |||||||
| HITCBC | 50 | 23 | std::size_t const i0 = first.index; | 50 | 23 | std::size_t const i0 = first.index; | ||
| HITCBC | 51 | 23 | std::size_t const i1 = last.index; | 51 | 23 | std::size_t const i1 = last.index; | ||
| HITCBC | 52 | 23 | BOOST_ASSERT(i0 <= i1); | 52 | 23 | BOOST_ASSERT(i0 <= i1); | ||
| HITCBC | 53 | 23 | std::size_t const nseg = i1 - i0; | 53 | 23 | std::size_t const nseg = i1 - i0; | ||
| 54 | 54 | |||||||
| HITCBC | 55 | 23 | bool const absolute = ref.buffer().starts_with('/'); | 55 | 23 | bool const absolute = ref.buffer().starts_with('/'); | ||
| 56 | 56 | |||||||
| 57 | // Empty range | 57 | // Empty range | |||||
| HITCBC | 58 | 23 | if (nseg == 0) | 58 | 23 | if (nseg == 0) | ||
| 59 | { | 59 | { | |||||
| 60 | std::size_t off0; | 60 | std::size_t off0; | |||||
| HITCBC | 61 | 6 | if (i0 == 0) | 61 | 6 | if (i0 == 0) | ||
| 62 | { | 62 | { | |||||
| 63 | // [begin, begin): don't include the leading '/' | 63 | // [begin, begin): don't include the leading '/' | |||||
| 64 | // for absolute, start right after the leading '/'; | 64 | // for absolute, start right after the leading '/'; | |||||
| HITCBC | 65 | 3 | if (absolute) | 65 | 3 | if (absolute) | ||
| 66 | { | 66 | { | |||||
| HITCBC | 67 | 2 | off0 = 1; | 67 | 2 | off0 = 1; | ||
| 68 | } | 68 | } | |||||
| 69 | // for relative, start at the first segment character. | 69 | // for relative, start at the first segment character. | |||||
| 70 | else | 70 | else | |||||
| 71 | { | 71 | { | |||||
| HITCBC | 72 | 1 | off0 = first.pos; | 72 | 1 | off0 = first.pos; | ||
| 73 | } | 73 | } | |||||
| 74 | } | 74 | } | |||||
| 75 | else | 75 | else | |||||
| 76 | { | 76 | { | |||||
| 77 | // [it, it) in the middle: | 77 | // [it, it) in the middle: | |||||
| 78 | // skip the separator before segment i0 | 78 | // skip the separator before segment i0 | |||||
| HITCBC | 79 | 3 | off0 = first.pos + 1; | 79 | 3 | off0 = first.pos + 1; | ||
| 80 | } | 80 | } | |||||
| 81 | 81 | |||||||
| HITCBC | 82 | 6 | core::string_view const sub(ref.data() + off0, 0); | 82 | 6 | core::string_view const sub(ref.data() + off0, 0); | ||
| HITCBC | 83 | 6 | return {sub, 0, 0}; | 83 | 6 | return {sub, 0, 0}; | ||
| 84 | } | 84 | } | |||||
| 85 | 85 | |||||||
| 86 | // General case: non-empty range | 86 | // General case: non-empty range | |||||
| 87 | // Start offset | 87 | // Start offset | |||||
| 88 | std::size_t off0; | 88 | std::size_t off0; | |||||
| HITCBC | 89 | 17 | if (i0 == 0) | 89 | 17 | if (i0 == 0) | ||
| 90 | { | 90 | { | |||||
| HITCBC | 91 | 10 | if (absolute) | 91 | 10 | if (absolute) | ||
| 92 | { | 92 | { | |||||
| 93 | // include leading '/' | 93 | // include leading '/' | |||||
| HITCBC | 94 | 5 | off0 = 0; | 94 | 5 | off0 = 0; | ||
| 95 | } | 95 | } | |||||
| 96 | else | 96 | else | |||||
| 97 | { | 97 | { | |||||
| 98 | // relative: start at first segment | 98 | // relative: start at first segment | |||||
| HITCBC | 99 | 5 | off0 = first.pos; | 99 | 5 | off0 = first.pos; | ||
| 100 | } | 100 | } | |||||
| 101 | } | 101 | } | |||||
| 102 | else | 102 | else | |||||
| 103 | { | 103 | { | |||||
| 104 | // include the separator preceding segment i0 | 104 | // include the separator preceding segment i0 | |||||
| HITCBC | 105 | 7 | off0 = first.pos; | 105 | 7 | off0 = first.pos; | ||
| 106 | } | 106 | } | |||||
| 107 | 107 | |||||||
| 108 | // End offset | 108 | // End offset | |||||
| 109 | std::size_t off1; | 109 | std::size_t off1; | |||||
| HITCBC | 110 | 17 | if(i1 == ref.nseg()) | 110 | 17 | if(i1 == ref.nseg()) | ||
| 111 | { | 111 | { | |||||
| HITCBC | 112 | 9 | off1 = ref.size(); | 112 | 9 | off1 = ref.size(); | ||
| 113 | } | 113 | } | |||||
| 114 | else | 114 | else | |||||
| 115 | { | 115 | { | |||||
| 116 | // stop before the slash preceding i1 | 116 | // stop before the slash preceding i1 | |||||
| HITCBC | 117 | 8 | off1 = last.pos; | 117 | 8 | off1 = last.pos; | ||
| 118 | } | 118 | } | |||||
| 119 | 119 | |||||||
| HITCBC | 120 | 17 | BOOST_ASSERT(off1 >= off0); | 120 | 17 | BOOST_ASSERT(off1 >= off0); | ||
| HITCBC | 121 | 17 | core::string_view const sub(ref.data() + off0, off1 - off0); | 121 | 17 | core::string_view const sub(ref.data() + off0, off1 - off0); | ||
| 122 | 122 | |||||||
| 123 | // decoded sizes reuse iterator bookkeeping instead of rescanning | 123 | // decoded sizes reuse iterator bookkeeping instead of rescanning | |||||
| HITCBC | 124 | 17 | std::size_t start_dn = (i0 == 0) ? 0 : first.decoded_prefix_size(); | 124 | 17 | std::size_t start_dn = (i0 == 0) ? 0 : first.decoded_prefix_size(); | ||
| HITCBC | 125 | 17 | std::size_t const end_dn = last.decoded_prefix_size(); // already excludes segment at `last` | 125 | 17 | std::size_t const end_dn = last.decoded_prefix_size(); // already excludes segment at `last` | ||
| HITCBC | 126 | 17 | BOOST_ASSERT(end_dn >= start_dn); | 126 | 17 | BOOST_ASSERT(end_dn >= start_dn); | ||
| HITCBC | 127 | 17 | std::size_t const dn_sum = end_dn - start_dn; | 127 | 17 | std::size_t const dn_sum = end_dn - start_dn; | ||
| 128 | 128 | |||||||
| HITCBC | 129 | 17 | return {sub, dn_sum, nseg}; | 129 | 17 | return {sub, dn_sum, nseg}; | ||
| 130 | } | 130 | } | |||||
| 131 | 131 | |||||||
| 132 | template<class Iter> | 132 | template<class Iter> | |||||
| 133 | inline | 133 | inline | |||||
| 134 | path_ref | 134 | path_ref | |||||
| HITCBC | 135 | 23 | make_subref(Iter const& first, Iter const& last) noexcept | 135 | 23 | make_subref(Iter const& first, Iter const& last) noexcept | ||
| 136 | { | 136 | { | |||||
| HITCBC | 137 | 23 | auto const& f = segments_iter_access::impl(first); | 137 | 23 | auto const& f = segments_iter_access::impl(first); | ||
| HITCBC | 138 | 23 | auto const& l = segments_iter_access::impl(last); | 138 | 23 | auto const& l = segments_iter_access::impl(last); | ||
| HITCBC | 139 | 23 | return make_subref_from_impls(f, l); | 139 | 23 | return make_subref_from_impls(f, l); | ||
| 140 | } | 140 | } | |||||
| 141 | 141 | |||||||
| 142 | } // detail | 142 | } // detail | |||||
| 143 | } // urls | 143 | } // urls | |||||
| 144 | } // boost | 144 | } // boost | |||||
| 145 | 145 | |||||||
| 146 | #endif | 146 | #endif | |||||