1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2014, Oracle and/or its affiliates. 4 5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle 6 7 // Licensed under the Boost Software License version 1.0. 8 // http://www.boost.org/users/license.html 9 10 #ifndef BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP 11 #define BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP 12 13 #include <boost/mpl/assert.hpp> 14 #include <boost/type_traits/is_convertible.hpp> 15 #include <boost/iterator.hpp> 16 #include <boost/iterator/iterator_facade.hpp> 17 #include <boost/iterator/iterator_categories.hpp> 18 19 20 namespace boost { namespace geometry 21 { 22 23 24 25 template 26 < 27 typename Iterator1, 28 typename Iterator2, 29 typename Value, 30 typename Reference = Value& 31 > 32 class concatenate_iterator 33 : public boost::iterator_facade 34 < 35 concatenate_iterator<Iterator1, Iterator2, Value, Reference>, 36 Value, 37 boost::bidirectional_traversal_tag, 38 Reference 39 > 40 { 41 private: 42 Iterator1 m_it1, m_end1; 43 Iterator2 m_begin2, m_it2; 44 45 public: 46 typedef Iterator1 first_iterator_type; 47 typedef Iterator2 second_iterator_type; 48 49 // default constructor concatenate_iterator()50 concatenate_iterator() {} 51 52 // for begin concatenate_iterator(Iterator1 it1,Iterator1 end1,Iterator2 begin2,Iterator2 it2)53 concatenate_iterator(Iterator1 it1, Iterator1 end1, 54 Iterator2 begin2, Iterator2 it2) 55 : m_it1(it1), m_end1(end1), m_begin2(begin2), m_it2(it2) 56 {} 57 58 // for end concatenate_iterator(Iterator1 end1,Iterator2 begin2,Iterator2 end2)59 concatenate_iterator(Iterator1 end1, Iterator2 begin2, Iterator2 end2) 60 : m_it1(end1), m_end1(end1), m_begin2(begin2), m_it2(end2) 61 {} 62 63 template 64 < 65 typename OtherIt1, 66 typename OtherIt2, 67 typename OtherValue, 68 typename OtherReference 69 > concatenate_iterator(concatenate_iterator<OtherIt1,OtherIt2,OtherValue,OtherReference> const & other)70 concatenate_iterator(concatenate_iterator 71 < 72 OtherIt1, 73 OtherIt2, 74 OtherValue, 75 OtherReference 76 > const& other) 77 : m_it1(other.m_it1) 78 , m_end1(other.m_end1) 79 , m_begin2(other.m_begin2) 80 , m_it2(other.m_it2) 81 { 82 static const bool are_conv 83 = boost::is_convertible<OtherIt1, Iterator1>::value 84 && boost::is_convertible<OtherIt2, Iterator2>::value; 85 86 BOOST_MPL_ASSERT_MSG((are_conv), 87 NOT_CONVERTIBLE, 88 (types<OtherIt1, OtherIt2>)); 89 } 90 91 private: 92 friend class boost::iterator_core_access; 93 94 template <typename It1, typename It2, typename V, typename R> 95 friend class concatenate_iterator; 96 dereference() const97 inline Reference dereference() const 98 { 99 if ( m_it1 == m_end1 ) 100 { 101 return *m_it2; 102 } 103 return *m_it1; 104 } 105 106 template 107 < 108 typename OtherIt1, 109 typename OtherIt2, 110 typename OtherValue, 111 typename OtherReference 112 > equal(concatenate_iterator<OtherIt1,OtherIt2,OtherValue,OtherReference> const & other) const113 inline bool equal(concatenate_iterator 114 < 115 OtherIt1, 116 OtherIt2, 117 OtherValue, 118 OtherReference 119 > const& other) const 120 { 121 return m_it1 == other.m_it1 && m_it2 == other.m_it2; 122 } 123 increment()124 inline void increment() 125 { 126 if ( m_it1 == m_end1 ) 127 { 128 ++m_it2; 129 } 130 else 131 { 132 ++m_it1; 133 } 134 } 135 decrement()136 inline void decrement() 137 { 138 if ( m_it2 == m_begin2 ) 139 { 140 --m_it1; 141 } 142 else 143 { 144 --m_it2; 145 } 146 } 147 }; 148 149 150 151 }} // namespace boost::geometry 152 153 #endif // BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP 154