element_iterator.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*-----------------------------------------------------------------------------+
  2. Copyright (c) 2009-2009: Joachim Faulhaber
  3. +------------------------------------------------------------------------------+
  4. Distributed under the Boost Software License, Version 1.0.
  5. (See accompanying file LICENCE.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. +-----------------------------------------------------------------------------*/
  8. #ifndef BOOST_ICL_DETAIL_ELEMENT_ITERATOR_HPP_JOFA_091104
  9. #define BOOST_ICL_DETAIL_ELEMENT_ITERATOR_HPP_JOFA_091104
  10. #include <boost/mpl/if.hpp>
  11. #include <boost/iterator/iterator_facade.hpp>
  12. #include <boost/config/warning_disable.hpp>
  13. #include <boost/icl/type_traits/succ_pred.hpp>
  14. #include <boost/icl/detail/mapped_reference.hpp>
  15. namespace boost{namespace icl
  16. {
  17. //------------------------------------------------------------------------------
  18. template<class Type>
  19. struct is_std_pair
  20. {
  21. typedef is_std_pair<Type> type;
  22. BOOST_STATIC_CONSTANT(bool, value = false);
  23. };
  24. template<class FirstT, class SecondT>
  25. struct is_std_pair<std::pair<FirstT, SecondT> >
  26. {
  27. typedef is_std_pair<std::pair<FirstT, SecondT> > type;
  28. BOOST_STATIC_CONSTANT(bool, value = true);
  29. };
  30. //------------------------------------------------------------------------------
  31. template<class Type>
  32. struct first_element
  33. {
  34. typedef Type type;
  35. };
  36. template<class FirstT, class SecondT>
  37. struct first_element<std::pair<FirstT, SecondT> >
  38. {
  39. typedef FirstT type;
  40. };
  41. //------------------------------------------------------------------------------
  42. template <class SegmentIteratorT> class element_iterator;
  43. template<class IteratorT>
  44. struct is_reverse
  45. {
  46. typedef is_reverse type;
  47. BOOST_STATIC_CONSTANT(bool, value = false);
  48. };
  49. template<class BaseIteratorT>
  50. struct is_reverse<std::reverse_iterator<BaseIteratorT> >
  51. {
  52. typedef is_reverse<std::reverse_iterator<BaseIteratorT> > type;
  53. BOOST_STATIC_CONSTANT(bool, value = true);
  54. };
  55. template<class BaseIteratorT>
  56. struct is_reverse<icl::element_iterator<BaseIteratorT> >
  57. {
  58. typedef is_reverse<icl::element_iterator<BaseIteratorT> > type;
  59. BOOST_STATIC_CONSTANT(bool, value = is_reverse<BaseIteratorT>::value);
  60. };
  61. //------------------------------------------------------------------------------
  62. template<class SegmentT>
  63. struct elemental;
  64. #ifdef ICL_USE_INTERVAL_TEMPLATE_TEMPLATE
  65. template<class DomainT, ICL_COMPARE Compare, ICL_INTERVAL(ICL_COMPARE) Interval>
  66. struct elemental<ICL_INTERVAL_TYPE(Interval,DomainT,Compare) >
  67. {
  68. typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) segment_type;
  69. typedef segment_type interval_type;
  70. typedef DomainT type;
  71. typedef DomainT domain_type;
  72. typedef DomainT codomain_type;
  73. typedef DomainT transit_type;
  74. };
  75. template< class DomainT, class CodomainT,
  76. ICL_COMPARE Compare, ICL_INTERVAL(ICL_COMPARE) Interval >
  77. struct elemental<std::pair<ICL_INTERVAL_TYPE(Interval,DomainT,Compare) const, CodomainT> >
  78. {
  79. typedef std::pair<ICL_INTERVAL_TYPE(Interval,DomainT,Compare), CodomainT> segment_type;
  80. typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) interval_type;
  81. typedef std::pair<DomainT, CodomainT> type;
  82. typedef DomainT domain_type;
  83. typedef CodomainT codomain_type;
  84. typedef mapped_reference<DomainT, CodomainT> transit_type;
  85. };
  86. #else //ICL_USE_INTERVAL_TEMPLATE_TYPE
  87. template<ICL_INTERVAL(ICL_COMPARE) Interval>
  88. struct elemental
  89. {
  90. typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) segment_type;
  91. typedef segment_type interval_type;
  92. typedef typename interval_traits<interval_type>::domain_type domain_type;
  93. typedef domain_type type;
  94. typedef domain_type codomain_type;
  95. typedef domain_type transit_type;
  96. };
  97. template< class CodomainT, ICL_INTERVAL(ICL_COMPARE) Interval >
  98. struct elemental<std::pair<ICL_INTERVAL_TYPE(Interval,DomainT,Compare) const, CodomainT> >
  99. {
  100. typedef std::pair<ICL_INTERVAL_TYPE(Interval,DomainT,Compare), CodomainT> segment_type;
  101. typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) interval_type;
  102. typedef typename interval_traits<interval_type>::domain_type domain_type;
  103. typedef CodomainT codomain_type;
  104. typedef std::pair<domain_type, codomain_type> type;
  105. typedef mapped_reference<domain_type, codomain_type> transit_type;
  106. };
  107. #endif //ICL_USE_INTERVAL_TEMPLATE_TEMPLATE
  108. //------------------------------------------------------------------------------
  109. //- struct segment_adapter
  110. //------------------------------------------------------------------------------
  111. template<class SegmentIteratorT, class SegmentT>
  112. struct segment_adapter;
  113. #ifdef ICL_USE_INTERVAL_TEMPLATE_TEMPLATE
  114. template<class SegmentIteratorT, class DomainT, ICL_COMPARE Compare, ICL_INTERVAL(ICL_COMPARE) Interval>
  115. struct segment_adapter<SegmentIteratorT, ICL_INTERVAL_TYPE(Interval,DomainT,Compare) >
  116. {
  117. typedef segment_adapter type;
  118. typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) segment_type;
  119. typedef segment_type interval_type;
  120. typedef typename interval_type::difference_type domain_difference_type;
  121. typedef DomainT domain_type;
  122. typedef DomainT codomain_type;
  123. typedef domain_type element_type;
  124. typedef domain_type& transit_type;
  125. static domain_type first (const SegmentIteratorT& leaper){ return leaper->first(); }
  126. static domain_type last (const SegmentIteratorT& leaper){ return leaper->last(); }
  127. static domain_difference_type length(const SegmentIteratorT& leaper){ return leaper->length();}
  128. static transit_type transient_element(domain_type& inter_pos, const SegmentIteratorT& leaper,
  129. const domain_difference_type& sneaker)
  130. {
  131. inter_pos = is_reverse<SegmentIteratorT>::value ? leaper->last() - sneaker
  132. : leaper->first() + sneaker;
  133. return inter_pos;
  134. }
  135. };
  136. template < class SegmentIteratorT, class DomainT, class CodomainT,
  137. ICL_COMPARE Compare, ICL_INTERVAL(ICL_COMPARE) Interval >
  138. struct segment_adapter<SegmentIteratorT, std::pair<ICL_INTERVAL_TYPE(Interval,DomainT,Compare) const, CodomainT> >
  139. {
  140. typedef segment_adapter type;
  141. typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) interval_type;
  142. typedef DomainT domain_type;
  143. typedef std::pair<DomainT, CodomainT> element_type;
  144. typedef CodomainT codomain_type;
  145. typedef mapped_reference<DomainT, CodomainT> transit_type;
  146. typedef typename difference_type_of<interval_traits<interval_type> >::type
  147. domain_difference_type;
  148. static domain_type first (const SegmentIteratorT& leaper){ return leaper->first.first(); }
  149. static domain_type last (const SegmentIteratorT& leaper){ return leaper->first.last(); }
  150. static domain_difference_type length(const SegmentIteratorT& leaper){ return leaper->first.length();}
  151. static transit_type transient_element(domain_type& inter_pos, const SegmentIteratorT& leaper,
  152. const domain_difference_type& sneaker)
  153. {
  154. inter_pos = is_reverse<SegmentIteratorT>::value ? leaper->first.last() - sneaker
  155. : leaper->first.first() + sneaker;
  156. return transit_type(inter_pos, leaper->second);
  157. }
  158. };
  159. #else // ICL_USE_INTERVAL_TEMPLATE_TYPE
  160. template<class SegmentIteratorT, ICL_INTERVAL(ICL_COMPARE) Interval>
  161. struct segment_adapter
  162. {
  163. typedef segment_adapter type;
  164. typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) segment_type;
  165. typedef segment_type interval_type;
  166. typedef typename interval_traits<interval_type>::domain_type domain_type;
  167. typedef domain_type codomain_type;
  168. typedef domain_type element_type;
  169. typedef domain_type& transit_type;
  170. typedef typename difference_type_of<interval_traits<interval_type> >::type
  171. domain_difference_type;
  172. static domain_type first (const SegmentIteratorT& leaper){ return leaper->first(); }
  173. static domain_type last (const SegmentIteratorT& leaper){ return leaper->last(); }
  174. static domain_difference_type length(const SegmentIteratorT& leaper){ return icl::length(*leaper);}
  175. static transit_type transient_element(domain_type& inter_pos, const SegmentIteratorT& leaper,
  176. const domain_difference_type& sneaker)
  177. {
  178. inter_pos = is_reverse<SegmentIteratorT>::value ? icl::last(*leaper) - sneaker
  179. : icl::first(*leaper) + sneaker;
  180. return inter_pos;
  181. }
  182. };
  183. template < class SegmentIteratorT, class CodomainT, ICL_INTERVAL(ICL_COMPARE) Interval >
  184. struct segment_adapter<SegmentIteratorT, std::pair<ICL_INTERVAL_TYPE(Interval,DomainT,Compare) const, CodomainT> >
  185. {
  186. typedef segment_adapter type;
  187. typedef ICL_INTERVAL_TYPE(Interval,DomainT,Compare) interval_type;
  188. typedef typename interval_traits<interval_type>::domain_type domain_type;
  189. typedef CodomainT codomain_type;
  190. typedef std::pair<domain_type, codomain_type> element_type;
  191. typedef mapped_reference<domain_type, CodomainT> transit_type;
  192. typedef typename difference_type_of<interval_traits<interval_type> >::type
  193. domain_difference_type;
  194. static domain_type first (const SegmentIteratorT& leaper){ return leaper->first.first(); }
  195. static domain_type last (const SegmentIteratorT& leaper){ return leaper->first.last(); }
  196. static domain_difference_type length(const SegmentIteratorT& leaper){ return icl::length(leaper->first);}
  197. static transit_type transient_element(domain_type& inter_pos, const SegmentIteratorT& leaper,
  198. const domain_difference_type& sneaker)
  199. {
  200. inter_pos = is_reverse<SegmentIteratorT>::value ? icl::last(leaper->first) - sneaker
  201. : icl::first(leaper->first) + sneaker;
  202. return transit_type(inter_pos, leaper->second);
  203. }
  204. };
  205. #endif // ICL_USE_INTERVAL_TEMPLATE_TEMPLATE
  206. template <class SegmentIteratorT>
  207. class element_iterator
  208. : public boost::iterator_facade<
  209. element_iterator<SegmentIteratorT>
  210. , typename elemental<typename SegmentIteratorT::value_type>::transit_type
  211. , boost::bidirectional_traversal_tag
  212. , typename elemental<typename SegmentIteratorT::value_type>::transit_type
  213. >
  214. {
  215. public:
  216. typedef element_iterator type;
  217. typedef SegmentIteratorT segment_iterator;
  218. typedef typename SegmentIteratorT::value_type segment_type;
  219. typedef typename first_element<segment_type>::type interval_type;
  220. typedef typename elemental<segment_type>::type element_type;
  221. typedef typename elemental<segment_type>::domain_type domain_type;
  222. typedef typename elemental<segment_type>::codomain_type codomain_type;
  223. typedef typename elemental<segment_type>::transit_type transit_type;
  224. typedef transit_type value_type;
  225. typedef typename difference_type_of<interval_traits<interval_type> >::type
  226. domain_difference_type;
  227. private:
  228. typedef typename segment_adapter<segment_iterator,segment_type>::type adapt;
  229. struct enabler{};
  230. public:
  231. element_iterator()
  232. : _saltator(identity_element<segment_iterator>::value())
  233. , _reptator(identity_element<domain_difference_type>::value()){}
  234. explicit element_iterator(segment_iterator jumper)
  235. : _saltator(jumper), _reptator(identity_element<domain_difference_type>::value()) {}
  236. template <class SaltatorT>
  237. element_iterator
  238. ( element_iterator<SaltatorT> const& other
  239. , typename enable_if<boost::is_convertible<SaltatorT*,SegmentIteratorT*>, enabler>::type = enabler())
  240. : _saltator(other._saltator), _reptator(other._reptator) {}
  241. private:
  242. friend class boost::iterator_core_access;
  243. template <class> friend class element_iterator;
  244. template <class SaltatorT>
  245. bool equal(element_iterator<SaltatorT> const& other) const
  246. {
  247. return this->_saltator == other._saltator
  248. && this->_reptator == other._reptator;
  249. }
  250. void increment()
  251. {
  252. if(_reptator < icl::pred(adapt::length(_saltator)))
  253. ++_reptator;
  254. else
  255. {
  256. ++_saltator;
  257. _reptator = identity_element<domain_difference_type>::value();
  258. }
  259. }
  260. void decrement()
  261. {
  262. if(identity_element<domain_difference_type>::value() < _reptator)
  263. --_reptator;
  264. else
  265. {
  266. --_saltator;
  267. _reptator = adapt::length(_saltator);
  268. --_reptator;
  269. }
  270. }
  271. value_type dereference()const
  272. {
  273. return adapt::transient_element(_inter_pos, _saltator, _reptator);
  274. }
  275. private:
  276. segment_iterator _saltator; // satltare: to jump : the fast moving iterator
  277. mutable domain_difference_type _reptator; // reptare: to sneak : the slow moving iterator 0 based
  278. mutable domain_type _inter_pos; // inter position : Position within the current segment
  279. // _saltator->first.first() <= _inter_pos <= _saltator->first.last()
  280. };
  281. }} // namespace icl boost
  282. #endif // BOOST_ICL_DETAIL_ELEMENT_ITERATOR_HPP_JOFA_091104