blob: 501ff8ab43cb02666560d8c95a035029b20222cc [file] [log] [blame]
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2011 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 <boost/range.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
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<Range> or "closing_iterator<Range const>
to get non-const / const behaviour
\note This class is normally used from "closeable_view" if Close==true
*/
template <typename Range>
struct closing_iterator
: public boost::iterator_facade
<
closing_iterator<Range>,
typename boost::range_value<Range>::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<Range>& operator=(closing_iterator<Range> 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<Range>::type const& dereference() const
{
return *m_iterator;
}
inline difference_type distance_to(closing_iterator<Range> const& other) const
{
return other.m_index - this->m_index;
}
inline bool equal(closing_iterator<Range> 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<Range>::type m_iterator;
typename boost::range_iterator<Range>::type m_end;
difference_type m_size;
difference_type m_index;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP