00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef VOLUMILL_CIRCULATOR_H
00023 #define VOLUMILL_CIRCULATOR_H
00024
00025 #pragma once
00026
00027 #include <boost/iterator/iterator_facade.hpp>
00028 #include <boost/type_traits.hpp>
00029
00030 namespace util
00031 {
00032
00041 template<class Iterator>
00042 class Circulator : public boost::iterator_facade<
00043 Circulator<Iterator>,
00044 typename std::iterator_traits<Iterator>::value_type,
00045 boost::bidirectional_traversal_tag,
00046 typename std::iterator_traits<Iterator>::reference
00047 >
00048 {
00049 public:
00050 Circulator() {}
00051 explicit Circulator(Iterator begin, Iterator end, Iterator pos)
00052 : m_begin (begin), m_end (end), m_pos (pos) {}
00053
00054 Iterator getIterator() const { return m_pos; }
00055
00056
00057 bool isValid() const { return m_begin != m_end; }
00058 private:
00059 friend class boost::iterator_core_access;
00060
00061 bool equal(Circulator<Iterator> const& other) const
00062 {
00063 return this->m_pos == other.m_pos;
00064 }
00065 void increment()
00066 {
00067 ++m_pos;
00068 if (m_pos == m_end)
00069 m_pos = m_begin;
00070 }
00071 void decrement()
00072 {
00073 if (m_pos == m_begin)
00074 m_pos = m_end;
00075 --m_pos;
00076 }
00077 typename std::iterator_traits<Iterator>::reference dereference() const
00078 {
00079 return *m_pos;
00080 }
00081 Iterator m_begin, m_end, m_pos;
00082 };
00083
00084 template<class Iterator>
00085 inline Circulator<Iterator> makeCirculator (Iterator begin, Iterator end, Iterator pos)
00086 {
00087 return Circulator<Iterator> (begin, end, pos);
00088 }
00089
00092 template<class Circulator>
00093 class CirculatorToIterator : public boost::iterator_facade<
00094 CirculatorToIterator<Circulator>,
00095 typename std::iterator_traits<Circulator>::value_type,
00096 boost::bidirectional_traversal_tag,
00097 typename std::iterator_traits<Circulator>::reference
00098 >
00099 {
00100 public:
00101 CirculatorToIterator() {}
00102 explicit CirculatorToIterator(Circulator c, int winding = 0)
00103 : m_circ (c), m_start (c), m_winding (winding) {}
00104
00105 Circulator getCirculator() const { return m_circ; }
00106 private:
00107 friend class boost::iterator_core_access;
00108 bool equal(CirculatorToIterator<Circulator> const& other) const
00109 {
00110 return this->m_circ == other.m_circ && this->m_winding == other.m_winding;
00111 }
00112 void increment()
00113 {
00114 ++m_circ;
00115 if (m_circ == m_start)
00116 ++m_winding;
00117 }
00118 void decrement()
00119 {
00120 if (m_circ == m_start)
00121 --m_winding;
00122 --m_circ;
00123 }
00124 typename std::iterator_traits<Circulator>::reference dereference() const
00125 {
00126 return *m_circ;
00127 }
00128 Circulator m_circ, m_start;
00129 int m_winding;
00130 };
00131
00132 template<class Circulator>
00133 inline CirculatorToIterator<Circulator> makeBeginIteratorFromCirculator (Circulator circ)
00134 {
00135 return CirculatorToIterator<Circulator> (circ);
00136 }
00137
00138 template<class Circulator>
00139 inline CirculatorToIterator<Circulator> makeEndIteratorFromCirculator (Circulator circ)
00140 {
00141 return CirculatorToIterator<Circulator> (circ, circ.isValid() ? 1 : 0);
00142 }
00143
00144 }
00145 #endif