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