flatten_iterator.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Licensed under the Boost Software License version 1.0.
  5. // http://www.boost.org/users/license.html
  6. #ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
  7. #define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
  8. #include <boost/mpl/assert.hpp>
  9. #include <boost/type_traits/is_convertible.hpp>
  10. #include <boost/iterator/iterator_facade.hpp>
  11. #include <boost/iterator/iterator_categories.hpp>
  12. #include <boost/geometry/core/assert.hpp>
  13. namespace boost { namespace geometry
  14. {
  15. template
  16. <
  17. typename OuterIterator,
  18. typename InnerIterator,
  19. typename Value,
  20. typename AccessInnerBegin,
  21. typename AccessInnerEnd,
  22. typename Reference = Value&
  23. >
  24. class flatten_iterator
  25. : public boost::iterator_facade
  26. <
  27. flatten_iterator
  28. <
  29. OuterIterator,
  30. InnerIterator,
  31. Value,
  32. AccessInnerBegin,
  33. AccessInnerEnd,
  34. Reference
  35. >,
  36. Value,
  37. boost::bidirectional_traversal_tag,
  38. Reference
  39. >
  40. {
  41. private:
  42. OuterIterator m_outer_it, m_outer_end;
  43. InnerIterator m_inner_it;
  44. public:
  45. typedef OuterIterator outer_iterator_type;
  46. typedef InnerIterator inner_iterator_type;
  47. // default constructor
  48. flatten_iterator() {}
  49. // for begin
  50. flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)
  51. : m_outer_it(outer_it), m_outer_end(outer_end)
  52. {
  53. advance_through_empty();
  54. }
  55. // for end
  56. flatten_iterator(OuterIterator outer_end)
  57. : m_outer_it(outer_end), m_outer_end(outer_end)
  58. {}
  59. template
  60. <
  61. typename OtherOuterIterator, typename OtherInnerIterator,
  62. typename OtherValue,
  63. typename OtherAccessInnerBegin, typename OtherAccessInnerEnd,
  64. typename OtherReference
  65. >
  66. flatten_iterator(flatten_iterator
  67. <
  68. OtherOuterIterator,
  69. OtherInnerIterator,
  70. OtherValue,
  71. OtherAccessInnerBegin,
  72. OtherAccessInnerEnd,
  73. OtherReference
  74. > const& other)
  75. : m_outer_it(other.m_outer_it),
  76. m_outer_end(other.m_outer_end),
  77. m_inner_it(other.m_inner_it)
  78. {
  79. static const bool are_conv
  80. = boost::is_convertible
  81. <
  82. OtherOuterIterator, OuterIterator
  83. >::value
  84. && boost::is_convertible
  85. <
  86. OtherInnerIterator, InnerIterator
  87. >::value;
  88. BOOST_MPL_ASSERT_MSG((are_conv),
  89. NOT_CONVERTIBLE,
  90. (types<OtherOuterIterator, OtherInnerIterator>));
  91. }
  92. flatten_iterator& operator=(flatten_iterator const& other)
  93. {
  94. m_outer_it = other.m_outer_it;
  95. m_outer_end = other.m_outer_end;
  96. // avoid assigning an iterator having singular value
  97. if ( other.m_outer_it != other.m_outer_end )
  98. {
  99. m_inner_it = other.m_inner_it;
  100. }
  101. return *this;
  102. }
  103. private:
  104. friend class boost::iterator_core_access;
  105. template
  106. <
  107. typename Outer,
  108. typename Inner,
  109. typename V,
  110. typename InnerBegin,
  111. typename InnerEnd,
  112. typename R
  113. >
  114. friend class flatten_iterator;
  115. static inline bool empty(OuterIterator outer_it)
  116. {
  117. return AccessInnerBegin::apply(*outer_it)
  118. == AccessInnerEnd::apply(*outer_it);
  119. }
  120. inline void advance_through_empty()
  121. {
  122. while ( m_outer_it != m_outer_end && empty(m_outer_it) )
  123. {
  124. ++m_outer_it;
  125. }
  126. if ( m_outer_it != m_outer_end )
  127. {
  128. m_inner_it = AccessInnerBegin::apply(*m_outer_it);
  129. }
  130. }
  131. inline Reference dereference() const
  132. {
  133. BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
  134. BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
  135. return *m_inner_it;
  136. }
  137. template
  138. <
  139. typename OtherOuterIterator,
  140. typename OtherInnerIterator,
  141. typename OtherValue,
  142. typename OtherAccessInnerBegin,
  143. typename OtherAccessInnerEnd,
  144. typename OtherReference
  145. >
  146. inline bool equal(flatten_iterator
  147. <
  148. OtherOuterIterator,
  149. OtherInnerIterator,
  150. OtherValue,
  151. OtherAccessInnerBegin,
  152. OtherAccessInnerEnd,
  153. OtherReference
  154. > const& other) const
  155. {
  156. if ( m_outer_it != other.m_outer_it )
  157. {
  158. return false;
  159. }
  160. if ( m_outer_it == m_outer_end )
  161. {
  162. return true;
  163. }
  164. return m_inner_it == other.m_inner_it;
  165. }
  166. inline void increment()
  167. {
  168. BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
  169. BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
  170. ++m_inner_it;
  171. if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) )
  172. {
  173. ++m_outer_it;
  174. advance_through_empty();
  175. }
  176. }
  177. inline void decrement()
  178. {
  179. if ( m_outer_it == m_outer_end
  180. || m_inner_it == AccessInnerBegin::apply(*m_outer_it) )
  181. {
  182. do
  183. {
  184. --m_outer_it;
  185. }
  186. while ( empty(m_outer_it) );
  187. m_inner_it = AccessInnerEnd::apply(*m_outer_it);
  188. }
  189. --m_inner_it;
  190. }
  191. };
  192. }} // namespace boost::geometry
  193. #endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP