closing_iterator.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  6. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP
  11. #define BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP
  12. #include <boost/range.hpp>
  13. #include <boost/iterator.hpp>
  14. #include <boost/iterator/iterator_facade.hpp>
  15. #include <boost/iterator/iterator_categories.hpp>
  16. namespace boost { namespace geometry
  17. {
  18. /*!
  19. \brief Iterator which iterates through a range, but adds first element at end of the range
  20. \tparam Range range on which this class is based on
  21. \ingroup iterators
  22. \note Use with "closing_iterator<Range> or "closing_iterator<Range const>
  23. to get non-const / const behaviour
  24. \note This class is normally used from "closeable_view" if Close==true
  25. */
  26. template <typename Range>
  27. struct closing_iterator
  28. : public boost::iterator_facade
  29. <
  30. closing_iterator<Range>,
  31. typename boost::range_value<Range>::type const,
  32. boost::random_access_traversal_tag
  33. >
  34. {
  35. /// Constructor including the range it is based on
  36. explicit inline closing_iterator(Range& range)
  37. : m_range(&range)
  38. , m_iterator(boost::begin(range))
  39. , m_end(boost::end(range))
  40. , m_size(boost::size(range))
  41. , m_index(0)
  42. {}
  43. /// Constructor to indicate the end of a range
  44. explicit inline closing_iterator(Range& range, bool)
  45. : m_range(&range)
  46. , m_iterator(boost::end(range))
  47. , m_end(boost::end(range))
  48. , m_size(boost::size(range))
  49. , m_index(m_size + 1)
  50. {}
  51. /// Default constructor
  52. explicit inline closing_iterator()
  53. : m_range(NULL)
  54. , m_size(0)
  55. , m_index(0)
  56. {}
  57. inline closing_iterator<Range>& operator=(closing_iterator<Range> const& source)
  58. {
  59. m_range = source.m_range;
  60. m_iterator = source.m_iterator;
  61. m_end = source.m_end;
  62. m_size = source.m_size;
  63. m_index = source.m_index;
  64. return *this;
  65. }
  66. typedef std::ptrdiff_t difference_type;
  67. private:
  68. friend class boost::iterator_core_access;
  69. inline typename boost::range_value<Range>::type const& dereference() const
  70. {
  71. return *m_iterator;
  72. }
  73. inline difference_type distance_to(closing_iterator<Range> const& other) const
  74. {
  75. return other.m_index - this->m_index;
  76. }
  77. inline bool equal(closing_iterator<Range> const& other) const
  78. {
  79. return this->m_range == other.m_range
  80. && this->m_index == other.m_index;
  81. }
  82. inline void increment()
  83. {
  84. if (++m_index < m_size)
  85. {
  86. ++m_iterator;
  87. }
  88. else
  89. {
  90. update_iterator();
  91. }
  92. }
  93. inline void decrement()
  94. {
  95. if (m_index-- < m_size)
  96. {
  97. --m_iterator;
  98. }
  99. else
  100. {
  101. update_iterator();
  102. }
  103. }
  104. inline void advance(difference_type n)
  105. {
  106. if (m_index < m_size && m_index + n < m_size)
  107. {
  108. m_index += n;
  109. m_iterator += n;
  110. }
  111. else
  112. {
  113. m_index += n;
  114. update_iterator();
  115. }
  116. }
  117. inline void update_iterator()
  118. {
  119. this->m_iterator = m_index <= m_size
  120. ? boost::begin(*m_range) + (m_index % m_size)
  121. : boost::end(*m_range)
  122. ;
  123. }
  124. Range* m_range;
  125. typename boost::range_iterator<Range>::type m_iterator;
  126. typename boost::range_iterator<Range>::type m_end;
  127. difference_type m_size;
  128. difference_type m_index;
  129. };
  130. }} // namespace boost::geometry
  131. #endif // BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP