Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cyclic_value.h Source File

cyclic_value.h

Go to the documentation of this file.
00001 ///\file
00002 
00003 /******************************************************************************
00004 The MIT License(MIT)
00005 
00006 Embedded Template Library.
00007 https://github.com/ETLCPP/etl
00008 http://www.etlcpp.com
00009 
00010 Copyright(c) 2014 jwellbelove
00011 
00012 Permission is hereby granted, free of charge, to any person obtaining a copy
00013 of this software and associated documentation files(the "Software"), to deal
00014 in the Software without restriction, including without limitation the rights
00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
00016 copies of the Software, and to permit persons to whom the Software is
00017 furnished to do so, subject to the following conditions :
00018 
00019 The above copyright notice and this permission notice shall be included in all
00020 copies or substantial portions of the Software.
00021 
00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00028 SOFTWARE.
00029 ******************************************************************************/
00030 
00031 #ifndef __ETL_CYCLIC_VALUE__
00032 #define __ETL_CYCLIC_VALUE__
00033 
00034 #include <stddef.h>
00035 
00036 ///\defgroup cyclic_value cyclic_value
00037 /// Provides a value that cycles between two limits.
00038 /// \ingroup utilities
00039 
00040 #include <algorithm>
00041 
00042 #include "platform.h "
00043 #include "static_assert.h"
00044 #include "exception.h "
00045 #include "static_assert.h"
00046 #include "type_traits.h "
00047 
00048 namespace etl
00049 {
00050   //***************************************************************************
00051   /// Provides a value that cycles between two limits.
00052   /// Supports incrementing and decrementing.
00053   ///\tparam T     The type of the variable.
00054   ///\tparam FIRST The first value of the range.
00055   ///\tparam LAST  The last value of the range.
00056   ///\ingroup cyclic_value
00057   //***************************************************************************
00058   template <typename T, T FIRST = 0, T LAST = 0, typename = void>
00059   class cyclic_value
00060   {
00061   public:
00062 
00063     //*************************************************************************
00064     /// Constructor.
00065     /// The initial value is set to the first value.
00066     //*************************************************************************
00067     cyclic_value()
00068       : value(FIRST)
00069     {
00070     }
00071 
00072     //*************************************************************************
00073     /// Copy constructor.
00074     //*************************************************************************
00075     cyclic_value(const cyclic_value<T, FIRST, LAST>& other)
00076       : value(other.value)
00077     {
00078     }
00079 
00080     //*************************************************************************
00081     /// Sets the value.
00082     ///\param value The value.
00083     //*************************************************************************
00084     void set(T value_)
00085     {
00086       if (value_ > LAST)
00087       {
00088         value_ = LAST;
00089       }
00090       else if (value_ < FIRST)
00091       {
00092         value_ = FIRST;
00093       }
00094 
00095       value = value_;
00096     }
00097 
00098     //*************************************************************************
00099     /// Resets the value to the first in the range.
00100     //*************************************************************************
00101     void to_first()
00102     {
00103       value = FIRST;
00104     }
00105 
00106     //*************************************************************************
00107     /// Resets the value to the last in the range.
00108     //*************************************************************************
00109     void to_last()
00110     {
00111       value = LAST;
00112     }
00113 
00114     //*************************************************************************
00115     /// Advances to value by a number of steps.
00116     ///\param n The number of steps to advance.
00117     //*************************************************************************
00118     void advance(int n)
00119     {
00120       T range = LAST - FIRST + T(1);
00121 
00122       n = n % range;
00123 
00124       if (n > 0)
00125       {
00126         for (int i = 0; i < n; ++i)
00127         {
00128           operator ++();
00129         }
00130       }
00131       else
00132       {
00133         for (int i = 0; i < -n; ++i)
00134         {
00135           operator --();
00136         }
00137       }
00138     }
00139 
00140     //*************************************************************************
00141     /// Conversion operator.
00142     /// \return The value of the underlying type.
00143     //*************************************************************************
00144     operator T()
00145     {
00146       return value;
00147     }
00148 
00149     //*************************************************************************
00150     /// Const conversion operator.
00151     /// \return The value of the underlying type.
00152     //*************************************************************************
00153     operator const T() const
00154     {
00155       return value;
00156     }
00157 
00158     //*************************************************************************
00159     /// ++ operator.
00160     //*************************************************************************
00161     cyclic_value& operator ++()
00162     {
00163       if (value >= LAST)
00164       {
00165         value = FIRST;
00166       }
00167       else
00168       {
00169         ++value;
00170       }
00171 
00172       return *this;
00173     }
00174 
00175     //*************************************************************************
00176     /// ++ operator.
00177     //*************************************************************************
00178     cyclic_value operator ++(int)
00179     {
00180       cyclic_value temp(*this);
00181 
00182       operator++();
00183 
00184       return temp;
00185     }
00186 
00187     //*************************************************************************
00188     /// -- operator.
00189     //*************************************************************************
00190     cyclic_value& operator --()
00191     {
00192       if (value <= FIRST)
00193       {
00194         value = LAST;
00195       }
00196       else
00197       {
00198         --value;
00199       }
00200 
00201       return *this;
00202     }
00203 
00204     //*************************************************************************
00205     /// -- operator.
00206     //*************************************************************************
00207     cyclic_value operator --(int)
00208     {
00209       cyclic_value temp(*this);
00210 
00211       operator--();
00212 
00213       return temp;
00214     }
00215 
00216     //*************************************************************************
00217     /// = operator.
00218     //*************************************************************************
00219     cyclic_value& operator =(T t)
00220     {
00221       set(t);
00222       return *this;
00223     }
00224 
00225     //*************************************************************************
00226     /// = operator.
00227     //*************************************************************************
00228     template <const T FIRST2, const T LAST2>
00229     cyclic_value& operator =(const cyclic_value<T, FIRST2, LAST2>& other)
00230     {
00231       set(other.get());
00232       return *this;
00233     }
00234 
00235     //*************************************************************************
00236     /// Gets the value.
00237     //*************************************************************************
00238     T get() const
00239     {
00240       return value;
00241     }
00242 
00243     //*************************************************************************
00244     /// Gets the first value.
00245     //*************************************************************************
00246     const T first() const
00247     {
00248       return FIRST;
00249     }
00250 
00251     //*************************************************************************
00252     /// Gets the last value.
00253     //*************************************************************************
00254     const T last() const
00255     {
00256       return LAST;
00257     }
00258 
00259     //*************************************************************************
00260     /// Swaps the values.
00261     //*************************************************************************
00262     void swap(cyclic_value<T, FIRST, LAST>& other)
00263     {
00264       std::swap(value, other.value);
00265     }
00266 
00267     //*************************************************************************
00268     /// Swaps the values.
00269     //*************************************************************************
00270     friend void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs)
00271     {
00272       lhs.swap(rhs);
00273     }
00274 
00275     //*************************************************************************
00276     /// Operator ==.
00277     //*************************************************************************
00278     friend bool operator == (const cyclic_value<T, FIRST, LAST>& lhs, const cyclic_value<T, FIRST, LAST>& rhs)
00279     {
00280       return lhs.value == rhs.value;
00281     }
00282 
00283     //*************************************************************************
00284     /// Operator !=.
00285     //*************************************************************************
00286     friend bool operator != (const cyclic_value<T, FIRST, LAST>& lhs, const cyclic_value<T, FIRST, LAST>& rhs)
00287     {
00288       return !(lhs == rhs);
00289     }
00290 
00291   private:
00292 
00293     T value; ///< The current value.
00294   };
00295 
00296   //***************************************************************************
00297   /// Provides a value that cycles between two limits.
00298   /// Supports incrementing and decrementing.
00299   ///\tparam T     The type of the variable.
00300   ///\tparam FIRST The first value of the range.
00301   ///\tparam LAST  The last value of the range.
00302   ///\ingroup cyclic_value
00303   //***************************************************************************
00304   template <typename T, const T FIRST, const T LAST>
00305   class cyclic_value<T, FIRST, LAST, typename etl::enable_if<(FIRST == 0) && (LAST == 0)>::type>
00306   {
00307   public:
00308 
00309     //*************************************************************************
00310     /// Constructor.
00311     /// Sets 'first' and 'last' to the template parameter values.
00312     /// The initial value is set to the first value.
00313     //*************************************************************************
00314     cyclic_value()
00315       : value(FIRST),
00316         first_value(FIRST),
00317         last_value(LAST)
00318     {
00319     }
00320 
00321     //*************************************************************************
00322     /// Constructor.
00323     /// Sets the value to the first of the range.
00324     ///\param first The first value in the range.
00325     ///\param last  The last value in the range.
00326     //*************************************************************************
00327     cyclic_value(T first_, T last_)
00328       : value(first_),
00329         first_value(first_),
00330         last_value(last_)
00331     {
00332     }
00333 
00334     //*************************************************************************
00335     /// Copy constructor.
00336     //*************************************************************************
00337     cyclic_value(const cyclic_value& other)
00338       : value(other.value),
00339         first_value(other.first_value),
00340         last_value(other.last_value)
00341     {
00342     }
00343 
00344     //*************************************************************************
00345     /// Sets the range.
00346     /// Sets the value to the first of the range.
00347     ///\param first The first value in the range.
00348     ///\param last  The last value in the range.
00349     //*************************************************************************
00350     void set(T first_, T last_)
00351     {
00352       first_value = first_;
00353       last_value  = last_;
00354       value       = first_;
00355     }
00356 
00357     //*************************************************************************
00358     /// Sets the value.
00359     ///\param value The value.
00360     //*************************************************************************
00361     void set(T value_)
00362     {
00363       if (value_ > last_value)
00364       {
00365         value_ = last_value;
00366       }
00367       else if (value_ < first_value)
00368       {
00369         value_ = first_value;
00370       }
00371 
00372       value = value_;
00373     }
00374 
00375     //*************************************************************************
00376     /// Resets the value to the first in the range.
00377     //*************************************************************************
00378     void to_first()
00379     {
00380       value = first_value;
00381     }
00382 
00383     //*************************************************************************
00384     /// Resets the value to the last in the range.
00385     //*************************************************************************
00386     void to_last()
00387     {
00388       value = last_value;
00389     }
00390 
00391     //*************************************************************************
00392     /// Advances to value by a number of steps.
00393     ///\param n The number of steps to advance.
00394     //*************************************************************************
00395     void advance(int n)
00396     {
00397       T range = last_value - first_value + T(1);
00398 
00399       n = n % range;
00400 
00401       if (n > 0)
00402       {
00403         for (int i = 0; i < n; ++i)
00404         {
00405           operator ++();
00406         }
00407       }
00408       else
00409       {
00410         for (int i = 0; i < -n; ++i)
00411         {
00412           operator --();
00413         }
00414       }
00415     }
00416 
00417     //*************************************************************************
00418     /// Conversion operator.
00419     /// \return The value of the underlying type.
00420     //*************************************************************************
00421     operator T()
00422     {
00423       return value;
00424     }
00425 
00426     //*************************************************************************
00427     /// Const conversion operator.
00428     /// \return The value of the underlying type.
00429     //*************************************************************************
00430     operator const T() const
00431     {
00432       return value;
00433     }
00434 
00435     //*************************************************************************
00436     /// ++ operator.
00437     //*************************************************************************
00438     cyclic_value& operator ++()
00439     {
00440       if (value >= last_value)
00441       {
00442         value = first_value;
00443       }
00444       else
00445       {
00446         ++value;
00447       }
00448 
00449       return *this;
00450     }
00451 
00452     //*************************************************************************
00453     /// ++ operator.
00454     //*************************************************************************
00455     cyclic_value operator ++(int)
00456     {
00457       cyclic_value temp(*this);
00458 
00459       operator++();
00460 
00461       return temp;
00462     }
00463 
00464     //*************************************************************************
00465     /// -- operator.
00466     //*************************************************************************
00467     cyclic_value& operator --()
00468     {
00469       if (value <= first_value)
00470       {
00471         value = last_value;
00472       }
00473       else
00474       {
00475         --value;
00476       }
00477 
00478       return *this;
00479     }
00480 
00481     //*************************************************************************
00482     /// -- operator.
00483     //*************************************************************************
00484     cyclic_value operator --(int)
00485     {
00486       cyclic_value temp(*this);
00487 
00488       operator--();
00489 
00490       return temp;
00491     }
00492 
00493     //*************************************************************************
00494     /// = operator.
00495     //*************************************************************************
00496     cyclic_value& operator =(T t)
00497     {
00498       set(t);
00499       return *this;
00500     }
00501 
00502     //*************************************************************************
00503     /// = operator.
00504     //*************************************************************************
00505     cyclic_value& operator =(const cyclic_value& other)
00506     {
00507       value       = other.value;
00508       first_value = other.first_value;
00509       last_value  = other.last_value;
00510       return *this;
00511     }
00512 
00513     //*************************************************************************
00514     /// Gets the value.
00515     //*************************************************************************
00516     T get() const
00517     {
00518       return value;
00519     }
00520 
00521     //*************************************************************************
00522     /// Gets the first value.
00523     //*************************************************************************
00524     T first() const
00525     {
00526       return first_value;
00527     }
00528 
00529     //*************************************************************************
00530     /// Gets the last value.
00531     //*************************************************************************
00532     T last() const
00533     {
00534       return last_value;
00535     }
00536 
00537     //*************************************************************************
00538     /// Swaps the values.
00539     //*************************************************************************
00540     void swap(cyclic_value<T, FIRST, LAST>& other)
00541     {
00542       std::swap(first_value, other.first_value);
00543       std::swap(last_value, other.last_value);
00544       std::swap(value, other.value);
00545     }
00546 
00547     //*************************************************************************
00548     /// Swaps the values.
00549     //*************************************************************************
00550     friend void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs)
00551     {
00552       lhs.swap(rhs);
00553     }
00554 
00555     //*************************************************************************
00556     /// Operator ==.
00557     //*************************************************************************
00558     friend bool operator == (const cyclic_value<T, FIRST, LAST>& lhs, const cyclic_value<T, FIRST, LAST>& rhs)
00559     {
00560       return (lhs.value       == rhs.value) &&
00561              (lhs.first_value == rhs.first_value) &&
00562              (lhs.last_value  == rhs.last_value);
00563     }
00564 
00565     //*************************************************************************
00566     /// Operator !=.
00567     //*************************************************************************
00568     friend bool operator != (const cyclic_value<T, FIRST, LAST>& lhs, const cyclic_value<T, FIRST, LAST>& rhs)
00569     {
00570       return !(lhs == rhs);
00571     }
00572 
00573   private:
00574 
00575     T value;       ///< The current value.
00576     T first_value; ///< The first value in the range.
00577     T last_value;  ///< The last value in the range.
00578   };
00579 }
00580 
00581 #endif
00582