Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 09:02:19

0001 //
0002 // Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/url
0008 //
0009 
0010 #ifndef BOOST_URL_DETAIL_SEGMENTS_RANGE_HPP
0011 #define BOOST_URL_DETAIL_SEGMENTS_RANGE_HPP
0012 
0013 #include <boost/url/detail/config.hpp>
0014 #include <boost/url/detail/url_impl.hpp>
0015 #include <boost/url/segments_base.hpp>
0016 #include <boost/url/segments_encoded_base.hpp>
0017 #include <boost/core/detail/string_view.hpp>
0018 #include <boost/assert.hpp>
0019 
0020 namespace boost {
0021 namespace urls {
0022 namespace detail {
0023 
0024 struct segments_iter_access
0025 {
0026     static
0027     segments_iter_impl const&
0028     impl(segments_base::iterator const& it) noexcept
0029     {
0030         return it.it_;
0031     }
0032 
0033     static
0034     segments_iter_impl const&
0035     impl(segments_encoded_base::iterator const& it) noexcept
0036     {
0037         return it.it_;
0038     }
0039 };
0040 
0041 inline
0042 path_ref
0043 make_subref_from_impls(
0044     segments_iter_impl const& first,
0045     segments_iter_impl const& last) noexcept
0046 {
0047     BOOST_ASSERT(first.ref.alias_of(last.ref));
0048     path_ref const& ref = first.ref;
0049 
0050     std::size_t const i0 = first.index;
0051     std::size_t const i1 = last.index;
0052     BOOST_ASSERT(i0 <= i1);
0053     std::size_t const nseg = i1 - i0;
0054 
0055     bool const absolute = ref.buffer().starts_with('/');
0056 
0057     // Empty range
0058     if (nseg == 0)
0059     {
0060         std::size_t off0;
0061         if (i0 == 0)
0062         {
0063             // [begin, begin): don't include the leading '/'
0064             // for absolute, start right after the leading '/';
0065             if (absolute)
0066             {
0067                 off0 = 1;
0068             }
0069             // for relative, start at the first segment character.
0070             else
0071             {
0072                 off0 = first.pos;
0073             }
0074         }
0075         else
0076         {
0077             // [it, it) in the middle:
0078             // skip the separator before segment i0
0079             off0 = first.pos + 1;
0080         }
0081 
0082         core::string_view const sub(ref.data() + off0, 0);
0083         return {sub, 0, 0};
0084     }
0085 
0086     // General case: non-empty range
0087     // Start offset
0088     std::size_t off0;
0089     if (i0 == 0)
0090     {
0091         if (absolute)
0092         {
0093             // include leading '/'
0094             off0 = 0;
0095         }
0096         else
0097         {
0098             // relative: start at first segment
0099             off0 = first.pos;
0100         }
0101     }
0102     else
0103     {
0104         // include the separator preceding segment i0
0105         off0 = first.pos;
0106     }
0107 
0108     // End offset
0109     std::size_t off1;
0110     if(i1 == ref.nseg())
0111     {
0112         off1 = ref.size();
0113     }
0114     else
0115     {
0116         // stop before the slash preceding i1
0117         off1 = last.pos;
0118     }
0119 
0120     BOOST_ASSERT(off1 >= off0);
0121     core::string_view const sub(ref.data() + off0, off1 - off0);
0122 
0123     // decoded sizes reuse iterator bookkeeping instead of rescanning
0124     std::size_t start_dn = (i0 == 0) ? 0 : first.decoded_prefix_size();
0125     std::size_t const end_dn = last.decoded_prefix_size(); // already excludes segment at `last`
0126     BOOST_ASSERT(end_dn >= start_dn);
0127     std::size_t const dn_sum = end_dn - start_dn;
0128 
0129     return {sub, dn_sum, nseg};
0130 }
0131 
0132 template<class Iter>
0133 inline
0134 path_ref
0135 make_subref(Iter const& first, Iter const& last) noexcept
0136 {
0137     auto const& f = segments_iter_access::impl(first);
0138     auto const& l = segments_iter_access::impl(last);
0139     return make_subref_from_impls(f, l);
0140 }
0141 
0142 } // detail
0143 } // urls
0144 } // boost
0145 
0146 #endif