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) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
0005 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
0006 
0007 // This file was modified by Oracle on 2020-2021.
0008 // Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
0009 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0010 
0011 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
0012 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
0013 
0014 // Use, modification and distribution is subject to the Boost Software License,
0015 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0016 // http://www.boost.org/LICENSE_1_0.txt)
0017 
0018 #ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
0019 #define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
0020 
0021 
0022 #include <type_traits>
0023 
0024 #include <boost/iterator/iterator_adaptor.hpp>
0025 #include <boost/iterator/iterator_categories.hpp>
0026 #include <boost/range/begin.hpp>
0027 #include <boost/range/difference_type.hpp>
0028 #include <boost/range/reference.hpp>
0029 #include <boost/range/size.hpp>
0030 #include <boost/range/value_type.hpp>
0031 
0032 #include <boost/geometry/core/assert.hpp>
0033 
0034 #include <boost/geometry/iterators/detail/iterator_base.hpp>
0035 
0036 
0037 namespace boost { namespace geometry
0038 {
0039 
0040 /*!
0041     \brief Iterator which ever circles through a range
0042     \tparam Iterator iterator on which this class is based on
0043     \ingroup iterators
0044     \details If the iterator arrives at range.end() it restarts from the
0045      beginning. So it has to be stopped in another way.
0046     Don't call for(....; it++) because it will turn in an endless loop
0047     \note Name inspired on David Bowie's
0048     "Chant Of The Ever Circling Skeletal Family"
0049 */
0050 template <typename Iterator>
0051 struct ever_circling_iterator :
0052     public detail::iterators::iterator_base
0053     <
0054         ever_circling_iterator<Iterator>,
0055         Iterator
0056     >
0057 {
0058     ever_circling_iterator() = default;
0059 
0060     explicit inline ever_circling_iterator(Iterator begin, Iterator end,
0061             bool skip_first = false)
0062       : m_begin(begin)
0063       , m_end(end)
0064       , m_skip_first(skip_first)
0065     {
0066         this->base_reference() = begin;
0067     }
0068 
0069     explicit inline ever_circling_iterator(Iterator begin, Iterator end, Iterator start,
0070             bool skip_first = false)
0071       : m_begin(begin)
0072       , m_end(end)
0073       , m_skip_first(skip_first)
0074     {
0075         this->base_reference() = start;
0076     }
0077 
0078     template
0079     <
0080         typename OtherIterator,
0081         std::enable_if_t<std::is_convertible<OtherIterator, Iterator>::value, int> = 0
0082     >
0083     inline ever_circling_iterator(ever_circling_iterator<OtherIterator> const& other)
0084         : m_begin(other.m_begin)
0085         , m_end(other.m_end)
0086         , m_skip_first(other.m_skip_first)
0087     {}
0088 
0089     /// Navigate to a certain position, should be in [start .. end], if at end
0090     /// it will circle again.
0091     inline void moveto(Iterator it)
0092     {
0093         this->base_reference() = it;
0094         check_end();
0095     }
0096 
0097 private:
0098     template <typename OtherIterator> friend struct ever_circling_iterator;
0099     friend class boost::iterator_core_access;
0100 
0101     inline void increment(bool possibly_skip = true)
0102     {
0103         (this->base_reference())++;
0104         check_end(possibly_skip);
0105     }
0106 
0107     inline void check_end(bool possibly_skip = true)
0108     {
0109         if (this->base() == this->m_end)
0110         {
0111             this->base_reference() = this->m_begin;
0112             if (m_skip_first && possibly_skip)
0113             {
0114                 increment(false);
0115             }
0116         }
0117     }
0118 
0119     Iterator m_begin;
0120     Iterator m_end;
0121     bool m_skip_first;
0122 };
0123 
0124 template <typename Range>
0125 struct ever_circling_range_iterator
0126     : public boost::iterator_facade
0127     <
0128         ever_circling_range_iterator<Range>,
0129         typename boost::range_value<Range>::type const,
0130         boost::random_access_traversal_tag,
0131         typename boost::range_reference<Range const>::type,
0132         typename boost::range_difference<Range>::type
0133     >
0134 {
0135 private:
0136     typedef boost::iterator_facade
0137         <
0138             ever_circling_range_iterator<Range>,
0139             typename boost::range_value<Range>::type const,
0140             boost::random_access_traversal_tag,
0141             typename boost::range_reference<Range const>::type,
0142             typename boost::range_difference<Range>::type
0143         > base_type;
0144 
0145 public:
0146     /// Constructor including the range it is based on
0147     explicit inline ever_circling_range_iterator(Range const& range)
0148         : m_begin(boost::begin(range))
0149         , m_iterator(boost::begin(range))
0150         , m_size(boost::size(range))
0151         , m_index(0)
0152     {}
0153 
0154     /// Default constructor
0155     explicit inline ever_circling_range_iterator()
0156         : m_size(0)
0157         , m_index(0)
0158     {}
0159 
0160     template
0161     <
0162         typename OtherRange,
0163         std::enable_if_t
0164             <
0165                 std::is_convertible
0166                     <
0167                         typename boost::range_iterator<OtherRange const>::type,
0168                         typename boost::range_iterator<Range const>::type
0169                     >::value,
0170                 int
0171             > = 0
0172     >
0173     inline ever_circling_range_iterator(ever_circling_range_iterator<OtherRange> const& other)
0174         : m_begin(other.m_begin)
0175         , m_iterator(other.m_iterator)
0176         , m_size(other.m_size)
0177         , m_index(other.m_index)
0178     {}
0179 
0180     typedef typename base_type::reference reference;
0181     typedef typename base_type::difference_type difference_type;
0182 
0183 private:
0184     template <typename OtherRange> friend struct ever_circling_range_iterator;
0185     friend class boost::iterator_core_access;
0186 
0187     inline reference dereference() const
0188     {
0189         return *m_iterator;
0190     }
0191 
0192     inline difference_type distance_to(ever_circling_range_iterator<Range> const& other) const
0193     {
0194         return other.m_index - this->m_index;
0195     }
0196 
0197     inline bool equal(ever_circling_range_iterator<Range> const& other) const
0198     {
0199         BOOST_GEOMETRY_ASSERT(m_begin == other.m_begin);
0200         return this->m_index == other.m_index;
0201     }
0202 
0203     inline void increment()
0204     {
0205         ++m_index;
0206         if (m_index >= 0 && m_index < m_size)
0207         {
0208             ++m_iterator;
0209         }
0210         else
0211         {
0212             update_iterator();
0213         }
0214     }
0215 
0216     inline void decrement()
0217     {
0218         --m_index;
0219         if (m_index >= 0 && m_index < m_size)
0220         {
0221             --m_iterator;
0222         }
0223         else
0224         {
0225             update_iterator();
0226         }
0227     }
0228 
0229     inline void advance(difference_type n)
0230     {
0231         if (m_index >= 0 && m_index < m_size
0232             && m_index + n >= 0 && m_index + n < m_size)
0233         {
0234             m_index += n;
0235             m_iterator += n;
0236         }
0237         else
0238         {
0239             m_index += n;
0240             update_iterator();
0241         }
0242     }
0243 
0244     inline void update_iterator()
0245     {
0246         while (m_index < 0)
0247         {
0248             m_index += m_size;
0249         }
0250         m_index = m_index % m_size;
0251         this->m_iterator = m_begin + m_index;
0252     }
0253 
0254     typename boost::range_iterator<Range const>::type m_begin;
0255     typename boost::range_iterator<Range const>::type m_iterator;
0256     difference_type m_size;
0257     difference_type m_index;
0258 };
0259 
0260 
0261 }} // namespace boost::geometry
0262 
0263 #endif // BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP