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.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 //! Copy constructor 235 /*! 236 Construct a copy of the split_iterator 237 */ split_iterator(const split_iterator & Other)238 split_iterator( const split_iterator& Other ) : 239 base_type(Other), 240 m_Match(Other.m_Match), 241 m_Next(Other.m_Next), 242 m_End(Other.m_End), 243 m_bEof(Other.m_bEof) 244 {} 245 246 //! Constructor 247 /*! 248 Construct new split_iterator for a given finder 249 and a range. 250 */ 251 template<typename FinderT> split_iterator(IteratorT Begin,IteratorT End,FinderT Finder)252 split_iterator( 253 IteratorT Begin, 254 IteratorT End, 255 FinderT Finder ) : 256 detail::find_iterator_base<IteratorT>(Finder,0), 257 m_Match(Begin,Begin), 258 m_Next(Begin), 259 m_End(End), 260 m_bEof(false) 261 { 262 // force the correct behavior for empty sequences and yield at least one token 263 if(Begin!=End) 264 { 265 increment(); 266 } 267 } 268 //! Constructor 269 /*! 270 Construct new split_iterator for a given finder 271 and a collection. 272 */ 273 template<typename FinderT, typename RangeT> split_iterator(RangeT & Col,FinderT Finder)274 split_iterator( 275 RangeT& Col, 276 FinderT Finder ) : 277 detail::find_iterator_base<IteratorT>(Finder,0), 278 m_bEof(false) 279 { 280 iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col)); 281 m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); 282 m_Next=::boost::begin(lit_col); 283 m_End=::boost::end(lit_col); 284 285 // force the correct behavior for empty sequences and yield at least one token 286 if(m_Next!=m_End) 287 { 288 increment(); 289 } 290 } 291 292 293 private: 294 // iterator operations 295 296 // dereference dereference() const297 const match_type& dereference() const 298 { 299 return m_Match; 300 } 301 302 // increment increment()303 void increment() 304 { 305 match_type FindMatch=this->do_find( m_Next, m_End ); 306 307 if(FindMatch.begin()==m_End && FindMatch.end()==m_End) 308 { 309 if(m_Match.end()==m_End) 310 { 311 // Mark iterator as eof 312 m_bEof=true; 313 } 314 } 315 316 m_Match=match_type( m_Next, FindMatch.begin() ); 317 m_Next=FindMatch.end(); 318 } 319 320 // comparison equal(const split_iterator & Other) const321 bool equal( const split_iterator& Other ) const 322 { 323 bool bEof=eof(); 324 bool bOtherEof=Other.eof(); 325 326 return bEof || bOtherEof ? bEof==bOtherEof : 327 ( 328 m_Match==Other.m_Match && 329 m_Next==Other.m_Next && 330 m_End==Other.m_End 331 ); 332 } 333 334 public: 335 // operations 336 337 //! Eof check 338 /*! 339 Check the eof condition. Eof condition means that 340 there is nothing more to be searched i.e. find_iterator 341 is after the last match. 342 */ eof() const343 bool eof() const 344 { 345 return this->is_null() || m_bEof; 346 } 347 348 private: 349 // Attributes 350 match_type m_Match; 351 input_iterator_type m_Next; 352 input_iterator_type m_End; 353 bool m_bEof; 354 }; 355 356 //! split iterator construction helper 357 /*! 358 * Construct a split iterator to iterate through the specified collection 359 */ 360 template<typename RangeT, typename FinderT> 361 inline split_iterator< 362 BOOST_STRING_TYPENAME range_iterator<RangeT>::type> make_split_iterator(RangeT & Collection,FinderT Finder)363 make_split_iterator( 364 RangeT& Collection, 365 FinderT Finder) 366 { 367 return split_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>( 368 Collection, Finder); 369 } 370 371 372 } // namespace algorithm 373 374 // pull names to the boost namespace 375 using algorithm::find_iterator; 376 using algorithm::make_find_iterator; 377 using algorithm::split_iterator; 378 using algorithm::make_split_iterator; 379 380 } // namespace boost 381 382 383 #endif // BOOST_STRING_FIND_ITERATOR_HPP 384