Chris@102: // Boost.Geometry (aka GGL, Generic Geometry Library) Chris@102: Chris@102: // Copyright (c) 2014, Oracle and/or its affiliates. Chris@102: Chris@102: // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle Chris@102: Chris@102: // Licensed under the Boost Software License version 1.0. Chris@102: // http://www.boost.org/users/license.html Chris@102: Chris@102: #ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP Chris@102: #define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: Chris@102: namespace boost { namespace geometry Chris@102: { Chris@102: Chris@102: Chris@102: Chris@102: template Chris@102: < Chris@102: typename OuterIterator, Chris@102: typename InnerIterator, Chris@102: typename Value, Chris@102: typename AccessInnerBegin, Chris@102: typename AccessInnerEnd, Chris@102: typename Reference = Value& Chris@102: > Chris@102: class flatten_iterator Chris@102: : public boost::iterator_facade Chris@102: < Chris@102: flatten_iterator Chris@102: < Chris@102: OuterIterator, Chris@102: InnerIterator, Chris@102: Value, Chris@102: AccessInnerBegin, Chris@102: AccessInnerEnd, Chris@102: Reference Chris@102: >, Chris@102: Value, Chris@102: boost::bidirectional_traversal_tag, Chris@102: Reference Chris@102: > Chris@102: { Chris@102: private: Chris@102: OuterIterator m_outer_it, m_outer_end; Chris@102: InnerIterator m_inner_it; Chris@102: Chris@102: public: Chris@102: typedef OuterIterator outer_iterator_type; Chris@102: typedef InnerIterator inner_iterator_type; Chris@102: Chris@102: // default constructor Chris@102: flatten_iterator() {} Chris@102: Chris@102: // for begin Chris@102: flatten_iterator(OuterIterator outer_it, OuterIterator outer_end) Chris@102: : m_outer_it(outer_it), m_outer_end(outer_end) Chris@102: { Chris@102: advance_through_empty(); Chris@102: } Chris@102: Chris@102: // for end Chris@102: flatten_iterator(OuterIterator outer_end) Chris@102: : m_outer_it(outer_end), m_outer_end(outer_end) Chris@102: {} Chris@102: Chris@102: template Chris@102: < Chris@102: typename OtherOuterIterator, typename OtherInnerIterator, Chris@102: typename OtherValue, Chris@102: typename OtherAccessInnerBegin, typename OtherAccessInnerEnd, Chris@102: typename OtherReference Chris@102: > Chris@102: flatten_iterator(flatten_iterator Chris@102: < Chris@102: OtherOuterIterator, Chris@102: OtherInnerIterator, Chris@102: OtherValue, Chris@102: OtherAccessInnerBegin, Chris@102: OtherAccessInnerEnd, Chris@102: OtherReference Chris@102: > const& other) Chris@102: : m_outer_it(other.m_outer_it), Chris@102: m_outer_end(other.m_outer_end), Chris@102: m_inner_it(other.m_inner_it) Chris@102: { Chris@102: static const bool are_conv Chris@102: = boost::is_convertible Chris@102: < Chris@102: OtherOuterIterator, OuterIterator Chris@102: >::value Chris@102: && boost::is_convertible Chris@102: < Chris@102: OtherInnerIterator, InnerIterator Chris@102: >::value; Chris@102: Chris@102: BOOST_MPL_ASSERT_MSG((are_conv), Chris@102: NOT_CONVERTIBLE, Chris@102: (types)); Chris@102: } Chris@102: Chris@102: flatten_iterator& operator=(flatten_iterator const& other) Chris@102: { Chris@102: m_outer_it = other.m_outer_it; Chris@102: m_outer_end = other.m_outer_end; Chris@102: // avoid assigning an iterator having singular value Chris@102: if ( other.m_outer_it != other.m_outer_end ) Chris@102: { Chris@102: m_inner_it = other.m_inner_it; Chris@102: } Chris@102: return *this; Chris@102: } Chris@102: Chris@102: private: Chris@102: friend class boost::iterator_core_access; Chris@102: Chris@102: template Chris@102: < Chris@102: typename Outer, Chris@102: typename Inner, Chris@102: typename V, Chris@102: typename InnerBegin, Chris@102: typename InnerEnd, Chris@102: typename R Chris@102: > Chris@102: friend class flatten_iterator; Chris@102: Chris@102: static inline bool empty(OuterIterator outer_it) Chris@102: { Chris@102: return AccessInnerBegin::apply(*outer_it) Chris@102: == AccessInnerEnd::apply(*outer_it); Chris@102: } Chris@102: Chris@102: inline void advance_through_empty() Chris@102: { Chris@102: while ( m_outer_it != m_outer_end && empty(m_outer_it) ) Chris@102: { Chris@102: ++m_outer_it; Chris@102: } Chris@102: Chris@102: if ( m_outer_it != m_outer_end ) Chris@102: { Chris@102: m_inner_it = AccessInnerBegin::apply(*m_outer_it); Chris@102: } Chris@102: } Chris@102: Chris@102: inline Reference dereference() const Chris@102: { Chris@102: BOOST_ASSERT( m_outer_it != m_outer_end ); Chris@102: BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) ); Chris@102: return *m_inner_it; Chris@102: } Chris@102: Chris@102: Chris@102: template Chris@102: < Chris@102: typename OtherOuterIterator, Chris@102: typename OtherInnerIterator, Chris@102: typename OtherValue, Chris@102: typename OtherAccessInnerBegin, Chris@102: typename OtherAccessInnerEnd, Chris@102: typename OtherReference Chris@102: > Chris@102: inline bool equal(flatten_iterator Chris@102: < Chris@102: OtherOuterIterator, Chris@102: OtherInnerIterator, Chris@102: OtherValue, Chris@102: OtherAccessInnerBegin, Chris@102: OtherAccessInnerEnd, Chris@102: OtherReference Chris@102: > const& other) const Chris@102: { Chris@102: if ( m_outer_it != other.m_outer_it ) Chris@102: { Chris@102: return false; Chris@102: } Chris@102: Chris@102: if ( m_outer_it == m_outer_end ) Chris@102: { Chris@102: return true; Chris@102: } Chris@102: Chris@102: return m_inner_it == other.m_inner_it; Chris@102: } Chris@102: Chris@102: inline void increment() Chris@102: { Chris@102: BOOST_ASSERT( m_outer_it != m_outer_end ); Chris@102: BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) ); Chris@102: Chris@102: ++m_inner_it; Chris@102: if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) ) Chris@102: { Chris@102: ++m_outer_it; Chris@102: advance_through_empty(); Chris@102: } Chris@102: } Chris@102: Chris@102: inline void decrement() Chris@102: { Chris@102: if ( m_outer_it == m_outer_end Chris@102: || m_inner_it == AccessInnerBegin::apply(*m_outer_it) ) Chris@102: { Chris@102: do Chris@102: { Chris@102: --m_outer_it; Chris@102: } Chris@102: while ( empty(m_outer_it) ); Chris@102: m_inner_it = --AccessInnerEnd::apply(*m_outer_it); Chris@102: } Chris@102: else Chris@102: { Chris@102: --m_inner_it; Chris@102: } Chris@102: } Chris@102: }; Chris@102: Chris@102: Chris@102: Chris@102: }} // namespace boost::geometry Chris@102: Chris@102: Chris@102: #endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP