mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Refactor multi_loop to multi_range
This commit is contained in:
parent
faed3231bf
commit
92c68b1367
@ -114,7 +114,19 @@ namespace etl
|
||||
|
||||
ETL_CONSTEXPR bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs < rhs;
|
||||
return (lhs < rhs);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct less_equal
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
ETL_CONSTEXPR bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
};
|
||||
|
||||
@ -126,7 +138,19 @@ namespace etl
|
||||
|
||||
ETL_CONSTEXPR bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs > rhs;
|
||||
return (rhs < lhs);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct greater_equal
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
ETL_CONSTEXPR bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
};
|
||||
|
||||
@ -239,59 +263,184 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
template <typename T>
|
||||
struct pre_increment
|
||||
template <typename T = void>
|
||||
struct plus
|
||||
{
|
||||
T operator()(T& value)
|
||||
{
|
||||
++value;
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
return value;
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs + rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct post_increment
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct minus
|
||||
{
|
||||
T operator()(T& value)
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
T temp(value);
|
||||
++value;
|
||||
return temp;
|
||||
return lhs - rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct increment : etl::pre_increment<T>
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct negate
|
||||
{
|
||||
};
|
||||
typedef T argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
template <typename T>
|
||||
struct pre_decrement
|
||||
{
|
||||
T operator()(T& value)
|
||||
ETL_CONSTEXPR T operator()(const T& lhs) const
|
||||
{
|
||||
--value;
|
||||
|
||||
return value;
|
||||
return -lhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct post_decrement
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct multiplies
|
||||
{
|
||||
T operator()(T& value)
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
T temp(value);
|
||||
--value;
|
||||
return temp;
|
||||
return lhs * rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct decrement : etl::pre_decrement<T>
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct divides
|
||||
{
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs / rhs;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct modulus
|
||||
{
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs % rhs;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct logical_and
|
||||
{
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs && rhs;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct logical_or
|
||||
{
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs || rhs;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct logical_not
|
||||
{
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs) const
|
||||
{
|
||||
return !lhs;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct bit_and
|
||||
{
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs & rhs;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct bit_or
|
||||
{
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs | rhs;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct bit_xor
|
||||
{
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs ^ rhs;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T = void>
|
||||
struct bit_not
|
||||
{
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef T result_type;
|
||||
|
||||
ETL_CONSTEXPR T operator()(const T& lhs) const
|
||||
{
|
||||
return ~lhs;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,341 +0,0 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2020 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_MULTI_LOOP_INCLUDED
|
||||
#define ETL_MULTI_LOOP_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "nullptr.h"
|
||||
#include "functional.h"
|
||||
#include "exception.h"
|
||||
#include "error_handler.h"
|
||||
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE "57"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// Exception for the multi_loop.
|
||||
//***************************************************************************
|
||||
class multi_loop_exception : public etl::exception
|
||||
{
|
||||
public:
|
||||
|
||||
multi_loop_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: exception(reason_, file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Circular reference exception.
|
||||
//***************************************************************************
|
||||
class multi_loop_circular_reference : public etl::multi_loop_exception
|
||||
{
|
||||
public:
|
||||
|
||||
multi_loop_circular_reference(string_type file_name_, numeric_type line_number_)
|
||||
: etl::multi_loop_exception(ETL_ERROR_TEXT("multi_loop:circular reference", ETL_FILE"A"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The base class for multi_loop.
|
||||
//***************************************************************************
|
||||
class imulti_loop
|
||||
{
|
||||
public:
|
||||
|
||||
//***************************************************************************
|
||||
/// Insert after this loop.
|
||||
//***************************************************************************
|
||||
imulti_loop& insert(imulti_loop& inner_loop)
|
||||
{
|
||||
ETL_ASSERT(is_valid(inner_loop), ETL_ERROR(multi_loop_circular_reference));
|
||||
|
||||
// Remember what the next loop was.
|
||||
imulti_loop* next = inner;
|
||||
|
||||
// Append the new loop
|
||||
inner = &inner_loop;
|
||||
|
||||
// Link to the original next loop.
|
||||
inner_loop.set_last(next);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Append to the most inner loop.
|
||||
//***************************************************************************
|
||||
imulti_loop& append(imulti_loop& inner_loop)
|
||||
{
|
||||
ETL_ASSERT(is_valid(inner_loop), ETL_ERROR(multi_loop_circular_reference));
|
||||
|
||||
if (inner != nullptr)
|
||||
{
|
||||
inner->append(inner_loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
inner = &inner_loop;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Unlinks this loop from its inner.
|
||||
/// Re-starts the loop.
|
||||
//***************************************************************************
|
||||
void clear()
|
||||
{
|
||||
inner = ETL_NULLPTR;
|
||||
start();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
bool completed() const
|
||||
{
|
||||
return has_completed;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Gets the total number of loops, from this loop inclusive.
|
||||
//***************************************************************************
|
||||
size_t number_of_loops() const
|
||||
{
|
||||
size_t count = 1U;
|
||||
|
||||
imulti_loop* p_loop = inner;
|
||||
|
||||
while (p_loop != ETL_NULLPTR)
|
||||
{
|
||||
++count;
|
||||
p_loop = p_loop->inner;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Gets the total number of iterations over all loops, from this loop inclusive.
|
||||
//***************************************************************************
|
||||
size_t number_of_iterations()
|
||||
{
|
||||
size_t count = 0U;
|
||||
|
||||
for (start(); !completed(); next())
|
||||
{
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Pure virtual functions.
|
||||
//***************************************************************************
|
||||
virtual void next() = 0;
|
||||
virtual void start() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructor
|
||||
//***************************************************************************
|
||||
imulti_loop()
|
||||
: has_completed(true)
|
||||
, inner(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Checks that there are no circular references by making sure that the
|
||||
/// inner loop does not link to this loop.
|
||||
//***************************************************************************
|
||||
bool is_valid(imulti_loop& inner_loop)
|
||||
{
|
||||
imulti_loop* loop = &inner_loop;
|
||||
|
||||
while (loop != ETL_NULLPTR)
|
||||
{
|
||||
if (loop == this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
loop = loop->inner;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Set the inner loop of the last linked loop.
|
||||
//***************************************************************************
|
||||
void set_last(imulti_loop* next)
|
||||
{
|
||||
// Find the last loop.
|
||||
imulti_loop* loop = this;
|
||||
|
||||
while (loop->inner != ETL_NULLPTR)
|
||||
{
|
||||
loop = loop->inner;
|
||||
}
|
||||
|
||||
loop->inner = next;
|
||||
}
|
||||
|
||||
bool has_completed;
|
||||
imulti_loop* inner;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// multi_loop
|
||||
/// \tparam T The type to loop over.
|
||||
/// \tparam TIncrementor The incrementor type that implements operator() to increment.
|
||||
/// Default = etl::increment, which calls operator ++() for the type.
|
||||
//***************************************************************************
|
||||
template <typename T, template <typename U> class TIncrementor = etl::increment>
|
||||
class multi_loop : public imulti_loop
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
typedef const T& const_reference;
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructor
|
||||
/// \param first The starting value of the loop.
|
||||
/// \param last The terminating value of the loop. Equal to the last required value + 1.
|
||||
//***************************************************************************
|
||||
multi_loop(value_type first_, value_type last_)
|
||||
: first(first_)
|
||||
, last(last_)
|
||||
, current(first_)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get a const reference to the starting value of the loop.
|
||||
//***************************************************************************
|
||||
const_reference begin()
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get a const reference to the terminating value of the loop.
|
||||
/// Equal to the last required value + 1.
|
||||
//***************************************************************************
|
||||
const_reference end()
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Initialises the loops to the starting values.
|
||||
//***************************************************************************
|
||||
void start() ETL_OVERRIDE
|
||||
{
|
||||
if (inner != ETL_NULLPTR)
|
||||
{
|
||||
inner->start();
|
||||
}
|
||||
|
||||
current = first;
|
||||
has_completed = false;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Step to the next logical values in the loops.
|
||||
//***************************************************************************
|
||||
void next() ETL_OVERRIDE
|
||||
{
|
||||
has_completed = false;
|
||||
|
||||
if (inner != ETL_NULLPTR)
|
||||
{
|
||||
inner->next();
|
||||
|
||||
if (inner->completed())
|
||||
{
|
||||
has_completed = increment();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
has_completed = increment();
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a const reference to the current loop value.
|
||||
//***************************************************************************
|
||||
const_reference value() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//***************************************************************************
|
||||
/// Increments the current loop value.
|
||||
//***************************************************************************
|
||||
bool increment()
|
||||
{
|
||||
incrementor(current);
|
||||
|
||||
const bool has_rolled_over = (current == last);
|
||||
|
||||
if (has_rolled_over)
|
||||
{
|
||||
current = first;
|
||||
}
|
||||
|
||||
return has_rolled_over;
|
||||
}
|
||||
|
||||
TIncrementor<value_type> incrementor; ///< The incrementor type.
|
||||
|
||||
value_type first; ///< The first value of the loop.
|
||||
value_type last; ///< The terminating value of the loop.
|
||||
value_type current; ///< The current value of the loop.
|
||||
};
|
||||
}
|
||||
|
||||
#undef ETL_FILE
|
||||
|
||||
#endif
|
||||
534
include/etl/multi_range.h
Normal file
534
include/etl/multi_range.h
Normal file
@ -0,0 +1,534 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2020 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_MULTI_LOOP_INCLUDED
|
||||
#define ETL_MULTI_LOOP_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "nullptr.h"
|
||||
#include "functional.h"
|
||||
#include "exception.h"
|
||||
#include "error_handler.h"
|
||||
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE "57"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// Exception for the multi_range.
|
||||
//***************************************************************************
|
||||
class multi_range_exception : public etl::exception
|
||||
{
|
||||
public:
|
||||
|
||||
multi_range_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: exception(reason_, file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Circular reference exception.
|
||||
//***************************************************************************
|
||||
class multi_range_circular_reference : public etl::multi_range_exception
|
||||
{
|
||||
public:
|
||||
|
||||
multi_range_circular_reference(string_type file_name_, numeric_type line_number_)
|
||||
: etl::multi_range_exception(ETL_ERROR_TEXT("multi_range:circular reference", ETL_FILE"A"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The base class for multi_range.
|
||||
//***************************************************************************
|
||||
class imulti_range
|
||||
{
|
||||
public:
|
||||
|
||||
//***************************************************************************
|
||||
/// Insert after this range.
|
||||
//***************************************************************************
|
||||
imulti_range& insert(imulti_range& inner_range)
|
||||
{
|
||||
ETL_ASSERT(is_valid(inner_range), ETL_ERROR(multi_range_circular_reference));
|
||||
|
||||
// Remember what the next range was.
|
||||
imulti_range* next = inner;
|
||||
|
||||
// Append the new range
|
||||
inner = &inner_range;
|
||||
|
||||
// Link to the original next range.
|
||||
inner_range.set_last(next);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Append to the most inner range.
|
||||
//***************************************************************************
|
||||
imulti_range& append(imulti_range& inner_range)
|
||||
{
|
||||
ETL_ASSERT(is_valid(inner_range), ETL_ERROR(multi_range_circular_reference));
|
||||
|
||||
if (inner != nullptr)
|
||||
{
|
||||
inner->append(inner_range);
|
||||
}
|
||||
else
|
||||
{
|
||||
inner = &inner_range;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Unlinks this range from its inner.
|
||||
//***************************************************************************
|
||||
void detach()
|
||||
{
|
||||
inner = ETL_NULLPTR;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Unlinks this and all inner ranges.
|
||||
//***************************************************************************
|
||||
void detach_all()
|
||||
{
|
||||
if (inner != ETL_NULLPTR)
|
||||
{
|
||||
inner->detach_all();
|
||||
}
|
||||
|
||||
detach();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
bool completed() const
|
||||
{
|
||||
return has_completed;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Gets the total number of ranges, from this range inclusive.
|
||||
//***************************************************************************
|
||||
size_t number_of_ranges() const
|
||||
{
|
||||
size_t count = 1U;
|
||||
|
||||
imulti_range* p_range = inner;
|
||||
|
||||
while (p_range != ETL_NULLPTR)
|
||||
{
|
||||
++count;
|
||||
p_range = p_range->inner;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Gets the total number of iterations over all ranges, from this range inclusive.
|
||||
//***************************************************************************
|
||||
size_t number_of_iterations()
|
||||
{
|
||||
size_t count = 0U;
|
||||
|
||||
for (start(); !completed(); next())
|
||||
{
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Pure virtual functions.
|
||||
//***************************************************************************
|
||||
virtual void next() = 0;
|
||||
virtual void start() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructor
|
||||
//***************************************************************************
|
||||
imulti_range()
|
||||
: has_completed(true)
|
||||
, inner(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Checks that there are no circular references.
|
||||
//***************************************************************************
|
||||
bool is_valid(imulti_range& inner_range)
|
||||
{
|
||||
imulti_range* range = &inner_range;
|
||||
|
||||
while (range != ETL_NULLPTR)
|
||||
{
|
||||
if (range == this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
range = range->inner;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Set the inner range of the last linked range.
|
||||
//***************************************************************************
|
||||
void set_last(imulti_range* next)
|
||||
{
|
||||
// Find the last range.
|
||||
imulti_range* range = this;
|
||||
|
||||
while (range->inner != ETL_NULLPTR)
|
||||
{
|
||||
range = range->inner;
|
||||
}
|
||||
|
||||
range->inner = next;
|
||||
}
|
||||
|
||||
bool has_completed;
|
||||
imulti_range* inner;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// multi_range
|
||||
/// \tparam T The type to range over.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
class multi_range : public imulti_range
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
typedef const T& const_reference;
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
struct step_type
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
virtual void operator()(value_type& value) = 0;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
struct forward_step : public step_type
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
virtual void operator()(value_type& value)
|
||||
{
|
||||
++value;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
struct forward_step_by : public step_type
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
explicit forward_step_by(const value_type& step_value_)
|
||||
: step_value(step_value_)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(value_type& value)
|
||||
{
|
||||
value += step_value;
|
||||
}
|
||||
|
||||
const value_type step_value;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
struct reverse_step : public step_type
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
virtual void operator()(value_type& value)
|
||||
{
|
||||
--value;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
struct reverse_step_by : public step_type
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
explicit reverse_step_by(const value_type& step_value_)
|
||||
: step_value(step_value_)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(value_type& value)
|
||||
{
|
||||
value -= step_value;
|
||||
}
|
||||
|
||||
const value_type step_value;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
struct compare_type
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
virtual bool operator()(const value_type& current, const value_type& last) const = 0;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
struct not_equal_compare : public compare_type
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
virtual bool operator()(const value_type& current, const value_type& last) const ETL_OVERRIDE
|
||||
{
|
||||
return etl::not_equal_to<value_type>()(current, last);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
struct less_than_compare : public compare_type
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
virtual bool operator()(const value_type& current, const value_type& last) const ETL_OVERRIDE
|
||||
{
|
||||
return etl::less<value_type>()(current, last);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
struct greater_than_compare : public compare_type
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
virtual bool operator()(const value_type& current, const value_type& last) const ETL_OVERRIDE
|
||||
{
|
||||
return etl::greater<value_type>()(current, last);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructor
|
||||
/// \param first The starting value of the range.
|
||||
/// \param last The terminating value of the range. Equal to the last required value + 1.
|
||||
//***************************************************************************
|
||||
multi_range(value_type first_,
|
||||
value_type last_)
|
||||
: first(first_)
|
||||
, last(last_)
|
||||
, current(first_)
|
||||
, p_stepper(&default_stepper)
|
||||
, p_compare(&default_compare)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructor
|
||||
/// \param first The starting value of the range.
|
||||
/// \param last The terminating value of the range. Equal to the last required value + 1.
|
||||
//***************************************************************************
|
||||
multi_range(value_type first_,
|
||||
value_type last_,
|
||||
step_type& stepper_)
|
||||
: first(first_)
|
||||
, last(last_)
|
||||
, current(first_)
|
||||
, p_stepper(&stepper_)
|
||||
, p_compare(&default_compare)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructor
|
||||
/// \param first The starting value of the range.
|
||||
/// \param last The terminating value of the range.
|
||||
//***************************************************************************
|
||||
multi_range(value_type first_,
|
||||
value_type last_,
|
||||
compare_type& compare_)
|
||||
: first(first_)
|
||||
, last(last_)
|
||||
, current(first_)
|
||||
, p_stepper(&default_stepper)
|
||||
, p_compare(&compare_)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructor
|
||||
/// \param first The starting value of the range.
|
||||
/// \param last The terminating value of the range. Equal to the last required value + 1.
|
||||
//***************************************************************************
|
||||
multi_range(value_type first_,
|
||||
value_type last_,
|
||||
step_type& stepper_,
|
||||
compare_type& compare_)
|
||||
: first(first_)
|
||||
, last(last_)
|
||||
, current(first_)
|
||||
, p_stepper(&stepper_)
|
||||
, p_compare(&compare_)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get a const reference to the starting value of the range.
|
||||
//***************************************************************************
|
||||
const_reference begin()
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Get a const reference to the terminating value of the range.
|
||||
/// Equal to the last required value + 1.
|
||||
//***************************************************************************
|
||||
const_reference end()
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Initialises the ranges to the starting values.
|
||||
//***************************************************************************
|
||||
void start() ETL_OVERRIDE
|
||||
{
|
||||
if (inner != ETL_NULLPTR)
|
||||
{
|
||||
inner->start();
|
||||
}
|
||||
|
||||
current = first;
|
||||
has_completed = !(*p_compare)(current, last); // Check for null range.
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Step to the next logical values in the ranges.
|
||||
//***************************************************************************
|
||||
void next() ETL_OVERRIDE
|
||||
{
|
||||
has_completed = false;
|
||||
|
||||
if (inner != ETL_NULLPTR)
|
||||
{
|
||||
inner->next();
|
||||
|
||||
if (inner->completed())
|
||||
{
|
||||
has_completed = step();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
has_completed = step();
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a const reference to the current range value.
|
||||
//***************************************************************************
|
||||
const_reference value() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//***************************************************************************
|
||||
/// Increments the current range value.
|
||||
//***************************************************************************
|
||||
bool step()
|
||||
{
|
||||
(*p_stepper)(current);
|
||||
|
||||
const bool has_rolled_over = !(*p_compare)(current, last);
|
||||
|
||||
if (has_rolled_over)
|
||||
{
|
||||
current = first;
|
||||
}
|
||||
|
||||
return has_rolled_over;
|
||||
}
|
||||
|
||||
multi_range() ETL_DELETE;
|
||||
multi_range(const multi_range&) ETL_DELETE;
|
||||
multi_range& operator =(const multi_range&) ETL_DELETE;
|
||||
|
||||
value_type first; ///< The first value of the range.
|
||||
value_type last; ///< The terminating value of the range.
|
||||
value_type current; ///< The current value of the range.
|
||||
|
||||
step_type* p_stepper;
|
||||
forward_step default_stepper;
|
||||
|
||||
compare_type* p_compare;
|
||||
not_equal_compare default_compare;
|
||||
};
|
||||
}
|
||||
|
||||
#undef ETL_FILE
|
||||
|
||||
#endif
|
||||
@ -154,63 +154,113 @@ namespace
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_pre_increment)
|
||||
TEST(test_plus)
|
||||
{
|
||||
etl::pre_increment<int> pi;
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
pi(i);
|
||||
j = pi(i);
|
||||
|
||||
CHECK_EQUAL(2, i);
|
||||
CHECK_EQUAL(2, j);
|
||||
auto f = etl::plus<int>();
|
||||
CHECK_EQUAL(2 + 4, f(2, 4));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_post_increment)
|
||||
TEST(test_minus)
|
||||
{
|
||||
etl::post_increment<int> pi;
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
pi(i);
|
||||
j = pi(i);
|
||||
|
||||
CHECK_EQUAL(2, i);
|
||||
CHECK_EQUAL(1, j);
|
||||
auto f = etl::minus<int>();
|
||||
CHECK_EQUAL(2 - 4, f(2, 4));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_pre_decrement)
|
||||
TEST(test_negate)
|
||||
{
|
||||
etl::pre_decrement<int> pi;
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
pi(i);
|
||||
j = pi(i);
|
||||
|
||||
CHECK_EQUAL(-2, i);
|
||||
CHECK_EQUAL(-2, j);
|
||||
auto f = etl::negate<int>();
|
||||
CHECK_EQUAL(-2, f(2));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_post_decrement)
|
||||
TEST(test_multiplies)
|
||||
{
|
||||
etl::post_decrement<int> pi;
|
||||
auto f = etl::multiplies<int>();
|
||||
CHECK_EQUAL(2 * 4, f(2, 4));
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
//*************************************************************************
|
||||
TEST(test_divides)
|
||||
{
|
||||
auto f = etl::divides<int>();
|
||||
CHECK_EQUAL(4 / 2, f(4, 2));
|
||||
}
|
||||
|
||||
pi(i);
|
||||
j = pi(i);
|
||||
//*************************************************************************
|
||||
TEST(test_modulus)
|
||||
{
|
||||
auto f = etl::modulus<int>();
|
||||
CHECK_EQUAL(5 % 2, f(5, 2));
|
||||
}
|
||||
|
||||
CHECK_EQUAL(-2, i);
|
||||
CHECK_EQUAL(-1, j);
|
||||
//*************************************************************************
|
||||
TEST(test_logical_and)
|
||||
{
|
||||
auto f = etl::logical_and<bool>();
|
||||
CHECK_EQUAL(false && false, f(false, false));
|
||||
CHECK_EQUAL(false && true, f(false, true));
|
||||
CHECK_EQUAL(true && false, f(true, false));
|
||||
CHECK_EQUAL(true && true, f(true, true));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_logical_or)
|
||||
{
|
||||
auto f = etl::logical_or<bool>();
|
||||
CHECK_EQUAL(false || false, f(false, false));
|
||||
CHECK_EQUAL(false || true, f(false, true));
|
||||
CHECK_EQUAL(true || false, f(true, false));
|
||||
CHECK_EQUAL(true || true, f(true, true));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_logical_not)
|
||||
{
|
||||
auto f = etl::logical_not<bool>();
|
||||
CHECK_EQUAL(!false, f(false));
|
||||
CHECK_EQUAL(!true, f(true));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_bit_and)
|
||||
{
|
||||
auto f = etl::bit_and<uint8_t>();
|
||||
CHECK_EQUAL(0x00 & 0xFF, f(0x00, 0xFF));
|
||||
CHECK_EQUAL(0xAA & 0xFF, f(0xAA, 0xFF));
|
||||
CHECK_EQUAL(0x55 & 0xFF, f(0x55, 0xFF));
|
||||
CHECK_EQUAL(0xFF & 0xFF, f(0xFF, 0xFF));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_bit_or)
|
||||
{
|
||||
auto f = etl::bit_or<uint8_t>();
|
||||
CHECK_EQUAL(0xFF | 0x00, f(0xFF, 0x00));
|
||||
CHECK_EQUAL(0xAA | 0x00, f(0xAA, 0x00));
|
||||
CHECK_EQUAL(0x55 | 0x00, f(0x55, 0x00));
|
||||
CHECK_EQUAL(0x55 | 0xAA, f(0x55, 0xAA));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_bit_xor)
|
||||
{
|
||||
auto f = etl::bit_xor<uint8_t>();
|
||||
CHECK_EQUAL(0xFF ^ 0x00, f(0xFF, 0x00));
|
||||
CHECK_EQUAL(0xAA ^ 0x00, f(0xAA, 0x00));
|
||||
CHECK_EQUAL(0x55 ^ 0x00, f(0x55, 0x00));
|
||||
CHECK_EQUAL(0x55 ^ 0xAA, f(0x55, 0xAA));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_bit_not)
|
||||
{
|
||||
auto f = etl::bit_not<uint8_t>();
|
||||
CHECK_EQUAL(uint8_t(~0x00), f(0x00));
|
||||
CHECK_EQUAL(uint8_t(~0x55), f(0x55));
|
||||
CHECK_EQUAL(uint8_t(~0xAA), f(0xAA));
|
||||
CHECK_EQUAL(uint8_t(~0xFF), f(0xFF));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -28,12 +28,14 @@ SOFTWARE.
|
||||
|
||||
#include "UnitTest++/UnitTest++.h"
|
||||
|
||||
#include "etl/multi_loop.h"
|
||||
#include "etl/multi_range.h"
|
||||
#include "etl/functional.h"
|
||||
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <forward_list>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -107,45 +109,63 @@ namespace
|
||||
|
||||
using Iterator = std::forward_list<std::string>::const_iterator;
|
||||
|
||||
using Outer = etl::multi_loop<int>;
|
||||
using Middle = etl::multi_loop<Index, etl::decrement>;
|
||||
using Inner = etl::multi_loop<Iterator>;
|
||||
//*************************************************************************
|
||||
using StepperOuter = etl::multi_range<int>::forward_step_by;
|
||||
|
||||
//*************************************************************************
|
||||
using StepperMiddle = etl::multi_range<Index>::reverse_step;
|
||||
|
||||
//*************************************************************************
|
||||
using CompareMiddle = etl::multi_range<Index>::greater_than_compare;
|
||||
|
||||
// Declare the loops.
|
||||
using Outer = etl::multi_range<int>;
|
||||
using Middle = etl::multi_range<Index>;
|
||||
using Inner = etl::multi_range<Iterator>;
|
||||
|
||||
// A list of strings.
|
||||
std::forward_list<std::string> strings =
|
||||
{
|
||||
"zero", "one", "two", "three"
|
||||
};
|
||||
|
||||
Outer outer(0, 4);
|
||||
Middle middle(Index(2), Index(-2));
|
||||
Inner inner(strings.begin(), strings.end());
|
||||
// Outer loop : Iterate from 0 to 6 in steps of 2.
|
||||
// Keep looping while the value is not equal to 8.
|
||||
StepperOuter stepperOuter(2);
|
||||
Outer outer(0, 8, stepperOuter);
|
||||
|
||||
SUITE(test_multi_loop)
|
||||
// Middle loop : Iterate from Index(2) to Index(-1).
|
||||
// Keep looping while the value is greater than Index(-2).
|
||||
StepperMiddle stepperMiddle;
|
||||
CompareMiddle compareMiddle;
|
||||
Middle middle(Index(2), Index(-2), stepperMiddle, compareMiddle);
|
||||
|
||||
// Inner loop : Iterate from the first to the last string in the forward_list of strings.
|
||||
// Keep looping while the iterator is not equal to strings.end().
|
||||
Inner inner(strings.begin(), strings.end());
|
||||
|
||||
SUITE(test_multi_range)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(create_three_loops)
|
||||
{
|
||||
outer.clear();
|
||||
middle.clear();
|
||||
inner.clear();
|
||||
|
||||
outer.append(middle);
|
||||
middle.insert(inner);
|
||||
|
||||
CHECK(!outer.completed());
|
||||
CHECK(!middle.completed());
|
||||
CHECK(!inner.completed());
|
||||
CHECK(outer.completed());
|
||||
CHECK(middle.completed());
|
||||
CHECK(inner.completed());
|
||||
|
||||
CHECK_EQUAL(3U, outer.number_of_loops());
|
||||
CHECK_EQUAL(2U, middle.number_of_loops());
|
||||
CHECK_EQUAL(1U, inner.number_of_loops());
|
||||
CHECK_EQUAL(3U, outer.number_of_ranges());
|
||||
CHECK_EQUAL(2U, middle.number_of_ranges());
|
||||
CHECK_EQUAL(1U, inner.number_of_ranges());
|
||||
|
||||
CHECK_EQUAL(64U, outer.number_of_iterations());
|
||||
CHECK_EQUAL(16U, middle.number_of_iterations());
|
||||
CHECK_EQUAL(4U, inner.number_of_iterations());
|
||||
|
||||
CHECK_EQUAL(0, outer.begin());
|
||||
CHECK_EQUAL(4, outer.end());
|
||||
CHECK_EQUAL(8, outer.end());
|
||||
CHECK_EQUAL(outer.begin(), outer.value());
|
||||
|
||||
CHECK_EQUAL(Index(2), middle.begin());
|
||||
@ -155,32 +175,30 @@ namespace
|
||||
CHECK(strings.begin() == inner.begin());
|
||||
CHECK(strings.end() == inner.end());
|
||||
CHECK(inner.begin() == inner.value());
|
||||
|
||||
outer.detach_all();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(create_three_loops_different_order)
|
||||
{
|
||||
outer.clear();
|
||||
middle.clear();
|
||||
inner.clear();
|
||||
|
||||
middle.append(inner);
|
||||
outer.insert(middle);
|
||||
|
||||
CHECK(!outer.completed());
|
||||
CHECK(!middle.completed());
|
||||
CHECK(!inner.completed());
|
||||
CHECK(outer.completed());
|
||||
CHECK(middle.completed());
|
||||
CHECK(inner.completed());
|
||||
|
||||
CHECK_EQUAL(3U, outer.number_of_loops());
|
||||
CHECK_EQUAL(2U, middle.number_of_loops());
|
||||
CHECK_EQUAL(1U, inner.number_of_loops());
|
||||
CHECK_EQUAL(3U, outer.number_of_ranges());
|
||||
CHECK_EQUAL(2U, middle.number_of_ranges());
|
||||
CHECK_EQUAL(1U, inner.number_of_ranges());
|
||||
|
||||
CHECK_EQUAL(64U, outer.number_of_iterations());
|
||||
CHECK_EQUAL(16U, middle.number_of_iterations());
|
||||
CHECK_EQUAL(4U, inner.number_of_iterations());
|
||||
|
||||
CHECK_EQUAL(0, outer.begin());
|
||||
CHECK_EQUAL(4, outer.end());
|
||||
CHECK_EQUAL(8, outer.end());
|
||||
CHECK_EQUAL(outer.begin(), outer.value());
|
||||
|
||||
CHECK_EQUAL(Index(2), middle.begin());
|
||||
@ -190,31 +208,29 @@ namespace
|
||||
CHECK(strings.begin() == inner.begin());
|
||||
CHECK(strings.end() == inner.end());
|
||||
CHECK(inner.begin() == inner.value());
|
||||
|
||||
outer.detach_all();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(create_three_loops_functional_style)
|
||||
{
|
||||
outer.clear();
|
||||
middle.clear();
|
||||
inner.clear();
|
||||
|
||||
outer.append(inner).insert(middle);
|
||||
|
||||
CHECK(!outer.completed());
|
||||
CHECK(!middle.completed());
|
||||
CHECK(!inner.completed());
|
||||
CHECK(outer.completed());
|
||||
CHECK(middle.completed());
|
||||
CHECK(inner.completed());
|
||||
|
||||
CHECK_EQUAL(3U, outer.number_of_loops());
|
||||
CHECK_EQUAL(2U, middle.number_of_loops());
|
||||
CHECK_EQUAL(1U, inner.number_of_loops());
|
||||
CHECK_EQUAL(3U, outer.number_of_ranges());
|
||||
CHECK_EQUAL(2U, middle.number_of_ranges());
|
||||
CHECK_EQUAL(1U, inner.number_of_ranges());
|
||||
|
||||
CHECK_EQUAL(64U, outer.number_of_iterations());
|
||||
CHECK_EQUAL(16U, middle.number_of_iterations());
|
||||
CHECK_EQUAL(4U, inner.number_of_iterations());
|
||||
|
||||
CHECK_EQUAL(0, outer.begin());
|
||||
CHECK_EQUAL(4, outer.end());
|
||||
CHECK_EQUAL(8, outer.end());
|
||||
CHECK_EQUAL(outer.begin(), outer.value());
|
||||
|
||||
CHECK_EQUAL(Index(2), middle.begin());
|
||||
@ -224,28 +240,42 @@ namespace
|
||||
CHECK(strings.begin() == inner.begin());
|
||||
CHECK(strings.end() == inner.end());
|
||||
CHECK(inner.begin() == inner.value());
|
||||
|
||||
outer.detach_all();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(create_three_loops_circular_links)
|
||||
{
|
||||
outer.clear();
|
||||
middle.clear();
|
||||
inner.clear();
|
||||
|
||||
middle.append(outer);
|
||||
|
||||
CHECK_THROW(outer.append(middle), etl::multi_loop_circular_reference);
|
||||
CHECK_THROW(inner.append(inner), etl::multi_loop_circular_reference);
|
||||
CHECK_THROW(outer.append(middle), etl::multi_range_circular_reference);
|
||||
CHECK_THROW(inner.append(inner), etl::multi_range_circular_reference);
|
||||
|
||||
outer.detach();
|
||||
middle.detach();
|
||||
inner.detach();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(null_loop)
|
||||
{
|
||||
Outer null_loop(2, 2);
|
||||
|
||||
CHECK(null_loop.completed());
|
||||
|
||||
CHECK_EQUAL(1U, null_loop.number_of_ranges());
|
||||
|
||||
CHECK_EQUAL(0U, null_loop.number_of_iterations());
|
||||
|
||||
CHECK_EQUAL(2, null_loop.begin());
|
||||
CHECK_EQUAL(2, null_loop.end());
|
||||
CHECK_EQUAL(null_loop.begin(), null_loop.value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(run_three_loops)
|
||||
{
|
||||
outer.clear();
|
||||
middle.clear();
|
||||
inner.clear();
|
||||
|
||||
outer.append(middle).append(inner);
|
||||
|
||||
struct result
|
||||
@ -261,18 +291,18 @@ namespace
|
||||
result{ 0, 1, "zero" }, result{ 0, 1, "one" }, result{ 0, 1, "two" }, result{ 0, 1, "three" },
|
||||
result{ 0, 0, "zero" }, result{ 0, 0, "one" }, result{ 0, 0, "two" }, result{ 0, 0, "three" },
|
||||
result{ 0, -1, "zero" }, result{ 0, -1, "one" }, result{ 0, -1, "two" }, result{ 0, -1, "three" },
|
||||
result{ 1, 2, "zero" }, result{ 1, 2, "one" }, result{ 1, 2, "two" }, result{ 1, 2, "three" },
|
||||
result{ 1, 1, "zero" }, result{ 1, 1, "one" }, result{ 1, 1, "two" }, result{ 1, 1, "three" },
|
||||
result{ 1, 0, "zero" }, result{ 1, 0, "one" }, result{ 1, 0, "two" }, result{ 1, 0, "three" },
|
||||
result{ 1, -1, "zero" }, result{ 1, -1, "one" }, result{ 1, -1, "two" }, result{ 1, -1, "three" },
|
||||
result{ 2, 2, "zero" }, result{ 2, 2, "one" }, result{ 2, 2, "two" }, result{ 2, 2, "three" },
|
||||
result{ 2, 1, "zero" }, result{ 2, 1, "one" }, result{ 2, 1, "two" }, result{ 2, 1, "three" },
|
||||
result{ 2, 0, "zero" }, result{ 2, 0, "one" }, result{ 2, 0, "two" }, result{ 2, 0, "three" },
|
||||
result{ 2, -1, "zero" }, result{ 2, -1, "one" }, result{ 2, -1, "two" }, result{ 2, -1, "three" },
|
||||
result{ 3, 2, "zero" }, result{ 3, 2, "one" }, result{ 3, 2, "two" }, result{ 3, 2, "three" },
|
||||
result{ 3, 1, "zero" }, result{ 3, 1, "one" }, result{ 3, 1, "two" }, result{ 3, 1, "three" },
|
||||
result{ 3, 0, "zero" }, result{ 3, 0, "one" }, result{ 3, 0, "two" }, result{ 3, 0, "three" },
|
||||
result{ 3, -1, "zero" }, result{ 3, -1, "one" }, result{ 3, -1, "two" }, result{ 3, -1, "three" }
|
||||
result{ 4, 2, "zero" }, result{ 4, 2, "one" }, result{ 4, 2, "two" }, result{ 4, 2, "three" },
|
||||
result{ 4, 1, "zero" }, result{ 4, 1, "one" }, result{ 4, 1, "two" }, result{ 4, 1, "three" },
|
||||
result{ 4, 0, "zero" }, result{ 4, 0, "one" }, result{ 4, 0, "two" }, result{ 4, 0, "three" },
|
||||
result{ 4, -1, "zero" }, result{ 4, -1, "one" }, result{ 4, -1, "two" }, result{ 4, -1, "three" },
|
||||
result{ 6, 2, "zero" }, result{ 6, 2, "one" }, result{ 6, 2, "two" }, result{ 6, 2, "three" },
|
||||
result{ 6, 1, "zero" }, result{ 6, 1, "one" }, result{ 6, 1, "two" }, result{ 6, 1, "three" },
|
||||
result{ 6, 0, "zero" }, result{ 6, 0, "one" }, result{ 6, 0, "two" }, result{ 6, 0, "three" },
|
||||
result{ 6, -1, "zero" }, result{ 6, -1, "one" }, result{ 6, -1, "two" }, result{ 6, -1, "three" }
|
||||
};
|
||||
|
||||
size_t i = 0U;
|
||||
@ -322,15 +352,13 @@ namespace
|
||||
}
|
||||
|
||||
CHECK(outer.completed());
|
||||
|
||||
outer.detach_all();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(create_three_loops_but_just_run_the_inner_two)
|
||||
{
|
||||
outer.clear();
|
||||
middle.clear();
|
||||
inner.clear();
|
||||
|
||||
outer.append(middle).append(inner);
|
||||
|
||||
struct result
|
||||
@ -395,6 +423,8 @@ namespace
|
||||
}
|
||||
|
||||
CHECK(middle.completed());
|
||||
|
||||
outer.detach_all();
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1292,7 +1292,7 @@
|
||||
<ClInclude Include="..\..\include\etl\macros.h" />
|
||||
<ClInclude Include="..\..\include\etl\message_packet.h" />
|
||||
<ClInclude Include="..\..\include\etl\multi_array.h" />
|
||||
<ClInclude Include="..\..\include\etl\multi_loop.h" />
|
||||
<ClInclude Include="..\..\include\etl\multi_range.h" />
|
||||
<ClInclude Include="..\..\include\etl\mutex\mutex_clang_sync.h" />
|
||||
<ClInclude Include="..\..\include\etl\mutex\mutex_freertos.h" />
|
||||
<ClInclude Include="..\..\include\etl\negative.h" />
|
||||
@ -1863,7 +1863,7 @@
|
||||
<ClCompile Include="..\test_message_timer.cpp" />
|
||||
<ClCompile Include="..\test_multimap.cpp" />
|
||||
<ClCompile Include="..\test_multiset.cpp" />
|
||||
<ClCompile Include="..\test_multi_loop.cpp" />
|
||||
<ClCompile Include="..\test_multi_range.cpp" />
|
||||
<ClCompile Include="..\test_murmur3.cpp" />
|
||||
<ClCompile Include="..\test_numeric.cpp" />
|
||||
<ClCompile Include="..\test_observer.cpp">
|
||||
|
||||
@ -906,9 +906,9 @@
|
||||
<ClInclude Include="..\..\arduino\Embedded_Template_Library.h">
|
||||
<Filter>ETL\Arduino</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\multi_loop.h">
|
||||
<ClInclude Include="..\..\include\etl\multi_range.h">
|
||||
<Filter>ETL\Utilities</Filter>
|
||||
</ClInclude>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\main.cpp">
|
||||
@ -1442,7 +1442,7 @@
|
||||
<ClCompile Include="..\test_format_spec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_multi_loop.cpp">
|
||||
<ClCompile Include="..\test_multi_range.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
@ -1563,4 +1563,4 @@
|
||||
<Filter>Resource Files\Images</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
Loading…
x
Reference in New Issue
Block a user