// Boost string_algo library find_iterator.hpp header file ---------------------------// // Copyright Pavol Droba 2002-2004. // // 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/ for updates, documentation, and revision history. #ifndef BOOST_STRING_FIND_ITERATOR_HPP #define BOOST_STRING_FIND_ITERATOR_HPP #include #include #include #include #include #include #include #include #include /*! \file Defines find iterator classes. Find iterator repeatedly applies a Finder to the specified input string to search for matches. Dereferencing the iterator yields the current match or a range between the last and the current match depending on the iterator used. */ namespace boost { namespace algorithm { // find_iterator -----------------------------------------------// //! find_iterator /*! Find iterator encapsulates a Finder and allows for incremental searching in a string. Each increment moves the iterator to the next match. Find iterator is a readable forward traversal iterator. Dereferencing the iterator yields an iterator_range delimiting the current match. */ template class find_iterator : public iterator_facade< find_iterator, const iterator_range, forward_traversal_tag >, private detail::find_iterator_base { private: // facade support friend class ::boost::iterator_core_access; private: // typedefs typedef detail::find_iterator_base base_type; typedef BOOST_STRING_TYPENAME base_type::input_iterator_type input_iterator_type; typedef BOOST_STRING_TYPENAME base_type::match_type match_type; public: //! Default constructor /*! Construct null iterator. All null iterators are equal. \post eof()==true */ find_iterator() {} //! Copy constructor /*! Construct a copy of the find_iterator */ find_iterator( const find_iterator& Other ) : base_type(Other), m_Match(Other.m_Match), m_End(Other.m_End) {} //! Constructor /*! Construct new find_iterator for a given finder and a range. */ template find_iterator( IteratorT Begin, IteratorT End, FinderT Finder ) : detail::find_iterator_base(Finder,0), m_Match(Begin,Begin), m_End(End) { increment(); } //! Constructor /*! Construct new find_iterator for a given finder and a range. */ template find_iterator( RangeT& Col, FinderT Finder ) : detail::find_iterator_base(Finder,0) { iterator_range::type> lit_col(::boost::as_literal(Col)); m_Match=::boost::make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); m_End=::boost::end(lit_col); increment(); } private: // iterator operations // dereference const match_type& dereference() const { return m_Match; } // increment void increment() { if(m_Match.begin() == m_Match.end()) m_Match=this->do_find(m_Match.end(),m_End); else { input_iterator_type last = m_Match.begin(); m_Match=this->do_find(++last,m_End); } } // comparison bool equal( const find_iterator& Other ) const { bool bEof=eof(); bool bOtherEof=Other.eof(); return bEof || bOtherEof ? bEof==bOtherEof : ( m_Match==Other.m_Match && m_End==Other.m_End ); } public: // operations //! Eof check /*! Check the eof condition. Eof condition means that there is nothing more to be searched i.e. find_iterator is after the last match. */ bool eof() const { return this->is_null() || ( m_Match.begin() == m_End && m_Match.end() == m_End ); } private: // Attributes match_type m_Match; input_iterator_type m_End; }; //! find iterator construction helper /*! * Construct a find iterator to iterate through the specified string */ template inline find_iterator< BOOST_STRING_TYPENAME range_iterator::type> make_find_iterator( RangeT& Collection, FinderT Finder) { return find_iterator::type>( Collection, Finder); } // split iterator -----------------------------------------------// //! split_iterator /*! Split iterator encapsulates a Finder and allows for incremental searching in a string. Unlike the find iterator, split iterator iterates through gaps between matches. Find iterator is a readable forward traversal iterator. Dereferencing the iterator yields an iterator_range delimiting the current match. */ template class split_iterator : public iterator_facade< split_iterator, const iterator_range, forward_traversal_tag >, private detail::find_iterator_base { private: // facade support friend class ::boost::iterator_core_access; private: // typedefs typedef detail::find_iterator_base base_type; typedef BOOST_STRING_TYPENAME base_type::input_iterator_type input_iterator_type; typedef BOOST_STRING_TYPENAME base_type::match_type match_type; public: //! Default constructor /*! Construct null iterator. All null iterators are equal. \post eof()==true */ split_iterator() {} //! Copy constructor /*! Construct a copy of the split_iterator */ split_iterator( const split_iterator& Other ) : base_type(Other), m_Match(Other.m_Match), m_Next(Other.m_Next), m_End(Other.m_End), m_bEof(Other.m_bEof) {} //! Constructor /*! Construct new split_iterator for a given finder and a range. */ template split_iterator( IteratorT Begin, IteratorT End, FinderT Finder ) : detail::find_iterator_base(Finder,0), m_Match(Begin,Begin), m_Next(Begin), m_End(End), m_bEof(false) { // force the correct behavior for empty sequences and yield at least one token if(Begin!=End) { increment(); } } //! Constructor /*! Construct new split_iterator for a given finder and a collection. */ template split_iterator( RangeT& Col, FinderT Finder ) : detail::find_iterator_base(Finder,0), m_bEof(false) { iterator_range::type> lit_col(::boost::as_literal(Col)); m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); m_Next=::boost::begin(lit_col); m_End=::boost::end(lit_col); // force the correct behavior for empty sequences and yield at least one token if(m_Next!=m_End) { increment(); } } private: // iterator operations // dereference const match_type& dereference() const { return m_Match; } // increment void increment() { match_type FindMatch=this->do_find( m_Next, m_End ); if(FindMatch.begin()==m_End && FindMatch.end()==m_End) { if(m_Match.end()==m_End) { // Mark iterator as eof m_bEof=true; } } m_Match=match_type( m_Next, FindMatch.begin() ); m_Next=FindMatch.end(); } // comparison bool equal( const split_iterator& Other ) const { bool bEof=eof(); bool bOtherEof=Other.eof(); return bEof || bOtherEof ? bEof==bOtherEof : ( m_Match==Other.m_Match && m_Next==Other.m_Next && m_End==Other.m_End ); } public: // operations //! Eof check /*! Check the eof condition. Eof condition means that there is nothing more to be searched i.e. find_iterator is after the last match. */ bool eof() const { return this->is_null() || m_bEof; } private: // Attributes match_type m_Match; input_iterator_type m_Next; input_iterator_type m_End; bool m_bEof; }; //! split iterator construction helper /*! * Construct a split iterator to iterate through the specified collection */ template inline split_iterator< BOOST_STRING_TYPENAME range_iterator::type> make_split_iterator( RangeT& Collection, FinderT Finder) { return split_iterator::type>( Collection, Finder); } } // namespace algorithm // pull names to the boost namespace using algorithm::find_iterator; using algorithm::make_find_iterator; using algorithm::split_iterator; using algorithm::make_split_iterator; } // namespace boost #endif // BOOST_STRING_FIND_ITERATOR_HPP