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/iterator_facade.hpp>
16 #include <boost/iterator/iterator_categories.hpp>
17 
18 
19 namespace boost { namespace geometry
20 {
21 
22 
23 
24 template
25 <
26     typename Iterator1,
27     typename Iterator2,
28     typename Value,
29     typename Reference = Value&
30 >
31 class concatenate_iterator
32     : public boost::iterator_facade
33         <
34             concatenate_iterator<Iterator1, Iterator2, Value, Reference>,
35             Value,
36             boost::bidirectional_traversal_tag,
37             Reference
38         >
39 {
40 private:
41     Iterator1 m_it1, m_end1;
42     Iterator2 m_begin2, m_it2;
43 
44 public:
45     typedef Iterator1 first_iterator_type;
46     typedef Iterator2 second_iterator_type;
47 
48     // default constructor
concatenate_iterator()49     concatenate_iterator() {}
50 
51     // for begin
concatenate_iterator(Iterator1 it1,Iterator1 end1,Iterator2 begin2,Iterator2 it2)52     concatenate_iterator(Iterator1 it1, Iterator1 end1,
53                          Iterator2 begin2, Iterator2 it2)
54         : m_it1(it1), m_end1(end1), m_begin2(begin2), m_it2(it2)
55     {}
56 
57     // for end
concatenate_iterator(Iterator1 end1,Iterator2 begin2,Iterator2 end2)58     concatenate_iterator(Iterator1 end1, Iterator2 begin2, Iterator2 end2)
59         : m_it1(end1), m_end1(end1), m_begin2(begin2), m_it2(end2)
60     {}
61 
62     template
63     <
64         typename OtherIt1,
65         typename OtherIt2,
66         typename OtherValue,
67         typename OtherReference
68     >
concatenate_iterator(concatenate_iterator<OtherIt1,OtherIt2,OtherValue,OtherReference> const & other)69     concatenate_iterator(concatenate_iterator
70                          <
71                              OtherIt1,
72                              OtherIt2,
73                              OtherValue,
74                              OtherReference
75                          > const& other)
76         : m_it1(other.m_it1)
77         , m_end1(other.m_end1)
78         , m_begin2(other.m_begin2)
79         , m_it2(other.m_it2)
80     {
81         static const bool are_conv
82             = boost::is_convertible<OtherIt1, Iterator1>::value
83            && boost::is_convertible<OtherIt2, Iterator2>::value;
84 
85         BOOST_MPL_ASSERT_MSG((are_conv),
86                              NOT_CONVERTIBLE,
87                              (types<OtherIt1, OtherIt2>));
88     }
89 
90 private:
91     friend class boost::iterator_core_access;
92 
93     template <typename It1, typename It2, typename V, typename R>
94     friend class concatenate_iterator;
95 
dereference() const96     inline Reference dereference() const
97     {
98         if ( m_it1 == m_end1 )
99         {
100             return *m_it2;
101         }
102         return *m_it1;
103     }
104 
105     template
106     <
107         typename OtherIt1,
108         typename OtherIt2,
109         typename OtherValue,
110         typename OtherReference
111     >
equal(concatenate_iterator<OtherIt1,OtherIt2,OtherValue,OtherReference> const & other) const112     inline bool equal(concatenate_iterator
113                       <
114                           OtherIt1,
115                           OtherIt2,
116                           OtherValue,
117                           OtherReference
118                       > const& other) const
119     {
120         return m_it1 == other.m_it1 && m_it2 == other.m_it2;
121     }
122 
increment()123     inline void increment()
124     {
125         if ( m_it1 == m_end1 )
126         {
127             ++m_it2;
128         }
129         else
130         {
131             ++m_it1;
132         }
133     }
134 
decrement()135     inline void decrement()
136     {
137         if ( m_it2 == m_begin2 )
138         {
139             --m_it1;
140         }
141         else
142         {
143             --m_it2;
144         }
145     }
146 };
147 
148 
149 
150 }} // namespace boost::geometry
151 
152 #endif // BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP
153