1 // Boost string_algo library find_iterator.hpp header file ---------------------------// 2 3 // Copyright Pavol Droba 2002-2004. 4 // 5 // Distributed under the Boost Software License, Version 1.0. 6 // (See accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 9 // See http://www.boost.org/ for updates, documentation, and revision history. 10 11 #ifndef BOOST_STRING_FIND_ITERATOR_HPP 12 #define BOOST_STRING_FIND_ITERATOR_HPP 13 14 #include <boost/algorithm/string/config.hpp> 15 #include <boost/iterator/iterator_facade.hpp> 16 #include <boost/iterator/iterator_categories.hpp> 17 18 #include <boost/range/iterator_range_core.hpp> 19 #include <boost/range/begin.hpp> 20 #include <boost/range/end.hpp> 21 #include <boost/range/iterator.hpp> 22 #include <boost/range/as_literal.hpp> 23 24 #include <boost/algorithm/string/detail/find_iterator.hpp> 25 26 /*! \file 27 Defines find iterator classes. Find iterator repeatedly applies a Finder 28 to the specified input string to search for matches. Dereferencing 29 the iterator yields the current match or a range between the last and the current 30 match depending on the iterator used. 31 */ 32 33 namespace boost { 34 namespace algorithm { 35 36 // find_iterator -----------------------------------------------// 37 38 //! find_iterator 39 /*! 40 Find iterator encapsulates a Finder and allows 41 for incremental searching in a string. 42 Each increment moves the iterator to the next match. 43 44 Find iterator is a readable forward traversal iterator. 45 46 Dereferencing the iterator yields an iterator_range delimiting 47 the current match. 48 */ 49 template<typename IteratorT> 50 class find_iterator : 51 public iterator_facade< 52 find_iterator<IteratorT>, 53 const iterator_range<IteratorT>, 54 forward_traversal_tag >, 55 private detail::find_iterator_base<IteratorT> 56 { 57 private: 58 // facade support 59 friend class ::boost::iterator_core_access; 60 61 private: 62 // typedefs 63 64 typedef detail::find_iterator_base<IteratorT> base_type; 65 typedef BOOST_STRING_TYPENAME 66 base_type::input_iterator_type input_iterator_type; 67 typedef BOOST_STRING_TYPENAME 68 base_type::match_type match_type; 69 70 public: 71 //! Default constructor 72 /*! 73 Construct null iterator. All null iterators are equal. 74 75 \post eof()==true 76 */ find_iterator()77 find_iterator() {} 78 79 //! Copy constructor 80 /*! 81 Construct a copy of the find_iterator 82 */ find_iterator(const find_iterator & Other)83 find_iterator( const find_iterator& Other ) : 84 base_type(Other), 85 m_Match(Other.m_Match), 86 m_End(Other.m_End) {} 87 88 //! Constructor 89 /*! 90 Construct new find_iterator for a given finder 91 and a range. 92 */ 93 template<typename FinderT> find_iterator(IteratorT Begin,IteratorT End,FinderT Finder)94 find_iterator( 95 IteratorT Begin, 96 IteratorT End, 97 FinderT Finder ) : 98 detail::find_iterator_base<IteratorT>(Finder,0), 99 m_Match(Begin,Begin), 100 m_End(End) 101 { 102 increment(); 103 } 104 105 //! Constructor 106 /*! 107 Construct new find_iterator for a given finder 108 and a range. 109 */ 110 template<typename FinderT, typename RangeT> find_iterator(RangeT & Col,FinderT Finder)111 find_iterator( 112 RangeT& Col, 113 FinderT Finder ) : 114 detail::find_iterator_base<IteratorT>(Finder,0) 115 { 116 iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col)); 117 m_Match=::boost::make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); 118 m_End=::boost::end(lit_col); 119 120 increment(); 121 } 122 123 private: 124 // iterator operations 125 126 // dereference dereference() const127 const match_type& dereference() const 128 { 129 return m_Match; 130 } 131 132 // increment increment()133 void increment() 134 { 135 m_Match=this->do_find(m_Match.end(),m_End); 136 } 137 138 // comparison equal(const find_iterator & Other) const139 bool equal( const find_iterator& Other ) const 140 { 141 bool bEof=eof(); 142 bool bOtherEof=Other.eof(); 143 144 return bEof || bOtherEof ? bEof==bOtherEof : 145 ( 146 m_Match==Other.m_Match && 147 m_End==Other.m_End 148 ); 149 } 150 151 public: 152 // operations 153 154 //! Eof check 155 /*! 156 Check the eof condition. Eof condition means that 157 there is nothing more to be searched i.e. find_iterator 158 is after the last match. 159 */ eof() const160 bool eof() const 161 { 162 return 163 this->is_null() || 164 ( 165 m_Match.begin() == m_End && 166 m_Match.end() == m_End 167 ); 168 } 169 170 private: 171 // Attributes 172 match_type m_Match; 173 input_iterator_type m_End; 174 }; 175 176 //! find iterator construction helper 177 /*! 178 * Construct a find iterator to iterate through the specified string 179 */ 180 template<typename RangeT, typename FinderT> 181 inline find_iterator< 182 BOOST_STRING_TYPENAME range_iterator<RangeT>::type> make_find_iterator(RangeT & Collection,FinderT Finder)183 make_find_iterator( 184 RangeT& Collection, 185 FinderT Finder) 186 { 187 return find_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>( 188 Collection, Finder); 189 } 190 191 // split iterator -----------------------------------------------// 192 193 //! split_iterator 194 /*! 195 Split iterator encapsulates a Finder and allows 196 for incremental searching in a string. 197 Unlike the find iterator, split iterator iterates 198 through gaps between matches. 199 200 Find iterator is a readable forward traversal iterator. 201 202 Dereferencing the iterator yields an iterator_range delimiting 203 the current match. 204 */ 205 template<typename IteratorT> 206 class split_iterator : 207 public iterator_facade< 208 split_iterator<IteratorT>, 209 const iterator_range<IteratorT>, 210 forward_traversal_tag >, 211 private detail::find_iterator_base<IteratorT> 212 { 213 private: 214 // facade support 215 friend class ::boost::iterator_core_access; 216 217 private: 218 // typedefs 219 220 typedef detail::find_iterator_base<IteratorT> base_type; 221 typedef BOOST_STRING_TYPENAME 222 base_type::input_iterator_type input_iterator_type; 223 typedef BOOST_STRING_TYPENAME 224 base_type::match_type match_type; 225 226 public: 227 //! Default constructor 228 /*! 229 Construct null iterator. All null iterators are equal. 230 231 \post eof()==true 232 */ split_iterator()233 split_iterator() : 234 m_Next(), 235 m_End(), 236 m_bEof(true) 237 {} 238 239 //! Copy constructor 240 /*! 241 Construct a copy of the split_iterator 242 */ split_iterator(const split_iterator & Other)243 split_iterator( const split_iterator& Other ) : 244 base_type(Other), 245 m_Match(Other.m_Match), 246 m_Next(Other.m_Next), 247 m_End(Other.m_End), 248 m_bEof(Other.m_bEof) 249 {} 250 251 //! Constructor 252 /*! 253 Construct new split_iterator for a given finder 254 and a range. 255 */ 256 template<typename FinderT> split_iterator(IteratorT Begin,IteratorT End,FinderT Finder)257 split_iterator( 258 IteratorT Begin, 259 IteratorT End, 260 FinderT Finder ) : 261 detail::find_iterator_base<IteratorT>(Finder,0), 262 m_Match(Begin,Begin), 263 m_Next(Begin), 264 m_End(End), 265 m_bEof(false) 266 { 267 // force the correct behavior for empty sequences and yield at least one token 268 if(Begin!=End) 269 { 270 increment(); 271 } 272 } 273 //! Constructor 274 /*! 275 Construct new split_iterator for a given finder 276 and a collection. 277 */ 278 template<typename FinderT, typename RangeT> split_iterator(RangeT & Col,FinderT Finder)279 split_iterator( 280 RangeT& Col, 281 FinderT Finder ) : 282 detail::find_iterator_base<IteratorT>(Finder,0), 283 m_bEof(false) 284 { 285 iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col)); 286 m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); 287 m_Next=::boost::begin(lit_col); 288 m_End=::boost::end(lit_col); 289 290 // force the correct behavior for empty sequences and yield at least one token 291 if(m_Next!=m_End) 292 { 293 increment(); 294 } 295 } 296 297 298 private: 299 // iterator operations 300 301 // dereference dereference() const302 const match_type& dereference() const 303 { 304 return m_Match; 305 } 306 307 // increment increment()308 void increment() 309 { 310 match_type FindMatch=this->do_find( m_Next, m_End ); 311 312 if(FindMatch.begin()==m_End && FindMatch.end()==m_End) 313 { 314 if(m_Match.end()==m_End) 315 { 316 // Mark iterator as eof 317 m_bEof=true; 318 } 319 } 320 321 m_Match=match_type( m_Next, FindMatch.begin() ); 322 m_Next=FindMatch.end(); 323 } 324 325 // comparison equal(const split_iterator & Other) const326 bool equal( const split_iterator& Other ) const 327 { 328 bool bEof=eof(); 329 bool bOtherEof=Other.eof(); 330 331 return bEof || bOtherEof ? bEof==bOtherEof : 332 ( 333 m_Match==Other.m_Match && 334 m_Next==Other.m_Next && 335 m_End==Other.m_End 336 ); 337 } 338 339 public: 340 // operations 341 342 //! Eof check 343 /*! 344 Check the eof condition. Eof condition means that 345 there is nothing more to be searched i.e. find_iterator 346 is after the last match. 347 */ eof() const348 bool eof() const 349 { 350 return this->is_null() || m_bEof; 351 } 352 353 private: 354 // Attributes 355 match_type m_Match; 356 input_iterator_type m_Next; 357 input_iterator_type m_End; 358 bool m_bEof; 359 }; 360 361 //! split iterator construction helper 362 /*! 363 * Construct a split iterator to iterate through the specified collection 364 */ 365 template<typename RangeT, typename FinderT> 366 inline split_iterator< 367 BOOST_STRING_TYPENAME range_iterator<RangeT>::type> make_split_iterator(RangeT & Collection,FinderT Finder)368 make_split_iterator( 369 RangeT& Collection, 370 FinderT Finder) 371 { 372 return split_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>( 373 Collection, Finder); 374 } 375 376 377 } // namespace algorithm 378 379 // pull names to the boost namespace 380 using algorithm::find_iterator; 381 using algorithm::make_find_iterator; 382 using algorithm::split_iterator; 383 using algorithm::make_split_iterator; 384 385 } // namespace boost 386 387 388 #endif // BOOST_STRING_FIND_ITERATOR_HPP 389