Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:35:36

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2014-2021, Oracle and/or its affiliates.
0004 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0005 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0006 
0007 // Licensed under the Boost Software License version 1.0.
0008 // http://www.boost.org/users/license.html
0009 
0010 #ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
0011 #define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
0012 
0013 
0014 #include <type_traits>
0015 
0016 #include <boost/iterator/iterator_facade.hpp>
0017 #include <boost/iterator/iterator_categories.hpp>
0018 
0019 #include <boost/geometry/core/assert.hpp>
0020 
0021 
0022 namespace boost { namespace geometry
0023 {
0024 
0025 
0026 
0027 template
0028 <
0029     typename OuterIterator,
0030     typename InnerIterator,
0031     typename Value,
0032     typename AccessInnerBegin,
0033     typename AccessInnerEnd,
0034     typename Reference = Value&
0035 >
0036 class flatten_iterator
0037     : public boost::iterator_facade
0038         <
0039             flatten_iterator
0040                 <
0041                     OuterIterator,
0042                     InnerIterator,
0043                     Value,
0044                     AccessInnerBegin,
0045                     AccessInnerEnd,
0046                     Reference
0047                 >,
0048             Value,
0049             boost::bidirectional_traversal_tag,
0050             Reference
0051         >
0052 {
0053 private:
0054     OuterIterator m_outer_it, m_outer_end;
0055     InnerIterator m_inner_it;
0056 
0057 public:
0058     typedef OuterIterator outer_iterator_type;
0059     typedef InnerIterator inner_iterator_type;
0060 
0061     // default constructor
0062     flatten_iterator() = default;
0063 
0064     // for begin
0065     flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)
0066         : m_outer_it(outer_it), m_outer_end(outer_end)
0067     {
0068         advance_through_empty();
0069     }
0070 
0071     // for end
0072     flatten_iterator(OuterIterator outer_end)
0073         : m_outer_it(outer_end), m_outer_end(outer_end)
0074     {}
0075 
0076     template
0077     <
0078         typename OtherOuterIterator, typename OtherInnerIterator,
0079         typename OtherValue,
0080         typename OtherAccessInnerBegin, typename OtherAccessInnerEnd,
0081         typename OtherReference,
0082         std::enable_if_t
0083             <
0084                 std::is_convertible<OtherOuterIterator, OuterIterator>::value
0085                 && std::is_convertible<OtherInnerIterator, InnerIterator>::value,
0086                 int
0087             > = 0
0088     >
0089     flatten_iterator(flatten_iterator
0090                      <
0091                          OtherOuterIterator,
0092                          OtherInnerIterator,
0093                          OtherValue,
0094                          OtherAccessInnerBegin,
0095                          OtherAccessInnerEnd,
0096                          OtherReference
0097                      > const& other)
0098         : m_outer_it(other.m_outer_it),
0099           m_outer_end(other.m_outer_end),
0100           m_inner_it(other.m_inner_it)
0101     {}
0102 
0103     flatten_iterator(flatten_iterator const& other) = default;
0104 
0105     flatten_iterator& operator=(flatten_iterator const& other)
0106     {
0107         m_outer_it = other.m_outer_it;
0108         m_outer_end = other.m_outer_end;
0109         // avoid assigning an iterator having singular value
0110         if ( other.m_outer_it != other.m_outer_end )
0111         {
0112             m_inner_it = other.m_inner_it;
0113         }
0114         return *this;
0115     }
0116 
0117 private:
0118     friend class boost::iterator_core_access;
0119 
0120     template
0121     <
0122         typename Outer,
0123         typename Inner,
0124         typename V,
0125         typename InnerBegin,
0126         typename InnerEnd,
0127         typename R
0128     >
0129     friend class flatten_iterator;
0130 
0131     static inline bool empty(OuterIterator outer_it)
0132     {
0133         return AccessInnerBegin::apply(*outer_it)
0134             == AccessInnerEnd::apply(*outer_it);
0135     }
0136 
0137     inline void advance_through_empty()
0138     {
0139         while ( m_outer_it != m_outer_end && empty(m_outer_it) )
0140         {
0141             ++m_outer_it;
0142         }
0143 
0144         if ( m_outer_it != m_outer_end )
0145         {
0146             m_inner_it = AccessInnerBegin::apply(*m_outer_it);
0147         }
0148     }
0149 
0150     inline Reference dereference() const
0151     {
0152         BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
0153         BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
0154         return *m_inner_it;
0155     }
0156 
0157 
0158     template
0159     <
0160         typename OtherOuterIterator,
0161         typename OtherInnerIterator,
0162         typename OtherValue,
0163         typename OtherAccessInnerBegin,
0164         typename OtherAccessInnerEnd,
0165         typename OtherReference
0166     >
0167     inline bool equal(flatten_iterator
0168                       <
0169                           OtherOuterIterator,
0170                           OtherInnerIterator,
0171                           OtherValue,
0172                           OtherAccessInnerBegin,
0173                           OtherAccessInnerEnd,
0174                           OtherReference
0175                       > const& other) const
0176     {
0177         if ( m_outer_it != other.m_outer_it )
0178         {
0179             return false;
0180         }
0181 
0182         if ( m_outer_it == m_outer_end )
0183         {
0184             return true;
0185         }
0186 
0187         return m_inner_it == other.m_inner_it;
0188     }
0189 
0190     inline void increment()
0191     {
0192         BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
0193         BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
0194 
0195         ++m_inner_it;
0196         if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) )
0197         {
0198             ++m_outer_it;
0199             advance_through_empty();
0200         }
0201     }
0202 
0203     inline void decrement()
0204     {
0205         if ( m_outer_it == m_outer_end
0206              || m_inner_it == AccessInnerBegin::apply(*m_outer_it) )
0207         {
0208             do
0209             {
0210                 --m_outer_it;
0211             }
0212             while ( empty(m_outer_it) );
0213             m_inner_it = AccessInnerEnd::apply(*m_outer_it);
0214         }
0215         --m_inner_it;
0216     }
0217 };
0218 
0219 
0220 
0221 }} // namespace boost::geometry
0222 
0223 
0224 #endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP