LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/test/utils/iterator - token_iterator.hpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 65 92 70.7 %
Date: 2026-06-25 07:23:51 Functions: 21 24 87.5 %

          Line data    Source code
       1             : //  (C) Copyright Gennadiy Rozental 2001.
       2             : //  Distributed under the Boost Software License, Version 1.0.
       3             : //  (See accompanying file LICENSE_1_0.txt or copy at
       4             : //  http://www.boost.org/LICENSE_1_0.txt)
       5             : 
       6             : //  See http://www.boost.org/libs/test for the library home page.
       7             : //
       8             : //  File        : $RCSfile$
       9             : //
      10             : //  Version     : $Revision$
      11             : //
      12             : //  Description : token iterator for string and range tokenization
      13             : // ***************************************************************************
      14             : 
      15             : #ifndef BOOST_TEST_UTILS_TOKEN_ITERATOR_HPP
      16             : #define BOOST_TEST_UTILS_TOKEN_ITERATOR_HPP
      17             : 
      18             : // Boost
      19             : #include <boost/config.hpp>
      20             : #include <boost/detail/workaround.hpp>
      21             : 
      22             : #include <boost/iterator/iterator_categories.hpp>
      23             : #include <boost/iterator/iterator_traits.hpp>
      24             : 
      25             : #include <boost/test/utils/iterator/input_iterator_facade.hpp>
      26             : #include <boost/test/utils/basic_cstring/basic_cstring.hpp>
      27             : #include <boost/test/utils/named_params.hpp>
      28             : #include <boost/test/utils/foreach.hpp>
      29             : 
      30             : // STL
      31             : #include <iosfwd>
      32             : #include <cctype>
      33             : 
      34             : #include <boost/test/detail/suppress_warnings.hpp>
      35             : 
      36             : //____________________________________________________________________________//
      37             : 
      38             : #ifdef BOOST_NO_STDC_NAMESPACE
      39             : namespace std{ using ::ispunct; using ::isspace; }
      40             : #endif
      41             : 
      42             : namespace boost {
      43             : namespace unit_test {
      44             : namespace utils {
      45             : 
      46             : // ************************************************************************** //
      47             : // **************               ti_delimeter_type              ************** //
      48             : // ************************************************************************** //
      49             : 
      50             : enum ti_delimeter_type {
      51             :     dt_char,        // character is delimeter if it among explicit list of some characters
      52             :     dt_ispunct,     // character is delimeter if it satisfies ispunct functor
      53             :     dt_isspace,     // character is delimeter if it satisfies isspace functor
      54             :     dt_none         // no character is delimeter
      55             : };
      56             : 
      57             : namespace ut_detail {
      58             : 
      59             : // ************************************************************************** //
      60             : // **************             default_char_compare             ************** //
      61             : // ************************************************************************** //
      62             : 
      63             : template<typename CharT>
      64             : class default_char_compare {
      65             : public:
      66        7467 :     bool operator()( CharT c1, CharT c2 )
      67             :     {
      68             : #ifdef BOOST_CLASSIC_IOSTREAMS
      69             :         return std::string_char_traits<CharT>::eq( c1, c2 );
      70             : #else
      71        7467 :         return std::char_traits<CharT>::eq( c1, c2 );
      72             : #endif
      73             :     }
      74             : };
      75             : 
      76             : // ************************************************************************** //
      77             : // **************                 delim_policy                 ************** //
      78             : // ************************************************************************** //
      79             : 
      80             : template<typename CharT,typename CharCompare>
      81             : class delim_policy {
      82             :     typedef basic_cstring<CharT const> cstring;
      83             : public:
      84             :     // Constructor
      85        4672 :     explicit    delim_policy( ti_delimeter_type type_ = dt_char, cstring delimeters_ = cstring() )
      86        2336 :     : m_type( type_ )
      87        2336 :     {
      88        2336 :         set_delimeters( delimeters_ );
      89        4672 :     }
      90             : 
      91         438 :     void        set_delimeters( ti_delimeter_type type_ ) { m_type = type_; }
      92        2774 :     void        set_delimeters( cstring delimeters_ )
      93             :     {
      94        2774 :         m_delimeters = delimeters_;
      95             : 
      96        2774 :         if( !m_delimeters.is_empty() )
      97         438 :             m_type = dt_char;
      98        2774 :     }
      99             :     void        set_delimeters( nfp::nil ) {}
     100       14934 :     bool        operator()( CharT c )
     101             :     {
     102       14934 :         switch( m_type ) {
     103             :         case dt_char: {
     104       22401 :             BOOST_TEST_FOREACH( CharT, delim, m_delimeters )
     105        7467 :                 if( CharCompare()( delim, c ) )
     106           0 :                     return true;
     107             : 
     108        7467 :             return false;
     109             :         }
     110             :         case dt_ispunct:
     111           0 :             return (std::ispunct)( c ) != 0;
     112             :         case dt_isspace:
     113           0 :             return (std::isspace)( c ) != 0;
     114             :         case dt_none:
     115        7467 :             return false;
     116             :         }
     117             : 
     118           0 :         return false;
     119       14934 :     }
     120             : 
     121             : private:
     122             :     // Data members
     123             :     cstring             m_delimeters;
     124             :     ti_delimeter_type   m_type;
     125             : };
     126             : 
     127             : // ************************************************************************** //
     128             : // **************                 token_assigner               ************** //
     129             : // ************************************************************************** //
     130             : 
     131             : template<typename TraversalTag>
     132             : struct token_assigner {
     133             : #if BOOST_WORKAROUND( BOOST_DINKUMWARE_STDLIB, < 306 )
     134             :     template<typename Iterator, typename C, typename T>
     135             :     static void assign( Iterator b, Iterator e, std::basic_string<C,T>& t )
     136             :     { for( ; b != e; ++b ) t += *b; }
     137             : 
     138             :     template<typename Iterator, typename C>
     139             :     static void assign( Iterator b, Iterator e, basic_cstring<C>& t )  { t.assign( b, e ); }
     140             : #else
     141             :     template<typename Iterator, typename Token>
     142         438 :     static void assign( Iterator b, Iterator e, Token& t )  { t.assign( b, e ); }
     143             : #endif
     144             :     template<typename Iterator, typename Token>
     145        7029 :     static void append_move( Iterator& b, Token& )          { ++b; }
     146             : };
     147             : 
     148             : //____________________________________________________________________________//
     149             : 
     150             : template<>
     151             : struct token_assigner<single_pass_traversal_tag> {
     152             :     template<typename Iterator, typename Token>
     153             :     static void assign( Iterator /*b*/, Iterator /*e*/, Token& /*t*/ )  {}
     154             : 
     155             :     template<typename Iterator, typename Token>
     156             :     static void append_move( Iterator& b, Token& t )        { t += *b; ++b; }
     157             : };
     158             : 
     159             : } // namespace ut_detail
     160             : 
     161             : // ************************************************************************** //
     162             : // **************                  modifiers                   ************** //
     163             : // ************************************************************************** //
     164             : 
     165             : namespace {
     166             : nfp::keyword<struct dropped_delimeters_t >           dropped_delimeters;
     167             : nfp::keyword<struct kept_delimeters_t >              kept_delimeters;
     168             : nfp::typed_keyword<bool,struct keep_empty_tokens_t > keep_empty_tokens;
     169             : nfp::typed_keyword<std::size_t,struct max_tokens_t > max_tokens;
     170             : }
     171             : 
     172             : // ************************************************************************** //
     173             : // **************             token_iterator_base              ************** //
     174             : // ************************************************************************** //
     175             : 
     176             : template<typename Derived,
     177             :          typename CharT,
     178             :          typename CharCompare   = ut_detail::default_char_compare<CharT>,
     179             :          typename ValueType     = basic_cstring<CharT const>,
     180             :          typename Reference     = basic_cstring<CharT const>,
     181             :          typename Traversal     = forward_traversal_tag>
     182             : class token_iterator_base
     183             : : public input_iterator_facade<Derived,ValueType,Reference,Traversal> {
     184             :     typedef basic_cstring<CharT const>                                      cstring;
     185             :     typedef ut_detail::delim_policy<CharT,CharCompare>                      delim_policy;
     186             :     typedef input_iterator_facade<Derived,ValueType,Reference,Traversal>    base;
     187             : 
     188             : protected:
     189             :     // Constructor
     190        1168 :     explicit    token_iterator_base()
     191        1168 :     : m_is_dropped( dt_isspace )
     192        1168 :     , m_is_kept( dt_ispunct )
     193        1168 :     , m_keep_empty_tokens( false )
     194        1168 :     , m_tokens_left( static_cast<std::size_t>(-1) )
     195        1168 :     , m_token_produced( false )
     196             :     {
     197        1168 :     }
     198             : 
     199             :     template<typename Modifier>
     200             :     void
     201         438 :     apply_modifier( Modifier const& m )
     202             :     {
     203         438 :         if( m.has( dropped_delimeters ) )
     204         438 :             m_is_dropped.set_delimeters( m[dropped_delimeters] );
     205             : 
     206         438 :         if( m.has( kept_delimeters ) )
     207         438 :             m_is_kept.set_delimeters( m[kept_delimeters] );
     208             : 
     209         438 :         if( m.has( keep_empty_tokens ) )
     210           0 :             m_keep_empty_tokens = true;
     211             : 
     212         438 :         nfp::opt_assign( m_tokens_left, m, max_tokens );
     213         438 :     }
     214             : 
     215             :     template<typename Iter>
     216         876 :     bool                    get( Iter& begin, Iter end )
     217             :     {
     218             :         typedef ut_detail::token_assigner<BOOST_DEDUCED_TYPENAME iterator_traversal<Iter>::type> Assigner;
     219             :         Iter check_point;
     220             : 
     221         876 :         this->m_value.clear();
     222             : 
     223         876 :         if( !m_keep_empty_tokens ) {
     224         876 :             while( begin != end && m_is_dropped( *begin ) )
     225           0 :                 ++begin;
     226             : 
     227         876 :             if( begin == end )
     228         438 :                 return false;
     229             : 
     230         438 :             check_point = begin;
     231             : 
     232         438 :             if( m_tokens_left == 1 )
     233           0 :                 while( begin != end )
     234           0 :                     Assigner::append_move( begin, this->m_value );
     235         438 :             else if( m_is_kept( *begin ) )
     236           0 :                 Assigner::append_move( begin, this->m_value );
     237             :             else
     238        7467 :                 while( begin != end && !m_is_dropped( *begin ) && !m_is_kept( *begin ) )
     239        7029 :                     Assigner::append_move( begin, this->m_value );
     240             : 
     241         438 :             --m_tokens_left;
     242         438 :         }
     243             :         else { // m_keep_empty_tokens is true
     244           0 :             check_point = begin;
     245             : 
     246           0 :             if( begin == end ) {
     247           0 :                 if( m_token_produced )
     248           0 :                     return false;
     249             : 
     250           0 :                 m_token_produced = true;
     251           0 :             }
     252           0 :             if( m_is_kept( *begin ) ) {
     253           0 :                 if( m_token_produced )
     254           0 :                     Assigner::append_move( begin, this->m_value );
     255             : 
     256           0 :                 m_token_produced = !m_token_produced;
     257           0 :             }
     258           0 :             else if( !m_token_produced && m_is_dropped( *begin ) )
     259           0 :                 m_token_produced = true;
     260             :             else {
     261           0 :                 if( m_is_dropped( *begin ) )
     262           0 :                     check_point = ++begin;
     263             : 
     264           0 :                 while( begin != end && !m_is_dropped( *begin ) && !m_is_kept( *begin ) )
     265           0 :                     Assigner::append_move( begin, this->m_value );
     266             : 
     267           0 :                 m_token_produced = true;
     268             :             }
     269             :         }
     270             : 
     271         438 :         Assigner::assign( check_point, begin, this->m_value );
     272             : 
     273         438 :         return true;
     274         876 :     }
     275             : 
     276             : private:
     277             :     // Data members
     278             :     delim_policy            m_is_dropped;
     279             :     delim_policy            m_is_kept;
     280             :     bool                    m_keep_empty_tokens;
     281             :     std::size_t             m_tokens_left;
     282             :     bool                    m_token_produced;
     283             : };
     284             : 
     285             : // ************************************************************************** //
     286             : // **************          basic_string_token_iterator         ************** //
     287             : // ************************************************************************** //
     288             : 
     289             : template<typename CharT,
     290             :          typename CharCompare = ut_detail::default_char_compare<CharT> >
     291             : class basic_string_token_iterator
     292             : : public token_iterator_base<basic_string_token_iterator<CharT,CharCompare>,CharT,CharCompare> {
     293             :     typedef basic_cstring<CharT const> cstring;
     294             :     typedef token_iterator_base<basic_string_token_iterator<CharT,CharCompare>,CharT,CharCompare> base;
     295             : public:
     296        1460 :     explicit    basic_string_token_iterator() {}
     297             :     explicit    basic_string_token_iterator( cstring src )
     298             :     : m_src( src )
     299             :     {
     300             :         this->init();
     301             :     }
     302             : 
     303             :     // warning: making the constructor accept anything else than a cstring should
     304             :     // ensure that no temporary object is created during string creation (previous
     305             :     // definition was "template<typename Src, typename Modifier> basic_string_token_iterator( Src src ..."
     306             :     // which may create a temporary string copy when called with an std::string.
     307             :     template<typename Modifier>
     308         876 :     basic_string_token_iterator( cstring src, Modifier const& m )
     309         438 :     : m_src( src )
     310         438 :     {
     311         438 :         this->apply_modifier( m );
     312             : 
     313         438 :         this->init();
     314         876 :     }
     315             : 
     316             : private:
     317             :     friend class input_iterator_core_access;
     318             : 
     319             :     // input iterator implementation
     320         876 :     bool        get()
     321             :     {
     322         876 :         typename cstring::iterator begin = m_src.begin();
     323         876 :         bool res = base::get( begin, m_src.end() );
     324             : 
     325         876 :         m_src.assign( begin, m_src.end() );
     326             : 
     327         876 :         return res;
     328             :     }
     329             : 
     330             :     // Data members
     331             :     cstring     m_src;
     332             : };
     333             : 
     334             : typedef basic_string_token_iterator<char>       string_token_iterator;
     335             : typedef basic_string_token_iterator<wchar_t>    wstring_token_iterator;
     336             : 
     337             : // ************************************************************************** //
     338             : // **************              range_token_iterator            ************** //
     339             : // ************************************************************************** //
     340             : 
     341             : template<typename Iter,
     342             :          typename CharCompare = ut_detail::default_char_compare<BOOST_DEDUCED_TYPENAME iterator_value<Iter>::type>,
     343             :          typename ValueType   = std::basic_string<BOOST_DEDUCED_TYPENAME iterator_value<Iter>::type>,
     344             :          typename Reference   = ValueType const&>
     345             : class range_token_iterator
     346             : : public token_iterator_base<range_token_iterator<Iter,CharCompare,ValueType,Reference>,
     347             :                              typename iterator_value<Iter>::type,CharCompare,ValueType,Reference> {
     348             :     typedef basic_cstring<typename ValueType::value_type> cstring;
     349             :     typedef token_iterator_base<range_token_iterator<Iter,CharCompare,ValueType,Reference>,
     350             :                                 typename iterator_value<Iter>::type,CharCompare,ValueType,Reference> base;
     351             : public:
     352             :     explicit    range_token_iterator() {}
     353             :     explicit    range_token_iterator( Iter begin, Iter end = Iter() )
     354             :     : m_begin( begin ), m_end( end )
     355             :     {
     356             :         this->init();
     357             :     }
     358             :     range_token_iterator( range_token_iterator const& rhs )
     359             :     : base( rhs )
     360             :     {
     361             :         if( this->m_valid ) {
     362             :             m_begin = rhs.m_begin;
     363             :             m_end   = rhs.m_end;
     364             :         }
     365             :     }
     366             : 
     367             :     template<typename Modifier>
     368             :     range_token_iterator( Iter begin, Iter end, Modifier const& m )
     369             :     : m_begin( begin ), m_end( end )
     370             :     {
     371             :         this->apply_modifier( m );
     372             : 
     373             :         this->init();
     374             :     }
     375             : 
     376             : private:
     377             :     friend class input_iterator_core_access;
     378             : 
     379             :     // input iterator implementation
     380             :     bool        get()
     381             :     {
     382             :         return base::get( m_begin, m_end );
     383             :     }
     384             : 
     385             :     // Data members
     386             :     Iter m_begin;
     387             :     Iter m_end;
     388             : };
     389             : 
     390             : // ************************************************************************** //
     391             : // **************            make_range_token_iterator         ************** //
     392             : // ************************************************************************** //
     393             : 
     394             : template<typename Iter>
     395             : inline range_token_iterator<Iter>
     396             : make_range_token_iterator( Iter begin, Iter end = Iter() )
     397             : {
     398             :     return range_token_iterator<Iter>( begin, end );
     399             : }
     400             : 
     401             : //____________________________________________________________________________//
     402             : 
     403             : template<typename Iter,typename Modifier>
     404             : inline range_token_iterator<Iter>
     405             : make_range_token_iterator( Iter begin, Iter end, Modifier const& m )
     406             : {
     407             :     return range_token_iterator<Iter>( begin, end, m );
     408             : }
     409             : 
     410             : //____________________________________________________________________________//
     411             : 
     412             : } // namespace utils
     413             : } // namespace unit_test
     414             : } // namespace boost
     415             : 
     416             : //____________________________________________________________________________//
     417             : 
     418             : #include <boost/test/detail/enable_warnings.hpp>
     419             : 
     420             : #endif // BOOST_TEST_UTILS_TOKEN_ITERATOR_HPP
     421             : 

Generated by: LCOV version 1.16