token_iterator.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 419 行

HPP
419
字号
//  (C) Copyright Gennadiy Rozental 2004-2008.//  Distributed under the Boost Software License, Version 1.0.//  (See accompanying file LICENSE_1_0.txt or copy at //  http://www.boost.org/LICENSE_1_0.txt)//  See http://www.boost.org/libs/test for the library home page.////  File        : $RCSfile$////  Version     : $Revision: 49312 $////  Description : token iterator for string and range tokenization// ***************************************************************************#ifndef BOOST_TOKEN_ITERATOR_HPP_071894GER#define BOOST_TOKEN_ITERATOR_HPP_071894GER// Boost#include <boost/config.hpp>#include <boost/detail/workaround.hpp>#include <boost/iterator/iterator_categories.hpp>#include <boost/iterator/iterator_traits.hpp>#include <boost/test/utils/iterator/input_iterator_facade.hpp>#include <boost/test/utils/basic_cstring/basic_cstring.hpp>#include <boost/test/utils/named_params.hpp>#include <boost/test/utils/foreach.hpp>// STL#include <iosfwd>#include <cctype>#include <boost/test/detail/suppress_warnings.hpp>//____________________________________________________________________________//#ifdef BOOST_NO_STDC_NAMESPACEnamespace std{ using ::ispunct; using ::isspace; }#endifnamespace boost {namespace unit_test {// ************************************************************************** //// **************               ti_delimeter_type              ************** //// ************************************************************************** //enum ti_delimeter_type {     dt_char,        // character is delimeter if it among explicit list of some characters    dt_ispunct,     // character is delimeter if it satisfies ispunct functor    dt_isspace,     // character is delimeter if it satisfies isspace functor    dt_none         // no character is delimeter};namespace ut_detail {// ************************************************************************** //// **************             default_char_compare             ************** //// ************************************************************************** //template<typename CharT>class default_char_compare {public:    bool operator()( CharT c1, CharT c2 )    {#ifdef BOOST_CLASSIC_IOSTREAMS        return std::string_char_traits<CharT>::eq( c1, c2 );#else        return std::char_traits<CharT>::eq( c1, c2 );#endif    }};// ************************************************************************** //// **************                 delim_policy                 ************** //// ************************************************************************** //template<typename CharT,typename CharCompare>class delim_policy {    typedef basic_cstring<CharT const> cstring;public:    // Constructor    explicit    delim_policy( ti_delimeter_type t = dt_char, cstring d = cstring() )    : m_type( t )    {        set_delimeters( d );    }    void        set_delimeters( ti_delimeter_type t ) { m_type = t; }    template<typename Src>    void        set_delimeters( Src d )    {        nfp::optionally_assign( m_delimeters, d );                if( !m_delimeters.is_empty() )            m_type = dt_char;    }    bool        operator()( CharT c )    {        switch( m_type ) {        case dt_char: {            BOOST_TEST_FOREACH( CharT, delim, m_delimeters )                if( CharCompare()( delim, c ) )                    return true;            return false;        }        case dt_ispunct:            return (std::ispunct)( c ) != 0;        case dt_isspace:            return (std::isspace)( c ) != 0;        case dt_none:            return false;        }        return false;    }private:    // Data members    cstring             m_delimeters;    ti_delimeter_type   m_type;};// ************************************************************************** //// **************                 token_assigner               ************** //// ************************************************************************** //template<typename TraversalTag>struct token_assigner {#if BOOST_WORKAROUND( BOOST_DINKUMWARE_STDLIB, < 306 )    template<typename Iterator, typename C, typename T>    static void assign( Iterator b, Iterator e, std::basic_string<C,T>& t )    { for( ; b != e; ++b ) t += *b; }        template<typename Iterator, typename C>    static void assign( Iterator b, Iterator e, basic_cstring<C>& t )  { t.assign( b, e ); }#else    template<typename Iterator, typename Token>    static void assign( Iterator b, Iterator e, Token& t )  { t.assign( b, e ); }#endif    template<typename Iterator, typename Token>    static void append_move( Iterator& b, Token& )          { ++b; }};//____________________________________________________________________________//template<>struct token_assigner<single_pass_traversal_tag> {    template<typename Iterator, typename Token>    static void assign( Iterator b, Iterator e, Token& t )  {}    template<typename Iterator, typename Token>    static void append_move( Iterator& b, Token& t )        { t += *b; ++b; }};} // namespace ut_detail// ************************************************************************** //// **************                  modifiers                   ************** //// ************************************************************************** //namespace {nfp::keyword<struct dropped_delimeters_t >           dropped_delimeters;nfp::keyword<struct kept_delimeters_t >              kept_delimeters;nfp::typed_keyword<bool,struct keep_empty_tokens_t > keep_empty_tokens;nfp::typed_keyword<std::size_t,struct max_tokens_t > max_tokens;}// ************************************************************************** //// **************             token_iterator_base              ************** //// ************************************************************************** //template<typename Derived,         typename CharT,         typename CharCompare   = ut_detail::default_char_compare<CharT>,         typename ValueType     = basic_cstring<CharT const>,         typename Reference     = basic_cstring<CharT const>,         typename Traversal     = forward_traversal_tag>class token_iterator_base: public input_iterator_facade<Derived,ValueType,Reference,Traversal> {    typedef basic_cstring<CharT const>                                      cstring;    typedef ut_detail::delim_policy<CharT,CharCompare>                      delim_policy;    typedef input_iterator_facade<Derived,ValueType,Reference,Traversal>    base;protected:    // Constructor    explicit    token_iterator_base()    : m_is_dropped( dt_isspace )    , m_is_kept( dt_ispunct )    , m_keep_empty_tokens( false )    , m_tokens_left( (std::size_t)-1 )    , m_token_produced( false )    {    }    template<typename Modifier>    void    apply_modifier( Modifier const& m )    {        if( m.has( dropped_delimeters ) )            m_is_dropped.set_delimeters( m[dropped_delimeters] );        if( m.has( kept_delimeters ) )            m_is_kept.set_delimeters( m[kept_delimeters] );        if( m.has( keep_empty_tokens ) )            m_keep_empty_tokens = true;        nfp::optionally_assign( m_tokens_left, m, max_tokens );    }    template<typename Iter>     bool                    get( Iter& begin, Iter end )    {        typedef ut_detail::token_assigner<BOOST_DEDUCED_TYPENAME iterator_traversal<Iter>::type> Assigner;        Iter check_point;        this->m_value.clear();        if( !m_keep_empty_tokens ) {            while( begin != end && m_is_dropped( *begin ) )                ++begin;            if( begin == end )                return false;            check_point = begin;            if( m_tokens_left == 1 )                while( begin != end )                    Assigner::append_move( begin, this->m_value );            else if( m_is_kept( *begin ) )                Assigner::append_move( begin, this->m_value );            else                while( begin != end && !m_is_dropped( *begin ) && !m_is_kept( *begin ) )                    Assigner::append_move( begin, this->m_value );            --m_tokens_left;        }         else { // m_keep_empty_tokens is true            check_point = begin;            if( begin == end ) {                if( m_token_produced )                     return false;                m_token_produced = true;            }            if( m_is_kept( *begin ) ) {                if( m_token_produced )                     Assigner::append_move( begin, this->m_value );                m_token_produced = !m_token_produced;            }             else if( !m_token_produced && m_is_dropped( *begin ) )                m_token_produced = true;            else {                if( m_is_dropped( *begin ) )                    check_point = ++begin;                while( begin != end && !m_is_dropped( *begin ) && !m_is_kept( *begin ) )                    Assigner::append_move( begin, this->m_value );                m_token_produced = true;            }        }        Assigner::assign( check_point, begin, this->m_value );        return true;    }private:    // Data members    delim_policy            m_is_dropped;    delim_policy            m_is_kept;    bool                    m_keep_empty_tokens;    std::size_t             m_tokens_left;    bool                    m_token_produced;};// ************************************************************************** //// **************          basic_string_token_iterator         ************** //// ************************************************************************** //template<typename CharT,         typename CharCompare = ut_detail::default_char_compare<CharT> >class basic_string_token_iterator: public token_iterator_base<basic_string_token_iterator<CharT,CharCompare>,CharT,CharCompare> {    typedef basic_cstring<CharT const> cstring;    typedef token_iterator_base<basic_string_token_iterator<CharT,CharCompare>,CharT,CharCompare> base;public:    explicit    basic_string_token_iterator() {}    explicit    basic_string_token_iterator( cstring src )    : m_src( src )    {        this->init();    }    template<typename Src, typename Modifier>    basic_string_token_iterator( Src src, Modifier const& m )    : m_src( src )    {        this->apply_modifier( m );        this->init();    }private:    friend class input_iterator_core_access;    // input iterator implementation    bool        get()    {        typename cstring::iterator begin = m_src.begin();        bool res = base::get( begin, m_src.end() );        m_src.assign( begin, m_src.end() );        return res;    }    // Data members    cstring     m_src;};typedef basic_string_token_iterator<char>       string_token_iterator;typedef basic_string_token_iterator<wchar_t>    wstring_token_iterator;// ************************************************************************** //// **************              range_token_iterator            ************** //// ************************************************************************** //template<typename Iter,         typename CharCompare = ut_detail::default_char_compare<BOOST_DEDUCED_TYPENAME iterator_value<Iter>::type>,         typename ValueType   = std::basic_string<BOOST_DEDUCED_TYPENAME iterator_value<Iter>::type>,         typename Reference   = ValueType const&>class range_token_iterator: public token_iterator_base<range_token_iterator<Iter,CharCompare,ValueType,Reference>,                             typename iterator_value<Iter>::type,CharCompare,ValueType,Reference> {    typedef basic_cstring<typename ValueType::value_type> cstring;    typedef token_iterator_base<range_token_iterator<Iter,CharCompare,ValueType,Reference>,                                typename iterator_value<Iter>::type,CharCompare,ValueType,Reference> base;public:    explicit    range_token_iterator() {}    explicit    range_token_iterator( Iter begin, Iter end = Iter() )    : m_begin( begin ), m_end( end )    {        this->init();    }    range_token_iterator( range_token_iterator const& rhs )    : base( rhs )    {        if( this->m_valid ) {            m_begin = rhs.m_begin;            m_end   = rhs.m_end;        }    }    template<typename Modifier>    range_token_iterator( Iter begin, Iter end, Modifier const& m )    : m_begin( begin ), m_end( end )    {        this->apply_modifier( m );        this->init();    }private:    friend class input_iterator_core_access;    // input iterator implementation    bool        get()    {        return base::get( m_begin, m_end );    }    // Data members    Iter m_begin;    Iter m_end;};// ************************************************************************** //// **************            make_range_token_iterator         ************** //// ************************************************************************** //template<typename Iter>inline range_token_iterator<Iter>make_range_token_iterator( Iter begin, Iter end = Iter() ){    return range_token_iterator<Iter>( begin, end );}//____________________________________________________________________________//template<typename Iter,typename Modifier>inline range_token_iterator<Iter>make_range_token_iterator( Iter begin, Iter end, Modifier const& m ){    return range_token_iterator<Iter>( begin, end, m );}//____________________________________________________________________________//} // namespace unit_test} // namespace boost//____________________________________________________________________________//#include <boost/test/detail/enable_warnings.hpp>#endif // BOOST_TOKEN_ITERATOR_HPP_071894GER

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?