find_iterator.hpp 13 KB

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