mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Merge branch 'feature/add-multi-loop' into development
# Conflicts: # include/etl/functional.h # include/etl/multi_loop.h # test/test_functional.cpp # test/test_multi_range.cpp
This commit is contained in:
commit
35debe90eb
@ -114,7 +114,7 @@ namespace etl
|
||||
|
||||
ETL_CONSTEXPR bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs < rhs;
|
||||
return (lhs < rhs);
|
||||
}
|
||||
};
|
||||
|
||||
@ -126,7 +126,7 @@ namespace etl
|
||||
|
||||
ETL_CONSTEXPR bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs <= rhs;
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
};
|
||||
|
||||
@ -138,7 +138,7 @@ namespace etl
|
||||
|
||||
ETL_CONSTEXPR bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs > rhs;
|
||||
return (rhs < lhs);
|
||||
}
|
||||
};
|
||||
|
||||
@ -150,7 +150,7 @@ namespace etl
|
||||
|
||||
ETL_CONSTEXPR bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs >= rhs;
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
};
|
||||
|
||||
@ -174,7 +174,7 @@ namespace etl
|
||||
|
||||
ETL_CONSTEXPR bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs != rhs;
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
@ -442,70 +442,6 @@ namespace etl
|
||||
return ~lhs;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
template <typename T>
|
||||
struct pre_increment
|
||||
{
|
||||
T operator()(T& value)
|
||||
{
|
||||
++value;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
template <typename T>
|
||||
struct post_increment
|
||||
{
|
||||
T operator()(T& value)
|
||||
{
|
||||
T temp(value);
|
||||
++value;
|
||||
return temp;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
template <typename T>
|
||||
struct increment : etl::pre_increment<T>
|
||||
{
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
template <typename T>
|
||||
struct pre_decrement
|
||||
{
|
||||
T operator()(T& value)
|
||||
{
|
||||
--value;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
template <typename T>
|
||||
struct post_decrement
|
||||
{
|
||||
T operator()(T& value)
|
||||
{
|
||||
T temp(value);
|
||||
--value;
|
||||
return temp;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
template <typename T>
|
||||
struct decrement : etl::pre_decrement<T>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,362 +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.
|
||||
//***************************************************************************
|
||||
void detach()
|
||||
{
|
||||
inner = ETL_NULLPTR;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Unlinks this and all inner loops.
|
||||
//***************************************************************************
|
||||
void detach_all()
|
||||
{
|
||||
if (inner != ETL_NULLPTR)
|
||||
{
|
||||
inner->detach_all();
|
||||
}
|
||||
|
||||
detach();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
//***************************************************************************
|
||||
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 TStepper The type that implements operator() to step.
|
||||
/// Default = etl::increment, which calls operator ++() for the type.
|
||||
/// \tparam TContinue The type that implements operator() to test for loop continuation.
|
||||
/// Default = etl::not_equal_to, which calls operator !=() for the type.
|
||||
//***************************************************************************
|
||||
template <typename T,
|
||||
typename TStepper = etl::increment<T>,
|
||||
typename TContinue = etl::not_equal_to<T> >
|
||||
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_,
|
||||
TStepper stepper_ = TStepper(),
|
||||
TContinue continue_loop_ = TContinue())
|
||||
: first(first_)
|
||||
, last(last_)
|
||||
, current(first_)
|
||||
, stepper(stepper_)
|
||||
, continue_loop(continue_loop_)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// 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 = !continue_loop(current, last); // Check for null loop.
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// 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 = step();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
has_completed = step();
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a const reference to the current loop value.
|
||||
//***************************************************************************
|
||||
const_reference value() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//***************************************************************************
|
||||
/// Increments the current loop value.
|
||||
//***************************************************************************
|
||||
bool step()
|
||||
{
|
||||
current = stepper(current);
|
||||
|
||||
const bool has_rolled_over = !continue_loop(current, last);
|
||||
|
||||
if (has_rolled_over)
|
||||
{
|
||||
current = first;
|
||||
}
|
||||
|
||||
return has_rolled_over;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
TStepper stepper; ///< The type to step the value to the next.
|
||||
TContinue continue_loop; ///< The type to determine if the loop should continue.
|
||||
};
|
||||
}
|
||||
|
||||
#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
|
||||
@ -169,66 +169,6 @@ namespace
|
||||
CHECK_EQUAL(1, ra);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_pre_increment)
|
||||
{
|
||||
etl::pre_increment<int> pi;
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
pi(i);
|
||||
j = pi(i);
|
||||
|
||||
CHECK_EQUAL(2, i);
|
||||
CHECK_EQUAL(2, j);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_post_increment)
|
||||
{
|
||||
etl::post_increment<int> pi;
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
pi(i);
|
||||
j = pi(i);
|
||||
|
||||
CHECK_EQUAL(2, i);
|
||||
CHECK_EQUAL(1, j);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_pre_decrement)
|
||||
{
|
||||
etl::pre_decrement<int> pd;
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
pd(i);
|
||||
j = pd(i);
|
||||
|
||||
CHECK_EQUAL(-2, i);
|
||||
CHECK_EQUAL(-2, j);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_post_decrement)
|
||||
{
|
||||
etl::post_decrement<int> pd;
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
pd(i);
|
||||
j = pd(i);
|
||||
|
||||
CHECK_EQUAL(-2, i);
|
||||
CHECK_EQUAL(-1, j);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_plus)
|
||||
{
|
||||
|
||||
@ -28,7 +28,7 @@ SOFTWARE.
|
||||
|
||||
#include "UnitTest++/UnitTest++.h"
|
||||
|
||||
#include "etl/multi_loop.h"
|
||||
#include "etl/multi_range.h"
|
||||
#include "etl/functional.h"
|
||||
|
||||
#include <iterator>
|
||||
@ -109,40 +109,42 @@ namespace
|
||||
|
||||
using Iterator = std::forward_list<std::string>::const_iterator;
|
||||
|
||||
struct Adder
|
||||
{
|
||||
Adder()
|
||||
: value(0)
|
||||
{
|
||||
}
|
||||
//*************************************************************************
|
||||
using StepperOuter = etl::multi_range<int>::forward_step_by;
|
||||
|
||||
Adder(int value_)
|
||||
: value(value_)
|
||||
{
|
||||
}
|
||||
//*************************************************************************
|
||||
using StepperMiddle = etl::multi_range<Index>::reverse_step;
|
||||
|
||||
int operator()(int i)
|
||||
{
|
||||
return i + value;
|
||||
}
|
||||
//*************************************************************************
|
||||
using CompareMiddle = etl::multi_range<Index>::greater_than_compare;
|
||||
|
||||
int value;
|
||||
};
|
||||
|
||||
using Outer = etl::multi_loop<int, Adder>;
|
||||
using Middle = etl::multi_loop<Index, etl::decrement<Index>, etl::greater<Index>>;
|
||||
using Inner = etl::multi_loop<Iterator>;
|
||||
// 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, 8, Adder(2));
|
||||
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)
|
||||
@ -154,9 +156,9 @@ namespace
|
||||
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());
|
||||
@ -187,9 +189,9 @@ namespace
|
||||
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());
|
||||
@ -219,9 +221,9 @@ namespace
|
||||
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());
|
||||
@ -247,8 +249,8 @@ namespace
|
||||
{
|
||||
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();
|
||||
@ -262,7 +264,7 @@ namespace
|
||||
|
||||
CHECK(null_loop.completed());
|
||||
|
||||
CHECK_EQUAL(1U, null_loop.number_of_loops());
|
||||
CHECK_EQUAL(1U, null_loop.number_of_ranges());
|
||||
|
||||
CHECK_EQUAL(0U, null_loop.number_of_iterations());
|
||||
|
||||
@ -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