00001 #ifndef CLASSLIB_SEQUENCE_H
00002 # define CLASSLIB_SEQUENCE_H
00003
00004
00005
00006 # include "classlib/utils/Range.h"
00007 # include "classlib/utils/IntTraits.h"
00008 # include "classlib/utils/DebugAids.h"
00009 # include "classlib/utils/Log.h"
00010 # include <stdexcept>
00011 # include <typeinfo>
00012
00013 namespace lat {
00014
00015
00016
00017
00018 template <class T> class Sequence;
00019
00020
00021
00022
00023 template <class T>
00024 logstream &operator<< (logstream &log, const Sequence<T> &s);
00025
00026
00027
00034 template <class T>
00035 class Sequence
00036 {
00037 public:
00038 Sequence (bool wraps = false);
00039 Sequence (T low, T high, bool wraps = false);
00040 Sequence (const Range<T> &limits, bool wraps = false);
00041
00042
00043
00044
00045 Range<T> limits (void) const;
00046 void limits (const Range<T> &value);
00047
00048 bool wraps (void) const;
00049 void wraps (bool value);
00050 bool wrapped (void);
00051
00052 T next (void);
00053 T current (void) const;
00054 void reset (void);
00055
00056 friend logstream & operator<< <> (logstream &log, const Sequence &s);
00057
00058 private:
00059 Range<T> m_limits;
00060 T m_current;
00061 bool m_wraps;
00062 bool m_wrapped;
00063
00064
00065 };
00066
00067
00068
00069 template <class T>
00070 inline logstream &
00071 operator<< (logstream &log, const Sequence<T> &s)
00072 {
00073 #ifndef NLOG
00074 ASSERT (s.m_limits.low () < s.m_limits.high ());
00075 ASSERT (s.m_current >= s.m_limits.low ());
00076 ASSERT (s.m_current <= s.m_limits.high ());
00077
00078 return log
00079 << "Sequence<" << typeid(T).name () << "> @ " << &s << " {\n" << indent
00080 << "limits [" << s.m_limits.low ()
00081 << ", " << s.m_limits.high () << "]\n"
00082 << "current " << s.m_current << endl
00083 << "wraps " << s.m_wraps << endl
00084 << "wrapped " << s.m_wrapped << endl
00085 << undent << "}";
00086 #endif // !NLOG
00087 }
00088
00089
00090
00103 template <class T>
00104 inline
00105 Sequence<T>::Sequence (bool wraps )
00106 : m_limits (IntTraits<T>::Min, IntTraits<T>::Max),
00107 m_current (IntTraits<T>::Min),
00108 m_wraps (wraps),
00109 m_wrapped (false)
00110 {
00111 ASSERT (m_limits.low () < m_limits.high ());
00112 ASSERT (m_current >= m_limits.low ());
00113 ASSERT (m_current <= m_limits.high ());
00114 }
00115
00117 template <class T>
00118 inline
00119 Sequence<T>::Sequence (T low, T high, bool wraps )
00120 : m_limits (low, high),
00121 m_current (low),
00122 m_wraps (wraps),
00123 m_wrapped (false)
00124 {
00125 ASSERT (m_limits.low () < m_limits.high ());
00126 ASSERT (m_current >= m_limits.low ());
00127 ASSERT (m_current <= m_limits.high ());
00128 }
00129
00131 template <class T>
00132 inline
00133 Sequence<T>::Sequence (const Range<T> &limits, bool wraps )
00134 : m_limits (limits),
00135 m_current (limits.low ()),
00136 m_wraps (wraps),
00137 m_wrapped (false)
00138 {
00139 ASSERT (m_limits.low () < m_limits.high ());
00140 ASSERT (m_current >= m_limits.low ());
00141 ASSERT (m_current <= m_limits.high ());
00142 }
00143
00145 template <class T>
00146 inline Range<T>
00147 Sequence<T>::limits (void) const
00148 { return m_limits; }
00149
00155 template <class T>
00156 inline void
00157 Sequence<T>::limits (const Range<T> &value)
00158 {
00159 ASSERT (m_limits.low () < m_limits.high ());
00160 ASSERT (m_current >= m_limits.low ());
00161 ASSERT (m_current <= m_limits.high ());
00162 ASSERT (value.low () < value.high ());
00163
00164 m_limits = limits;
00165 if (m_current < m_limits.low ())
00166 {
00167 m_wrapped = true;
00168 m_current = m_limits.low ();
00169 }
00170 else if (m_current > m_limits.high ())
00171 {
00172 m_wrapped = true;
00173 m_current = m_limits.high ();
00174 }
00175 }
00176
00179 template <class T>
00180 inline bool
00181 Sequence<T>::wraps (void) const
00182 { return m_wraps; }
00183
00186 template <class T>
00187 inline void Sequence<T>::wraps (bool value)
00188 { m_wraps = value; }
00189
00192 template <class T>
00193 inline bool
00194 Sequence<T>::wrapped (void)
00195 { bool wrapped = m_wrapped; m_wrapped = false; return wrapped; }
00196
00205 template <class T>
00206 inline T
00207 Sequence<T>::next (void)
00208 {
00209 ASSERT (m_limits.low () < m_limits.high ());
00210 ASSERT (m_current >= m_limits.low ());
00211 ASSERT (m_current <= m_limits.high ());
00212
00213 if (m_current == m_limits.high ())
00214 if (m_wraps)
00215 {
00216 m_wrapped = true;
00217 m_current = m_limits.low ();
00218 }
00219 else
00220 throw std::range_error ("Sequence upper limit reached");
00221 else
00222 ++m_current;
00223
00224 ASSERT (m_current >= m_limits.low ());
00225 ASSERT (m_current <= m_limits.high ());
00226 return m_current;
00227 }
00228
00230 template <class T>
00231 inline T
00232 Sequence<T>::current (void) const
00233 {
00234 ASSERT (m_limits.low () < m_limits.high ());
00235 ASSERT (m_current >= m_limits.low ());
00236 ASSERT (m_current <= m_limits.high ());
00237 return m_current;
00238 }
00239
00242 template <class T>
00243 inline void
00244 Sequence<T>::reset (void)
00245 {
00246 ASSERT (m_limits.low () < m_limits.high ());
00247 ASSERT (m_current >= m_limits.low ());
00248 ASSERT (m_current <= m_limits.high ());
00249
00250 m_current = m_limits.low ();
00251 m_wrapped = false;
00252
00253 ASSERT (m_limits.low () < m_limits.high ());
00254 ASSERT (m_current >= m_limits.low ());
00255 ASSERT (m_current <= m_limits.high ());
00256 }
00257
00258 }
00259 #endif // CLASSLIB_SEQUENCE_H