Containers (STL-compatible) StateMachines MessageBus and more for Embedded Systems. See www.etlcpp.com
Diff: cyclic_value.h
- Revision:
- 0:b47c2a7920c2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cyclic_value.h Fri Mar 16 16:34:18 2018 +0000 @@ -0,0 +1,582 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +http://www.etlcpp.com + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ETL_CYCLIC_VALUE__ +#define __ETL_CYCLIC_VALUE__ + +#include <stddef.h> + +///\defgroup cyclic_value cyclic_value +/// Provides a value that cycles between two limits. +/// \ingroup utilities + +#include <algorithm> + +#include "platform.h" +#include "static_assert.h" +#include "exception.h" +#include "static_assert.h" +#include "type_traits.h" + +namespace etl +{ + //*************************************************************************** + /// Provides a value that cycles between two limits. + /// Supports incrementing and decrementing. + ///\tparam T The type of the variable. + ///\tparam FIRST The first value of the range. + ///\tparam LAST The last value of the range. + ///\ingroup cyclic_value + //*************************************************************************** + template <typename T, T FIRST = 0, T LAST = 0, typename = void> + class cyclic_value + { + public: + + //************************************************************************* + /// Constructor. + /// The initial value is set to the first value. + //************************************************************************* + cyclic_value() + : value(FIRST) + { + } + + //************************************************************************* + /// Copy constructor. + //************************************************************************* + cyclic_value(const cyclic_value<T, FIRST, LAST>& other) + : value(other.value) + { + } + + //************************************************************************* + /// Sets the value. + ///\param value The value. + //************************************************************************* + void set(T value_) + { + if (value_ > LAST) + { + value_ = LAST; + } + else if (value_ < FIRST) + { + value_ = FIRST; + } + + value = value_; + } + + //************************************************************************* + /// Resets the value to the first in the range. + //************************************************************************* + void to_first() + { + value = FIRST; + } + + //************************************************************************* + /// Resets the value to the last in the range. + //************************************************************************* + void to_last() + { + value = LAST; + } + + //************************************************************************* + /// Advances to value by a number of steps. + ///\param n The number of steps to advance. + //************************************************************************* + void advance(int n) + { + T range = LAST - FIRST + T(1); + + n = n % range; + + if (n > 0) + { + for (int i = 0; i < n; ++i) + { + operator ++(); + } + } + else + { + for (int i = 0; i < -n; ++i) + { + operator --(); + } + } + } + + //************************************************************************* + /// Conversion operator. + /// \return The value of the underlying type. + //************************************************************************* + operator T() + { + return value; + } + + //************************************************************************* + /// Const conversion operator. + /// \return The value of the underlying type. + //************************************************************************* + operator const T() const + { + return value; + } + + //************************************************************************* + /// ++ operator. + //************************************************************************* + cyclic_value& operator ++() + { + if (value >= LAST) + { + value = FIRST; + } + else + { + ++value; + } + + return *this; + } + + //************************************************************************* + /// ++ operator. + //************************************************************************* + cyclic_value operator ++(int) + { + cyclic_value temp(*this); + + operator++(); + + return temp; + } + + //************************************************************************* + /// -- operator. + //************************************************************************* + cyclic_value& operator --() + { + if (value <= FIRST) + { + value = LAST; + } + else + { + --value; + } + + return *this; + } + + //************************************************************************* + /// -- operator. + //************************************************************************* + cyclic_value operator --(int) + { + cyclic_value temp(*this); + + operator--(); + + return temp; + } + + //************************************************************************* + /// = operator. + //************************************************************************* + cyclic_value& operator =(T t) + { + set(t); + return *this; + } + + //************************************************************************* + /// = operator. + //************************************************************************* + template <const T FIRST2, const T LAST2> + cyclic_value& operator =(const cyclic_value<T, FIRST2, LAST2>& other) + { + set(other.get()); + return *this; + } + + //************************************************************************* + /// Gets the value. + //************************************************************************* + T get() const + { + return value; + } + + //************************************************************************* + /// Gets the first value. + //************************************************************************* + const T first() const + { + return FIRST; + } + + //************************************************************************* + /// Gets the last value. + //************************************************************************* + const T last() const + { + return LAST; + } + + //************************************************************************* + /// Swaps the values. + //************************************************************************* + void swap(cyclic_value<T, FIRST, LAST>& other) + { + std::swap(value, other.value); + } + + //************************************************************************* + /// Swaps the values. + //************************************************************************* + friend void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) + { + lhs.swap(rhs); + } + + //************************************************************************* + /// Operator ==. + //************************************************************************* + friend bool operator == (const cyclic_value<T, FIRST, LAST>& lhs, const cyclic_value<T, FIRST, LAST>& rhs) + { + return lhs.value == rhs.value; + } + + //************************************************************************* + /// Operator !=. + //************************************************************************* + friend bool operator != (const cyclic_value<T, FIRST, LAST>& lhs, const cyclic_value<T, FIRST, LAST>& rhs) + { + return !(lhs == rhs); + } + + private: + + T value; ///< The current value. + }; + + //*************************************************************************** + /// Provides a value that cycles between two limits. + /// Supports incrementing and decrementing. + ///\tparam T The type of the variable. + ///\tparam FIRST The first value of the range. + ///\tparam LAST The last value of the range. + ///\ingroup cyclic_value + //*************************************************************************** + template <typename T, const T FIRST, const T LAST> + class cyclic_value<T, FIRST, LAST, typename etl::enable_if<(FIRST == 0) && (LAST == 0)>::type> + { + public: + + //************************************************************************* + /// Constructor. + /// Sets 'first' and 'last' to the template parameter values. + /// The initial value is set to the first value. + //************************************************************************* + cyclic_value() + : value(FIRST), + first_value(FIRST), + last_value(LAST) + { + } + + //************************************************************************* + /// Constructor. + /// Sets the value to the first of the range. + ///\param first The first value in the range. + ///\param last The last value in the range. + //************************************************************************* + cyclic_value(T first_, T last_) + : value(first_), + first_value(first_), + last_value(last_) + { + } + + //************************************************************************* + /// Copy constructor. + //************************************************************************* + cyclic_value(const cyclic_value& other) + : value(other.value), + first_value(other.first_value), + last_value(other.last_value) + { + } + + //************************************************************************* + /// Sets the range. + /// Sets the value to the first of the range. + ///\param first The first value in the range. + ///\param last The last value in the range. + //************************************************************************* + void set(T first_, T last_) + { + first_value = first_; + last_value = last_; + value = first_; + } + + //************************************************************************* + /// Sets the value. + ///\param value The value. + //************************************************************************* + void set(T value_) + { + if (value_ > last_value) + { + value_ = last_value; + } + else if (value_ < first_value) + { + value_ = first_value; + } + + value = value_; + } + + //************************************************************************* + /// Resets the value to the first in the range. + //************************************************************************* + void to_first() + { + value = first_value; + } + + //************************************************************************* + /// Resets the value to the last in the range. + //************************************************************************* + void to_last() + { + value = last_value; + } + + //************************************************************************* + /// Advances to value by a number of steps. + ///\param n The number of steps to advance. + //************************************************************************* + void advance(int n) + { + T range = last_value - first_value + T(1); + + n = n % range; + + if (n > 0) + { + for (int i = 0; i < n; ++i) + { + operator ++(); + } + } + else + { + for (int i = 0; i < -n; ++i) + { + operator --(); + } + } + } + + //************************************************************************* + /// Conversion operator. + /// \return The value of the underlying type. + //************************************************************************* + operator T() + { + return value; + } + + //************************************************************************* + /// Const conversion operator. + /// \return The value of the underlying type. + //************************************************************************* + operator const T() const + { + return value; + } + + //************************************************************************* + /// ++ operator. + //************************************************************************* + cyclic_value& operator ++() + { + if (value >= last_value) + { + value = first_value; + } + else + { + ++value; + } + + return *this; + } + + //************************************************************************* + /// ++ operator. + //************************************************************************* + cyclic_value operator ++(int) + { + cyclic_value temp(*this); + + operator++(); + + return temp; + } + + //************************************************************************* + /// -- operator. + //************************************************************************* + cyclic_value& operator --() + { + if (value <= first_value) + { + value = last_value; + } + else + { + --value; + } + + return *this; + } + + //************************************************************************* + /// -- operator. + //************************************************************************* + cyclic_value operator --(int) + { + cyclic_value temp(*this); + + operator--(); + + return temp; + } + + //************************************************************************* + /// = operator. + //************************************************************************* + cyclic_value& operator =(T t) + { + set(t); + return *this; + } + + //************************************************************************* + /// = operator. + //************************************************************************* + cyclic_value& operator =(const cyclic_value& other) + { + value = other.value; + first_value = other.first_value; + last_value = other.last_value; + return *this; + } + + //************************************************************************* + /// Gets the value. + //************************************************************************* + T get() const + { + return value; + } + + //************************************************************************* + /// Gets the first value. + //************************************************************************* + T first() const + { + return first_value; + } + + //************************************************************************* + /// Gets the last value. + //************************************************************************* + T last() const + { + return last_value; + } + + //************************************************************************* + /// Swaps the values. + //************************************************************************* + void swap(cyclic_value<T, FIRST, LAST>& other) + { + std::swap(first_value, other.first_value); + std::swap(last_value, other.last_value); + std::swap(value, other.value); + } + + //************************************************************************* + /// Swaps the values. + //************************************************************************* + friend void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) + { + lhs.swap(rhs); + } + + //************************************************************************* + /// Operator ==. + //************************************************************************* + friend bool operator == (const cyclic_value<T, FIRST, LAST>& lhs, const cyclic_value<T, FIRST, LAST>& rhs) + { + return (lhs.value == rhs.value) && + (lhs.first_value == rhs.first_value) && + (lhs.last_value == rhs.last_value); + } + + //************************************************************************* + /// Operator !=. + //************************************************************************* + friend bool operator != (const cyclic_value<T, FIRST, LAST>& lhs, const cyclic_value<T, FIRST, LAST>& rhs) + { + return !(lhs == rhs); + } + + private: + + T value; ///< The current value. + T first_value; ///< The first value in the range. + T last_value; ///< The last value in the range. + }; +} + +#endif +