LCOV - code coverage report
Current view: top level - boost/url/detail - any_segments_iter.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 61 62 98.4 %
Date: 2024-02-29 20:02:55 Functions: 33 37 89.2 %

          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_ANY_SEGMENTS_ITER_HPP
      11             : #define BOOST_URL_DETAIL_ANY_SEGMENTS_ITER_HPP
      12             : 
      13             : #include <boost/url/pct_string_view.hpp>
      14             : #include <boost/static_assert.hpp>
      15             : #include <cstddef>
      16             : #include <iterator>
      17             : #include <type_traits>
      18             : 
      19             : namespace boost {
      20             : namespace urls {
      21             : namespace detail {
      22             : 
      23             : struct BOOST_SYMBOL_VISIBLE
      24             :     any_segments_iter
      25             : {
      26             : protected:
      27             :     explicit
      28         610 :     any_segments_iter(
      29             :         core::string_view s_ = {}) noexcept
      30         610 :         : s(s_)
      31             :     {
      32         610 :     }
      33             : 
      34         610 :     virtual ~any_segments_iter() = default;
      35             : 
      36             : public:
      37             :     // this is adjusted
      38             :     // when self-intersecting
      39             :     core::string_view s;
      40             : 
      41             :     // the first segment,
      42             :     // to handle special cases
      43             :     core::string_view front;
      44             : 
      45             :     // quick number of segments
      46             :     // 0 = zero
      47             :     // 1 = one
      48             :     // 2 = two, or more
      49             :     int fast_nseg = 0;
      50             : 
      51             :     // whether the segments should encode colons
      52             :     // when we measure and copy. the calling
      53             :     // function uses this for the first
      54             :     // segment in some cases, such as:
      55             :     // "x:y:z" -> remove_scheme -> "y%3Az"
      56             :     // as "y:z" would no longer represent a path
      57             :     bool encode_colons = false;
      58             : 
      59             :     // Rewind the iterator to the beginning
      60             :     virtual void rewind() noexcept = 0;
      61             : 
      62             :     // Measure and increment the current
      63             :     // element. n is increased by the
      64             :     // encoded size. Returns false on
      65             :     // end of range. 
      66             :     virtual bool measure(std::size_t& n) = 0;
      67             : 
      68             :     // Copy and increment the current
      69             :     // element, encoding as needed.
      70             :     virtual void copy(char*& dest,
      71             :         char const* end) noexcept = 0;
      72             : };
      73             : 
      74             : //------------------------------------------------
      75             : //
      76             : // segment_iter
      77             : //
      78             : //------------------------------------------------
      79             : 
      80             : // A 1-segment range
      81             : // allowing self-intersection
      82             : struct BOOST_SYMBOL_VISIBLE
      83             :     segment_iter
      84             :     : any_segments_iter
      85             : {
      86          74 :     virtual ~segment_iter() = default;
      87             : 
      88             :     explicit
      89             :     segment_iter(
      90             :         core::string_view s) noexcept;
      91             : 
      92             : private:
      93             :     bool at_end_ = false;
      94             :     void rewind() noexcept override;
      95             :     bool measure(std::size_t&) noexcept override;
      96             :     void copy(char*&, char const*) noexcept override;
      97             : };
      98             : 
      99             : //------------------------------------------------
     100             : //
     101             : // segments_iter
     102             : //
     103             : //------------------------------------------------
     104             : 
     105             : struct segments_iter_base
     106             : {
     107             : protected:
     108             :     BOOST_URL_DECL static void
     109             :     measure_impl(std::size_t&,
     110             :         core::string_view, bool) noexcept;
     111             :     BOOST_URL_DECL static void
     112             :     copy_impl(char*&, char const*,
     113             :         core::string_view, bool) noexcept;
     114             : };
     115             : 
     116             : // iterates segments in a
     117             : // plain segment range
     118             : template<class FwdIt>
     119             : struct segments_iter
     120             :     : any_segments_iter
     121             :     , segments_iter_base
     122             : {
     123             :     BOOST_STATIC_ASSERT(
     124             :         std::is_convertible<
     125             :             typename std::iterator_traits<
     126             :                 FwdIt>::reference,
     127             :             core::string_view>::value);
     128             : 
     129          79 :     segments_iter(
     130             :         FwdIt first,
     131             :         FwdIt last) noexcept
     132             :         : it_(first)
     133             :         , it0_(first)
     134          79 :         , end_(last)
     135             :     {
     136          79 :         if(first != last)
     137             :         {
     138          79 :             front = *first;
     139          79 :             auto it = first;
     140          79 :             if(++it == last)
     141           8 :                 fast_nseg = 1;
     142             :             else
     143          71 :                 fast_nseg = 2;
     144             :         }
     145             :         else
     146             :         {
     147           0 :             fast_nseg = 0;
     148             :         }
     149          79 :     }
     150             : 
     151             : private:
     152             :     FwdIt it_;
     153             :     FwdIt it0_;
     154             :     FwdIt end_;
     155             : 
     156             :     void
     157          79 :     rewind() noexcept override
     158             :     {
     159          79 :         it_ = it0_;
     160          79 :     }
     161             : 
     162             :     bool
     163         267 :     measure(
     164             :         std::size_t& n) noexcept override
     165             :     {
     166         267 :         if(it_ == end_)
     167          79 :             return false;
     168         188 :         measure_impl(n,
     169         182 :             detail::to_sv(*it_),
     170         188 :             encode_colons);
     171         188 :         ++it_;
     172         188 :         return true;
     173             :     }
     174             : 
     175             :     void
     176         188 :     copy(
     177             :         char*& dest,
     178             :         char const* end) noexcept override
     179             :     {
     180         188 :         copy_impl(dest, end,
     181         194 :             detail::to_sv(*it_++),
     182         188 :             encode_colons);
     183         188 :     }
     184             : };
     185             : 
     186             : //------------------------------------------------
     187             : //
     188             : // segment_encoded_iter
     189             : //
     190             : //------------------------------------------------
     191             : 
     192             : // A 1-segment range
     193             : // allowing self-intersection
     194             : struct BOOST_SYMBOL_VISIBLE
     195             :     segment_encoded_iter
     196             :     : any_segments_iter
     197             : {
     198          72 :     virtual ~segment_encoded_iter() = default;
     199             : 
     200             :     explicit
     201             :     segment_encoded_iter(
     202             :         pct_string_view const& s) noexcept;
     203             : 
     204             : private:
     205             :     bool at_end_ = false;
     206             :     void rewind() noexcept override;
     207             :     bool measure(std::size_t&) noexcept override;
     208             :     void copy(char*&, char const*) noexcept override;
     209             : };
     210             : 
     211             : //------------------------------------------------
     212             : //
     213             : // segments_encoded_iter
     214             : //
     215             : //------------------------------------------------
     216             : 
     217             : // Validating and copying from
     218             : // a string of encoded segments
     219             : struct segments_encoded_iter_base
     220             : {
     221             : protected:
     222             :     BOOST_URL_DECL static void
     223             :     measure_impl(std::size_t&,
     224             :         core::string_view, bool) noexcept;
     225             :     BOOST_URL_DECL static void
     226             :     copy_impl(char*&, char const*,
     227             :         core::string_view, bool) noexcept;
     228             : };
     229             : 
     230             : // iterates segments in an
     231             : // encoded segment range
     232             : template<class FwdIt>
     233             : struct segments_encoded_iter
     234             :     : public any_segments_iter
     235             :     , public segments_encoded_iter_base
     236             : {
     237             :     BOOST_STATIC_ASSERT(
     238             :         std::is_convertible<
     239             :             typename std::iterator_traits<
     240             :                 FwdIt>::reference,
     241             :             core::string_view>::value);
     242             : 
     243         385 :     segments_encoded_iter(
     244             :         FwdIt first,
     245             :         FwdIt last)
     246             :         : it_(first)
     247             :         , it0_(first)
     248         398 :         , end_(last)
     249             :     {
     250         385 :         if(it_ != end_)
     251             :         {
     252             :             // throw on invalid input
     253         196 :             front = pct_string_view(
     254         125 :                 detail::to_sv(*first));
     255         183 :             auto it = first;
     256         183 :             if(++it == last)
     257          65 :                 fast_nseg = 1;
     258             :             else
     259         118 :                 fast_nseg = 2;
     260             :         }
     261             :         else
     262             :         {
     263         189 :             fast_nseg = 0;
     264             :         }
     265         372 :     }
     266             : 
     267             : private:
     268             :     FwdIt it_;
     269             :     FwdIt it0_;
     270             :     FwdIt end_;
     271             : 
     272             :     void
     273         370 :     rewind() noexcept override
     274             :     {
     275         370 :         it_ = it0_;
     276         370 :     }
     277             : 
     278             :     bool
     279         771 :     measure(
     280             :         std::size_t& n) override
     281             :     {
     282         771 :         if(it_ == end_)
     283         370 :             return false;
     284             :         // throw on invalid input
     285         401 :         measure_impl(n,
     286             :             pct_string_view(
     287         401 :                 detail::to_sv(*it_++)),
     288         401 :             encode_colons);
     289         399 :         return true;
     290             :     }
     291             : 
     292             :     void
     293         397 :     copy(
     294             :         char*& dest,
     295             :         char const* end) noexcept override
     296             :     {
     297         397 :         copy_impl(dest, end,
     298         397 :             detail::to_sv(*it_++),
     299         397 :             encode_colons);
     300         397 :     }
     301             : };
     302             : 
     303             : //------------------------------------------------
     304             : 
     305             : template<class FwdIt>
     306             : segments_iter<FwdIt>
     307          79 : make_segments_iter(
     308             :     FwdIt first, FwdIt last)
     309             : {
     310             :     return segments_iter<
     311          79 :         FwdIt>(first, last);
     312             : }
     313             : 
     314             : template<class FwdIt>
     315             : segments_encoded_iter<FwdIt>
     316         385 : make_segments_encoded_iter(
     317             :     FwdIt first, FwdIt last)
     318             : {
     319             :     return segments_encoded_iter<
     320         385 :         FwdIt>(first, last);
     321             : }
     322             : 
     323             : } // detail
     324             : } // urls
     325             : } // boost
     326             : 
     327             : #endif

Generated by: LCOV version 1.15