// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP #define BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP #include #include #include #include namespace boost { namespace geometry { /*! \brief Iterator which iterates through a range, but adds first element at end of the range \tparam Range range on which this class is based on \ingroup iterators \note Use with "closing_iterator or "closing_iterator to get non-const / const behaviour \note This class is normally used from "closeable_view" if Close==true */ template struct closing_iterator : public boost::iterator_facade < closing_iterator, typename boost::range_value::type const, boost::random_access_traversal_tag > { /// Constructor including the range it is based on explicit inline closing_iterator(Range& range) : m_range(&range) , m_iterator(boost::begin(range)) , m_end(boost::end(range)) , m_size(boost::size(range)) , m_index(0) {} /// Constructor to indicate the end of a range explicit inline closing_iterator(Range& range, bool) : m_range(&range) , m_iterator(boost::end(range)) , m_end(boost::end(range)) , m_size(boost::size(range)) , m_index(m_size + 1) {} /// Default constructor explicit inline closing_iterator() : m_range(NULL) , m_size(0) , m_index(0) {} inline closing_iterator& operator=(closing_iterator const& source) { m_range = source.m_range; m_iterator = source.m_iterator; m_end = source.m_end; m_size = source.m_size; m_index = source.m_index; return *this; } typedef std::ptrdiff_t difference_type; private: friend class boost::iterator_core_access; inline typename boost::range_value::type const& dereference() const { return *m_iterator; } inline difference_type distance_to(closing_iterator const& other) const { return other.m_index - this->m_index; } inline bool equal(closing_iterator const& other) const { return this->m_range == other.m_range && this->m_index == other.m_index; } inline void increment() { if (++m_index < m_size) { ++m_iterator; } else { update_iterator(); } } inline void decrement() { if (m_index-- < m_size) { --m_iterator; } else { update_iterator(); } } inline void advance(difference_type n) { if (m_index < m_size && m_index + n < m_size) { m_index += n; m_iterator += n; } else { m_index += n; update_iterator(); } } inline void update_iterator() { this->m_iterator = m_index <= m_size ? boost::begin(*m_range) + (m_index % m_size) : boost::end(*m_range) ; } Range* m_range; typename boost::range_iterator::type m_iterator; typename boost::range_iterator::type m_end; difference_type m_size; difference_type m_index; }; }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP