mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Merge branch 'development' into manchester-big-endian-support
This commit is contained in:
commit
805dc2f5ff
38
.treefmt.toml
Normal file
38
.treefmt.toml
Normal file
@ -0,0 +1,38 @@
|
||||
[global]
|
||||
excludes = [
|
||||
"**/Doxyfile",
|
||||
"**/Makefile",
|
||||
"*.*-format",
|
||||
"*.S",
|
||||
"*.cmm",
|
||||
"*.css",
|
||||
"*.dld",
|
||||
"*.gdb",
|
||||
"*.gif",
|
||||
"*.gitignore",
|
||||
"*.html",
|
||||
"*.ini",
|
||||
"*.josh",
|
||||
"*.json",
|
||||
"*.md",
|
||||
"*.png",
|
||||
"*.puml",
|
||||
"*.py",
|
||||
"*.rb",
|
||||
"*.rst",
|
||||
"*.s",
|
||||
"*.sh",
|
||||
"*.spec",
|
||||
"*.toml",
|
||||
"*.txt",
|
||||
"*.yaml",
|
||||
"*.yml",
|
||||
"docker/**",
|
||||
"scripts/clang-format-wrapper",
|
||||
"include/etl/generators/**"
|
||||
]
|
||||
|
||||
[formatter.cpp]
|
||||
command = "scripts/clang-format-wrapper"
|
||||
options = [ "-i", "--style=file" ]
|
||||
includes = [ "*.c", "*.cc", "*.cpp", "*.h", "*.hh", "*.hpp" ]
|
||||
@ -6,6 +6,7 @@ Thanks for considering a contribution! Here’s what you need to know before ope
|
||||
- If you are fixing a bug, add a unit test that *fails* before the bug fix is implemented.
|
||||
- Do not initiate a pull request until all of the units tests pass. See below for information on project files and test scripts.
|
||||
- Branches should be based on the branch `master`. If `development` has pending updates, I’ll rebase the PR against it before pulling..
|
||||
- For formatting help, you can use clang-format, or the convenience wrapper treefmt. See also [docs/source-formatting.md](docs/source-formatting.md)
|
||||
|
||||
There is a project file for VS2022 for C++14, 17, 20, 23, and bash scripts that run the tests for C++11, 14, 17, 20, 23 under Linux with GCC and Clang.
|
||||
There are syntax-only check bash scripts that cover C++03, 11, 14, 17, 20, 23 under Linux with GCC and Clang.
|
||||
|
||||
99
docs/source-formatting.md
Normal file
99
docs/source-formatting.md
Normal file
@ -0,0 +1,99 @@
|
||||
# Source Formatting
|
||||
|
||||
This project uses **clang-format** (version 18) to enforce a consistent coding style
|
||||
for C and C++ source files. For convenience, **treefmt** is also configured as a
|
||||
single-command wrapper that discovers and formats every file in the tree.
|
||||
|
||||
---
|
||||
|
||||
## clang-format
|
||||
|
||||
### Configuration file
|
||||
|
||||
The formatting rules live in [`.clang-format`](../.clang-format) at the repository
|
||||
root. The style is based on **LLVM**.
|
||||
|
||||
See the `.clang-format` file itself for the complete list.
|
||||
|
||||
### Version requirement
|
||||
|
||||
clang-format **18** is required.
|
||||
The helper script [`scripts/clang-format-wrapper`](../scripts/clang-format-wrapper)
|
||||
automatically resolves the correct binary: it first looks for `clang-format-18` on
|
||||
`PATH`, then falls back to `clang-format` and verifies that its major version is 18.
|
||||
All other tooling in the repo calls this wrapper instead of `clang-format` directly.
|
||||
|
||||
### Running clang-format manually
|
||||
|
||||
Format every tracked source file in the repository:
|
||||
|
||||
```bash
|
||||
git ls-files -z \
|
||||
'*.c' '*.cc' '*.cpp' \
|
||||
'*.h' '*.hh' '*.hpp' \
|
||||
':(exclude)include/etl/generators/*' | xargs -0 scripts/clang-format-wrapper -i --verbose --style=file
|
||||
```
|
||||
|
||||
You can also format individual files directly:
|
||||
|
||||
```bash
|
||||
scripts/clang-format-wrapper -i --style=file path/to/file.cpp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## treefmt
|
||||
|
||||
[treefmt](https://treefmt.com) is a language-agnostic source-tree formatter.
|
||||
It reads a single configuration file and dispatches each file to the appropriate
|
||||
formatter. In this project, it delegates all C/C++ formatting to the same
|
||||
`clang-format-wrapper` described above.
|
||||
|
||||
In comparison to calling clang-format directly, it brings a significant speedup.
|
||||
|
||||
### Configuration file
|
||||
|
||||
The configuration lives in [`.treefmt.toml`](../.treefmt.toml) at the repository root.
|
||||
|
||||
### Installing treefmt
|
||||
|
||||
treefmt is a standalone Go binary. Install it with any of:
|
||||
|
||||
```bash
|
||||
# Using the official install script
|
||||
curl -fsSL https://raw.githubusercontent.com/numtide/treefmt/main/install.sh | bash
|
||||
|
||||
# Or via Homebrew
|
||||
brew install treefmt
|
||||
|
||||
# Or via Nix
|
||||
nix profile install nixpkgs#treefmt2
|
||||
```
|
||||
|
||||
See the [treefmt documentation](https://treefmt.com) for more options.
|
||||
|
||||
### Running treefmt
|
||||
|
||||
From the repository root:
|
||||
|
||||
```bash
|
||||
# Format everything
|
||||
treefmt
|
||||
|
||||
# Check formatting without modifying files (useful in CI)
|
||||
treefmt --fail-on-change
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Excluded paths
|
||||
|
||||
`.treefmt.toml` excludes generated files under
|
||||
`include/etl/generators/`. Do **not** format those files manually via clang-format or treefmt.
|
||||
|
||||
## Pre-commit
|
||||
|
||||
Before submitting a PR / contribution, run `treefmt --fail-on-change` to catch
|
||||
unformatted code before merge.
|
||||
|
||||
Alternatively, a plain `treefmt` automatically fixes any issues.
|
||||
@ -34,16 +34,43 @@ SOFTWARE.
|
||||
#include "platform.h"
|
||||
#include "type_traits.h"
|
||||
#include "integral_limits.h"
|
||||
#include "error_handler.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
namespace private_absolute
|
||||
{
|
||||
//*************************************************************************
|
||||
// Non-constexpr function that is never called for valid inputs.
|
||||
// If reached during constant evaluation, the compiler emits an error
|
||||
// because it's not constexpr.
|
||||
// At runtime, triggers the ETL assert handler.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
inline T signed_min_error()
|
||||
{
|
||||
ETL_ASSERT_FAIL(ETL_ERROR_GENERIC("absolute value of minimum signed integer is undefined"));
|
||||
return T(0);
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
// For signed types.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR
|
||||
typename etl::enable_if<etl::is_signed<T>::value, T>::type
|
||||
ETL_CONSTEXPR
|
||||
typename etl::enable_if<etl::is_signed<T>::value && etl::is_integral<T>::value, T>::type
|
||||
absolute(T value)
|
||||
{
|
||||
return (value == etl::integral_limits<T>::min) ? etl::private_absolute::signed_min_error<T>()
|
||||
: (value < T(0)) ? -value : value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR
|
||||
typename etl::enable_if<etl::is_signed<T>::value && !etl::is_integral<T>::value, T>::type
|
||||
absolute(T value) ETL_NOEXCEPT
|
||||
{
|
||||
return (value < T(0)) ? -value : value;
|
||||
|
||||
@ -34,7 +34,7 @@ SOFTWARE.
|
||||
#define ETL_ALGORITHM_INCLUDED
|
||||
|
||||
///\defgroup algorithm algorithm
|
||||
/// Including reverse engineered algorithms from C++ 0x11, 0x14, 0x17
|
||||
/// Including reverse engineered algorithms from C++11, 14, 17
|
||||
/// Additional new variants of certain algorithms.
|
||||
///\ingroup utilities
|
||||
|
||||
@ -507,6 +507,7 @@ namespace etl
|
||||
//***************************************************************************
|
||||
template <typename TIterator, typename T, typename Compare>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
bool binary_search(TIterator first, TIterator last, const T& value, Compare compare)
|
||||
{
|
||||
first = etl::lower_bound(first, last, value, compare);
|
||||
@ -516,6 +517,7 @@ namespace etl
|
||||
|
||||
template <typename TIterator, typename T>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
bool binary_search(TIterator first, TIterator last, const T& value)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
|
||||
@ -949,7 +951,7 @@ namespace etl
|
||||
{
|
||||
// Push Heap Helper
|
||||
template <typename TIterator, typename TDistance, typename TValue, typename TCompare>
|
||||
void push_heap(TIterator first, TDistance value_index, TDistance top_index, TValue value, TCompare compare)
|
||||
ETL_CONSTEXPR14 void push_heap(TIterator first, TDistance value_index, TDistance top_index, TValue value, TCompare compare)
|
||||
{
|
||||
TDistance parent = (value_index - 1) / 2;
|
||||
|
||||
@ -965,7 +967,7 @@ namespace etl
|
||||
|
||||
// Adjust Heap Helper
|
||||
template <typename TIterator, typename TDistance, typename TValue, typename TCompare>
|
||||
void adjust_heap(TIterator first, TDistance value_index, TDistance length, TValue value, TCompare compare)
|
||||
ETL_CONSTEXPR14 void adjust_heap(TIterator first, TDistance value_index, TDistance length, TValue value, TCompare compare)
|
||||
{
|
||||
TDistance top_index = value_index;
|
||||
TDistance child2nd = (2 * value_index) + 2;
|
||||
@ -993,7 +995,7 @@ namespace etl
|
||||
|
||||
// Is Heap Helper
|
||||
template <typename TIterator, typename TDistance, typename TCompare>
|
||||
bool is_heap(const TIterator first, const TDistance n, TCompare compare)
|
||||
ETL_CONSTEXPR14 bool is_heap(const TIterator first, const TDistance n, TCompare compare)
|
||||
{
|
||||
TDistance parent = 0;
|
||||
|
||||
@ -1016,6 +1018,7 @@ namespace etl
|
||||
|
||||
// Pop Heap
|
||||
template <typename TIterator, typename TCompare>
|
||||
ETL_CONSTEXPR14
|
||||
void pop_heap(TIterator first, TIterator last, TCompare compare)
|
||||
{
|
||||
typedef typename etl::iterator_traits<TIterator>::value_type value_t;
|
||||
@ -1029,6 +1032,7 @@ namespace etl
|
||||
|
||||
// Pop Heap
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
void pop_heap(TIterator first, TIterator last)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
|
||||
@ -1038,6 +1042,7 @@ namespace etl
|
||||
|
||||
// Push Heap
|
||||
template <typename TIterator, typename TCompare>
|
||||
ETL_CONSTEXPR14
|
||||
void push_heap(TIterator first, TIterator last, TCompare compare)
|
||||
{
|
||||
typedef typename etl::iterator_traits<TIterator>::difference_type difference_t;
|
||||
@ -1048,6 +1053,7 @@ namespace etl
|
||||
|
||||
// Push Heap
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
void push_heap(TIterator first, TIterator last)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
|
||||
@ -1057,6 +1063,7 @@ namespace etl
|
||||
|
||||
// Make Heap
|
||||
template <typename TIterator, typename TCompare>
|
||||
ETL_CONSTEXPR14
|
||||
void make_heap(TIterator first, TIterator last, TCompare compare)
|
||||
{
|
||||
typedef typename etl::iterator_traits<TIterator>::difference_type difference_t;
|
||||
@ -1084,6 +1091,7 @@ namespace etl
|
||||
|
||||
// Make Heap
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
void make_heap(TIterator first, TIterator last)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
|
||||
@ -1094,6 +1102,7 @@ namespace etl
|
||||
// Is Heap
|
||||
template <typename TIterator>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
bool is_heap(TIterator first, TIterator last)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
|
||||
@ -1104,6 +1113,7 @@ namespace etl
|
||||
// Is Heap
|
||||
template <typename TIterator, typename TCompare>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
bool is_heap(TIterator first, TIterator last, TCompare compare)
|
||||
{
|
||||
return private_heap::is_heap(first, last - first, compare);
|
||||
@ -1111,6 +1121,7 @@ namespace etl
|
||||
|
||||
// Sort Heap
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
void sort_heap(TIterator first, TIterator last)
|
||||
{
|
||||
while (first != last)
|
||||
@ -1122,6 +1133,7 @@ namespace etl
|
||||
|
||||
// Sort Heap
|
||||
template <typename TIterator, typename TCompare>
|
||||
ETL_CONSTEXPR14
|
||||
void sort_heap(TIterator first, TIterator last, TCompare compare)
|
||||
{
|
||||
while (first != last)
|
||||
@ -1131,6 +1143,119 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// partial_sort
|
||||
///\ingroup algorithm
|
||||
///<a href="http://en.cppreference.com/w/cpp/algorithm/partial_sort"></a>
|
||||
//***************************************************************************
|
||||
template <typename TIterator, typename TCompare>
|
||||
ETL_CONSTEXPR14
|
||||
void partial_sort(TIterator first, TIterator middle, TIterator last, TCompare compare)
|
||||
{
|
||||
if (first == middle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
typedef typename etl::iterator_traits<TIterator>::value_type value_t;
|
||||
typedef typename etl::iterator_traits<TIterator>::difference_type difference_t;
|
||||
|
||||
etl::make_heap(first, middle, compare);
|
||||
|
||||
for (TIterator i = middle; i != last; ++i)
|
||||
{
|
||||
if (compare(*i, *first))
|
||||
{
|
||||
value_t value = ETL_MOVE(*i);
|
||||
*i = ETL_MOVE(*first);
|
||||
|
||||
private_heap::adjust_heap(first, difference_t(0), difference_t(middle - first), ETL_MOVE(value), compare);
|
||||
}
|
||||
}
|
||||
|
||||
etl::sort_heap(first, middle, compare);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// partial_sort
|
||||
///\ingroup algorithm
|
||||
///<a href="http://en.cppreference.com/w/cpp/algorithm/partial_sort"></a>
|
||||
//***************************************************************************
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
void partial_sort(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
|
||||
|
||||
etl::partial_sort(first, middle, last, compare());
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// partial_sort_copy
|
||||
///\ingroup algorithm
|
||||
///<a href="http://en.cppreference.com/w/cpp/algorithm/partial_sort_copy"></a>
|
||||
//***************************************************************************
|
||||
template <typename TInputIterator, typename TRandomAccessIterator, typename TCompare>
|
||||
ETL_CONSTEXPR14
|
||||
TRandomAccessIterator partial_sort_copy(TInputIterator first,
|
||||
TInputIterator last,
|
||||
TRandomAccessIterator d_first,
|
||||
TRandomAccessIterator d_last,
|
||||
TCompare compare)
|
||||
{
|
||||
typedef typename etl::iterator_traits<TRandomAccessIterator>::value_type value_t;
|
||||
typedef typename etl::iterator_traits<TRandomAccessIterator>::difference_type difference_t;
|
||||
|
||||
TRandomAccessIterator result = d_first;
|
||||
|
||||
// Fill the destination range
|
||||
while ((first != last) && (result != d_last))
|
||||
{
|
||||
*result = *first;
|
||||
++result;
|
||||
++first;
|
||||
}
|
||||
|
||||
if (result == d_first)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Build a max-heap over the destination range
|
||||
etl::make_heap(d_first, result, compare);
|
||||
|
||||
// Process remaining input elements
|
||||
for (TInputIterator i = first; i != last; ++i)
|
||||
{
|
||||
if (compare(*i, *d_first))
|
||||
{
|
||||
value_t value = *i;
|
||||
private_heap::adjust_heap(d_first, difference_t(0), difference_t(result - d_first), ETL_MOVE(value), compare);
|
||||
}
|
||||
}
|
||||
|
||||
etl::sort_heap(d_first, result, compare);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// partial_sort_copy
|
||||
///\ingroup algorithm
|
||||
///<a href="http://en.cppreference.com/w/cpp/algorithm/partial_sort_copy"></a>
|
||||
//***************************************************************************
|
||||
template <typename TInputIterator, typename TRandomAccessIterator>
|
||||
ETL_CONSTEXPR14
|
||||
TRandomAccessIterator partial_sort_copy(TInputIterator first,
|
||||
TInputIterator last,
|
||||
TRandomAccessIterator d_first,
|
||||
TRandomAccessIterator d_last)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TRandomAccessIterator>::value_type> compare;
|
||||
|
||||
return etl::partial_sort_copy(first, last, d_first, d_last, compare());
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
// Search
|
||||
//***************************************************************************
|
||||
@ -1185,7 +1310,6 @@ namespace etl
|
||||
//***************************************************************************
|
||||
namespace private_algorithm
|
||||
{
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************
|
||||
// For random access iterators
|
||||
template <typename TIterator>
|
||||
@ -1193,27 +1317,32 @@ namespace etl
|
||||
typename etl::enable_if<etl::is_random_access_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
if (first == middle)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
if (middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
typedef typename etl::iterator_traits<TIterator>::value_type value_type;
|
||||
typedef typename etl::iterator_traits<TIterator>::difference_type difference_type;
|
||||
|
||||
int n = last - first;
|
||||
int m = middle - first;
|
||||
int gcd_nm = (n == 0 || m == 0) ? n + m : etl::gcd(n, m);
|
||||
|
||||
difference_type n = last - first;
|
||||
difference_type m = middle - first;
|
||||
difference_type gcd_nm = (n == 0 || m == 0) ? n + m : etl::gcd(n, m);
|
||||
TIterator result = first + (last - middle);
|
||||
|
||||
for (int i = 0; i < gcd_nm; i++)
|
||||
for (difference_type i = 0; i < gcd_nm; i++)
|
||||
{
|
||||
value_type temp = ETL_MOVE(*(first + i));
|
||||
int j = i;
|
||||
difference_type j = i;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int k = j + m;
|
||||
difference_type k = j + m;
|
||||
|
||||
if (k >= n)
|
||||
{
|
||||
@ -1234,56 +1363,6 @@ namespace etl
|
||||
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
//*********************************
|
||||
// For random access iterators
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_random_access_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
typedef typename etl::iterator_traits<TIterator>::value_type value_type;
|
||||
|
||||
int n = last - first;
|
||||
int m = middle - first;
|
||||
int gcd_nm = (n == 0 || m == 0) ? n + m : etl::gcd(n, m);
|
||||
|
||||
TIterator result = first + (last - middle);
|
||||
|
||||
for (int i = 0; i < gcd_nm; i++)
|
||||
{
|
||||
value_type temp = *(first + i);
|
||||
int j = i;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int k = j + m;
|
||||
|
||||
if (k >= n)
|
||||
{
|
||||
k = k - n;
|
||||
}
|
||||
|
||||
if (k == i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*(first + j) = *(first + k);
|
||||
j = k;
|
||||
}
|
||||
|
||||
*(first + j) = temp;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************
|
||||
// For bidirectional iterators
|
||||
@ -1292,7 +1371,12 @@ namespace etl
|
||||
typename etl::enable_if<etl::is_bidirectional_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
if (first == middle)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
if (middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
@ -1314,7 +1398,12 @@ namespace etl
|
||||
typename etl::enable_if<etl::is_forward_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
if (first == middle)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
if (middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
@ -1390,26 +1479,29 @@ namespace etl
|
||||
ETL_CONSTEXPR14
|
||||
TIterator rotate(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
if (middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
if (etl::next(first) == middle)
|
||||
{
|
||||
return private_algorithm::rotate_left_by_one(first, last);
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP20
|
||||
if (etl::next(middle) == last)
|
||||
{
|
||||
#if ETL_USING_CPP20
|
||||
if ETL_IF_CONSTEXPR(etl::is_forward_iterator<TIterator>::value)
|
||||
{
|
||||
return private_algorithm::rotate_general(first, middle, last);
|
||||
}
|
||||
else
|
||||
if ETL_IF_CONSTEXPR(etl::is_bidirectional_iterator_concept<TIterator>::value)
|
||||
{
|
||||
return private_algorithm::rotate_right_by_one(first, last);
|
||||
}
|
||||
#else
|
||||
return private_algorithm::rotate_general(first, middle, last);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return private_algorithm::rotate_general(first, middle, last);
|
||||
}
|
||||
@ -1641,35 +1733,6 @@ namespace etl
|
||||
return compare(b, a) ? ETL_OR_STD::pair<const T&, const T&>(b, a) : ETL_OR_STD::pair<const T&, const T&>(a, b);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// is_sorted_until
|
||||
///\ingroup algorithm
|
||||
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted_until"></a>
|
||||
//***************************************************************************
|
||||
template <typename TIterator>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
TIterator is_sorted_until(TIterator begin,
|
||||
TIterator end)
|
||||
{
|
||||
if (begin != end)
|
||||
{
|
||||
TIterator next = begin;
|
||||
|
||||
while (++next != end)
|
||||
{
|
||||
if (*next < *begin)
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// is_sorted_until
|
||||
///\ingroup algorithm
|
||||
@ -1700,6 +1763,22 @@ namespace etl
|
||||
return end;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// is_sorted_until
|
||||
///\ingroup algorithm
|
||||
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted_until"></a>
|
||||
//***************************************************************************
|
||||
template <typename TIterator>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
TIterator is_sorted_until(TIterator begin,
|
||||
TIterator end)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
|
||||
|
||||
return etl::is_sorted_until(begin, end, compare());
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// is_sorted
|
||||
///\ingroup algorithm
|
||||
@ -1768,22 +1847,9 @@ namespace etl
|
||||
TIterator is_unique_sorted_until(TIterator begin,
|
||||
TIterator end)
|
||||
{
|
||||
if (begin != end)
|
||||
{
|
||||
TIterator next = begin;
|
||||
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
|
||||
|
||||
while (++next != end)
|
||||
{
|
||||
if (!(*begin < *next))
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
return end;
|
||||
return etl::is_unique_sorted_until(begin, end, compare());
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
@ -1838,6 +1904,51 @@ namespace etl
|
||||
return end;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// adjacent_find
|
||||
///\ingroup algorithm
|
||||
///<a href="http://en.cppreference.com/w/cpp/algorithm/adjacent_find"></a>
|
||||
//***************************************************************************
|
||||
template <typename TIterator, typename TBinaryPredicate>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
TIterator adjacent_find(TIterator first, TIterator last, TBinaryPredicate predicate)
|
||||
{
|
||||
if (first != last)
|
||||
{
|
||||
TIterator next = first;
|
||||
++next;
|
||||
|
||||
while (next != last)
|
||||
{
|
||||
if (predicate(*first, *next))
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
++first;
|
||||
++next;
|
||||
}
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// adjacent_find
|
||||
///\ingroup algorithm
|
||||
///<a href="http://en.cppreference.com/w/cpp/algorithm/adjacent_find"></a>
|
||||
//***************************************************************************
|
||||
template <typename TIterator>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
TIterator adjacent_find(TIterator first, TIterator last)
|
||||
{
|
||||
typedef etl::equal_to<typename etl::iterator_traits<TIterator>::value_type> predicate;
|
||||
|
||||
return etl::adjacent_find(first, last, predicate());
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// is_permutation
|
||||
///\ingroup algorithm
|
||||
@ -1896,9 +2007,9 @@ namespace etl
|
||||
{
|
||||
if (i == etl::find_if(begin1, i, etl::bind1st(predicate, *i)))
|
||||
{
|
||||
size_t n = etl::count(begin2, end2, *i);
|
||||
size_t n = etl::count_if(begin2, end2, etl::bind1st(predicate, *i));
|
||||
|
||||
if (n == 0 || size_t(etl::count(i, end1, *i)) != n)
|
||||
if (n == 0 || size_t(etl::count_if(i, end1, etl::bind1st(predicate, *i))) != n)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -1922,18 +2033,20 @@ namespace etl
|
||||
TIterator2 begin2,
|
||||
TIterator2 end2)
|
||||
{
|
||||
if (begin1 != end1)
|
||||
if (etl::distance(begin1, end1) != etl::distance(begin2, end2))
|
||||
{
|
||||
for (TIterator1 i = begin1; i != end1; ++i)
|
||||
{
|
||||
if (i == etl::find(begin1, i, *i))
|
||||
{
|
||||
size_t n = etl::count(begin2, end2, *i);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (n == 0 || size_t(etl::count(i, end1, *i)) != n)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (TIterator1 i = begin1; i != end1; ++i)
|
||||
{
|
||||
if (i == etl::find(begin1, i, *i))
|
||||
{
|
||||
size_t n = etl::count(begin2, end2, *i);
|
||||
|
||||
if (n == 0 || size_t(etl::count(i, end1, *i)) != n)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1948,24 +2061,27 @@ namespace etl
|
||||
//***************************************************************************
|
||||
template <typename TIterator1, typename TIterator2, typename TBinaryPredicate>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
bool is_permutation(TIterator1 begin1,
|
||||
TIterator1 end1,
|
||||
TIterator2 begin2,
|
||||
TIterator2 end2,
|
||||
TBinaryPredicate predicate)
|
||||
{
|
||||
if (begin1 != end1)
|
||||
if (etl::distance(begin1, end1) != etl::distance(begin2, end2))
|
||||
{
|
||||
for (TIterator1 i = begin1; i != end1; ++i)
|
||||
{
|
||||
if (i == etl::find_if(begin1, i, etl::bind1st(predicate, *i)))
|
||||
{
|
||||
size_t n = etl::count(begin2, end2, *i);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (n == 0 || size_t(etl::count(i, end1, *i)) != n)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (TIterator1 i = begin1; i != end1; ++i)
|
||||
{
|
||||
if (i == etl::find_if(begin1, i, etl::bind1st(predicate, *i)))
|
||||
{
|
||||
size_t n = etl::count_if(begin2, end2, etl::bind1st(predicate, *i));
|
||||
|
||||
if (n == 0 || size_t(etl::count_if(i, end1, etl::bind1st(predicate, *i))) != n)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2020,14 +2136,22 @@ namespace etl
|
||||
TIterator end,
|
||||
TUnaryPredicate predicate)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
if (!predicate(*begin))
|
||||
{
|
||||
return begin;
|
||||
}
|
||||
typedef typename etl::iterator_traits<TIterator>::difference_type difference_t;
|
||||
|
||||
++begin;
|
||||
// binary search on a partitioned range
|
||||
for (difference_t length = etl::distance(begin, end); 0 < length; )
|
||||
{
|
||||
difference_t half = length / 2;
|
||||
TIterator middle = etl::next(begin, half);
|
||||
if (predicate(*middle))
|
||||
{
|
||||
begin = etl::next(middle);
|
||||
length -= (half + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = half;
|
||||
}
|
||||
}
|
||||
|
||||
return begin;
|
||||
@ -2344,6 +2468,253 @@ namespace etl
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// unique
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/unique
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
TIterator unique(TIterator first, TIterator last)
|
||||
{
|
||||
if (first == last)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
TIterator result = first;
|
||||
|
||||
while (++first != last)
|
||||
{
|
||||
if (!(*result == *first) && (++result != first))
|
||||
{
|
||||
*result = ETL_MOVE(*first);
|
||||
}
|
||||
}
|
||||
|
||||
return ++result;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// unique
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/unique
|
||||
/// predicate overload to determine equality.
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TIterator, typename TBinaryPredicate>
|
||||
ETL_CONSTEXPR14
|
||||
TIterator unique(TIterator first, TIterator last, TBinaryPredicate predicate)
|
||||
{
|
||||
if (first == last)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
TIterator result = first;
|
||||
|
||||
while (++first != last)
|
||||
{
|
||||
if (!predicate(*result, *first) && (++result != first))
|
||||
{
|
||||
*result = ETL_MOVE(*first);
|
||||
}
|
||||
}
|
||||
|
||||
return ++result;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// unique_copy
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/unique_copy
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TInputIterator, typename TOutputIterator>
|
||||
ETL_CONSTEXPR14
|
||||
TOutputIterator unique_copy(TInputIterator first,
|
||||
TInputIterator last,
|
||||
TOutputIterator d_first)
|
||||
{
|
||||
if (first == last)
|
||||
{
|
||||
return d_first;
|
||||
}
|
||||
|
||||
typename etl::iterator_traits<TInputIterator>::value_type prev = *first;
|
||||
*d_first = prev;
|
||||
|
||||
while (++first != last)
|
||||
{
|
||||
if (!(prev == *first))
|
||||
{
|
||||
prev = *first;
|
||||
*(++d_first) = prev;
|
||||
}
|
||||
}
|
||||
|
||||
return ++d_first;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// unique_copy
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/unique_copy
|
||||
/// predicate overload to determine equality.
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TInputIterator, typename TOutputIterator, typename TBinaryPredicate>
|
||||
ETL_CONSTEXPR14
|
||||
TOutputIterator unique_copy(TInputIterator first,
|
||||
TInputIterator last,
|
||||
TOutputIterator d_first,
|
||||
TBinaryPredicate predicate)
|
||||
{
|
||||
if (first == last)
|
||||
{
|
||||
return d_first;
|
||||
}
|
||||
|
||||
typename etl::iterator_traits<TInputIterator>::value_type prev = *first;
|
||||
*d_first = prev;
|
||||
|
||||
while (++first != last)
|
||||
{
|
||||
if (!predicate(prev, *first))
|
||||
{
|
||||
prev = *first;
|
||||
*(++d_first) = prev;
|
||||
}
|
||||
}
|
||||
|
||||
return ++d_first;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// merge
|
||||
/// Merges two sorted ranges into one sorted range.
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/merge
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TInputIterator1, typename TInputIterator2, typename TOutputIterator, typename TCompare>
|
||||
ETL_CONSTEXPR14
|
||||
TOutputIterator merge(TInputIterator1 first1, TInputIterator1 last1,
|
||||
TInputIterator2 first2, TInputIterator2 last2,
|
||||
TOutputIterator d_first,
|
||||
TCompare compare)
|
||||
{
|
||||
while ((first1 != last1) && (first2 != last2))
|
||||
{
|
||||
if (compare(*first2, *first1))
|
||||
{
|
||||
*d_first = *first2;
|
||||
++first2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d_first = *first1;
|
||||
++first1;
|
||||
}
|
||||
++d_first;
|
||||
}
|
||||
|
||||
d_first = etl::copy(first1, last1, d_first);
|
||||
d_first = etl::copy(first2, last2, d_first);
|
||||
|
||||
return d_first;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// merge
|
||||
/// Merges two sorted ranges into one sorted range.
|
||||
/// Uses operator< for comparison.
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/merge
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TInputIterator1, typename TInputIterator2, typename TOutputIterator>
|
||||
ETL_CONSTEXPR14
|
||||
TOutputIterator merge(TInputIterator1 first1, TInputIterator1 last1,
|
||||
TInputIterator2 first2, TInputIterator2 last2,
|
||||
TOutputIterator d_first)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TInputIterator1>::value_type> compare;
|
||||
|
||||
return etl::merge(first1, last1, first2, last2, d_first, compare());
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// inplace_merge
|
||||
/// Merges two consecutive sorted ranges [first, middle) and [middle, last)
|
||||
/// into one sorted range [first, last) in-place.
|
||||
/// Uses an iterative rotate-based algorithm that requires no additional
|
||||
/// memory, no recursion and no explicit stack, making it safe for deeply
|
||||
/// embedded targets with constrained stack sizes.
|
||||
/// Complexity: O(N log N) comparisons, O(N log N) element moves.
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/inplace_merge
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TBidirectionalIterator, typename TCompare>
|
||||
void inplace_merge(TBidirectionalIterator first,
|
||||
TBidirectionalIterator middle,
|
||||
TBidirectionalIterator last,
|
||||
TCompare compare)
|
||||
{
|
||||
typedef typename etl::iterator_traits<TBidirectionalIterator>::difference_type difference_type;
|
||||
|
||||
difference_type len1 = etl::distance(first, middle);
|
||||
difference_type len2 = etl::distance(middle, last);
|
||||
|
||||
while ((len1 != 0) && (len2 != 0))
|
||||
{
|
||||
// Find where the first element of the right half belongs in the left half.
|
||||
// All elements in [first, cut1) are <= *middle, so they are already in place.
|
||||
TBidirectionalIterator cut1 = etl::upper_bound(first, middle, *middle, compare);
|
||||
difference_type prefix = etl::distance(first, cut1);
|
||||
len1 -= prefix;
|
||||
|
||||
// If the entire left half is <= *middle, we are done.
|
||||
if (len1 == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Advance first past the already-placed prefix.
|
||||
first = cut1;
|
||||
|
||||
// Find where the first element of the (remaining) left half belongs in
|
||||
// the right half. All elements in [middle, cut2) are < *first, so they
|
||||
// need to be moved before *first.
|
||||
TBidirectionalIterator cut2 = etl::lower_bound(middle, last, *first, compare);
|
||||
difference_type run = etl::distance(middle, cut2);
|
||||
len2 -= run;
|
||||
|
||||
// Rotate the block [first, middle, cut2) so that [middle, cut2) moves
|
||||
// before [first, middle). After the rotate the elements from
|
||||
// [middle, cut2) (length = run) now occupy [first, first + run) and
|
||||
// are in their final position.
|
||||
etl::rotate(first, middle, cut2);
|
||||
|
||||
// Advance past the block we just placed.
|
||||
etl::advance(first, run);
|
||||
middle = cut2;
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// inplace_merge
|
||||
/// Merges two consecutive sorted ranges [first, middle) and [middle, last)
|
||||
/// into one sorted range [first, last) in-place.
|
||||
/// Uses operator< for comparison.
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/inplace_merge
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TBidirectionalIterator>
|
||||
void inplace_merge(TBidirectionalIterator first,
|
||||
TBidirectionalIterator middle,
|
||||
TBidirectionalIterator last)
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TBidirectionalIterator>::value_type> compare;
|
||||
|
||||
etl::inplace_merge(first, middle, last, compare());
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
@ -3140,6 +3511,11 @@ namespace etl
|
||||
ETL_CONSTEXPR20
|
||||
void selection_sort(TIterator first, TIterator last, TCompare compare)
|
||||
{
|
||||
if (first == last)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TIterator min;
|
||||
const TIterator ilast = private_algorithm::get_before_last(first, last);
|
||||
const TIterator jlast = last;
|
||||
@ -3160,7 +3536,10 @@ namespace etl
|
||||
}
|
||||
|
||||
using ETL_OR_STD::swap; // Allow ADL
|
||||
swap(*i, *min);
|
||||
if (min != i)
|
||||
{
|
||||
swap(*i, *min);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3184,11 +3563,7 @@ namespace etl
|
||||
ETL_CONSTEXPR14
|
||||
void heap_sort(TIterator first, TIterator last, TCompare compare)
|
||||
{
|
||||
if (!etl::is_heap(first, last, compare))
|
||||
{
|
||||
etl::make_heap(first, last, compare);
|
||||
}
|
||||
|
||||
etl::make_heap(first, last, compare);
|
||||
etl::sort_heap(first, last, compare);
|
||||
}
|
||||
|
||||
@ -3200,11 +3575,7 @@ namespace etl
|
||||
ETL_CONSTEXPR14
|
||||
void heap_sort(TIterator first, TIterator last)
|
||||
{
|
||||
if (!etl::is_heap(first, last))
|
||||
{
|
||||
etl::make_heap(first, last);
|
||||
}
|
||||
|
||||
etl::make_heap(first, last);
|
||||
etl::sort_heap(first, last);
|
||||
}
|
||||
|
||||
@ -3248,7 +3619,7 @@ namespace etl
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns the maximum value.
|
||||
/// Returns the minimum value.
|
||||
//***************************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename T>
|
||||
@ -3444,14 +3815,7 @@ namespace etl
|
||||
{
|
||||
typedef typename etl::iterator_traits<TIterator>::value_type value_type;
|
||||
|
||||
TIterator pivot = last; // Maybe find a better pivot choice?
|
||||
value_type pivot_value = *pivot;
|
||||
|
||||
// Swap the pivot with the last, if necessary.
|
||||
if (pivot != last)
|
||||
{
|
||||
swap(*pivot, *last);
|
||||
}
|
||||
value_type pivot_value = ETL_MOVE(*last);
|
||||
|
||||
TIterator i = first;
|
||||
|
||||
@ -3550,7 +3914,7 @@ namespace etl
|
||||
{
|
||||
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare_t;
|
||||
|
||||
nth_element(first, last, compare_t());
|
||||
nth_element(first, nth, last, compare_t());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ SOFTWARE.
|
||||
#include <stddef.h>
|
||||
|
||||
///\defgroup array array
|
||||
/// A replacement for std::array if you haven't got C++0x11.
|
||||
/// A replacement for std::array if you haven't got C++11.
|
||||
///\ingroup containers
|
||||
|
||||
namespace etl
|
||||
@ -81,7 +81,7 @@ namespace etl
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup array
|
||||
/// A replacement for std::array if you haven't got C++0x11.
|
||||
/// A replacement for std::array if you haven't got C++11.
|
||||
//***************************************************************************
|
||||
template <typename T, size_t SIZE_>
|
||||
class array
|
||||
@ -646,7 +646,7 @@ namespace etl
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup array
|
||||
/// A replacement for std::array if you haven't got C++0x11.
|
||||
/// A replacement for std::array if you haven't got C++11.
|
||||
/// Specialisation for zero sized array.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
@ -1105,7 +1105,7 @@ namespace etl
|
||||
#if ETL_USING_CPP17
|
||||
template <typename... T>
|
||||
array(T...) -> array<typename etl::common_type<T...>::type, sizeof...(T)>;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Make
|
||||
|
||||
@ -48,7 +48,9 @@ SOFTWARE.
|
||||
#include "variant.h"
|
||||
#include "visitor.h"
|
||||
|
||||
#if ETL_USING_FORMAT_FLOATING_POINT
|
||||
#include <cmath>
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
|
||||
@ -138,9 +140,11 @@ namespace etl
|
||||
unsigned int,
|
||||
long long int,
|
||||
unsigned long long int,
|
||||
#if ETL_USING_FORMAT_FLOATING_POINT
|
||||
float,
|
||||
double,
|
||||
long double,
|
||||
#endif
|
||||
const char*,
|
||||
etl::string_view,
|
||||
const void*
|
||||
@ -302,6 +306,7 @@ namespace etl
|
||||
{
|
||||
}
|
||||
|
||||
#if ETL_USING_FORMAT_FLOATING_POINT
|
||||
basic_format_arg(const float v)
|
||||
: data(v)
|
||||
{
|
||||
@ -316,6 +321,7 @@ namespace etl
|
||||
: data(v)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
basic_format_arg(const etl::string_view v)
|
||||
: data(v)
|
||||
@ -1039,6 +1045,7 @@ namespace etl
|
||||
format_plain_num(it, value, spec, width);
|
||||
}
|
||||
|
||||
#if ETL_USING_FORMAT_FLOATING_POINT
|
||||
template<typename OutputIt, typename T>
|
||||
void format_floating_default(OutputIt& it, T value, const format_spec_t& spec)
|
||||
{
|
||||
@ -1214,6 +1221,7 @@ namespace etl
|
||||
private_format::format_sequence<OutputIt>(it, ".");
|
||||
private_format::format_plain_num<OutputIt, unsigned long long int>(it, fractional_int, spec, fractional_decimals);
|
||||
}
|
||||
#endif
|
||||
|
||||
class dummy_assign_to
|
||||
{
|
||||
@ -1336,6 +1344,7 @@ namespace etl
|
||||
size_t count;
|
||||
};
|
||||
|
||||
#if ETL_USING_FORMAT_FLOATING_POINT
|
||||
template<typename OutputIt, typename T>
|
||||
void format_floating_g(OutputIt& it, T value, const format_spec_t& spec)
|
||||
{
|
||||
@ -1409,6 +1418,7 @@ namespace etl
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class OutputIt>
|
||||
struct format_visitor
|
||||
@ -1490,6 +1500,7 @@ namespace etl
|
||||
return it;
|
||||
}
|
||||
|
||||
#if ETL_USING_FORMAT_FLOATING_POINT
|
||||
template<typename OutputIt, typename Float>
|
||||
typename format_context<OutputIt>::iterator format_aligned_floating(Float arg, format_context<OutputIt>& fmt_ctx)
|
||||
{
|
||||
@ -1534,6 +1545,7 @@ namespace etl
|
||||
private_format::fill<OutputIt>(it, suffix_size, fmt_ctx.format_spec.fill);
|
||||
return it;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename OutputIt>
|
||||
void format_string_view(OutputIt& it, etl::string_view arg, const format_spec_t& spec)
|
||||
@ -2072,6 +2084,7 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
#if ETL_USING_FORMAT_FLOATING_POINT
|
||||
template<>
|
||||
struct formatter<float>
|
||||
{
|
||||
@ -2119,6 +2132,7 @@ namespace etl
|
||||
return private_format::format_aligned_floating<OutputIt, long double>(arg, fmt_ctx);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct formatter<etl::string_view>
|
||||
|
||||
@ -62,6 +62,7 @@ SOFTWARE.
|
||||
#include "largest.h"
|
||||
#if ETL_USING_CPP11
|
||||
#include "tuple.h"
|
||||
#include "type_list.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
@ -83,14 +84,14 @@ namespace etl
|
||||
// For internal FSM use.
|
||||
typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
|
||||
|
||||
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||||
#if ETL_USING_CPP11 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++11 and above
|
||||
template <typename, typename, etl::fsm_state_id_t, typename...>
|
||||
class fsm_state;
|
||||
#else
|
||||
template <typename, typename, etl::fsm_state_id_t,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename>
|
||||
class fsm_state;
|
||||
#endif
|
||||
@ -195,7 +196,7 @@ namespace etl
|
||||
// Pass this whenever no state change is desired.
|
||||
// The highest unsigned value of fsm_state_id_t.
|
||||
static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
|
||||
|
||||
|
||||
// Pass this when this event also needs to be passed to the parent.
|
||||
static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
|
||||
|
||||
@ -213,15 +214,15 @@ namespace etl
|
||||
ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Self_Transition;
|
||||
|
||||
// Compile-time: TState::ID must equal its index in the type list (0..N-1)
|
||||
template <size_t Id, typename...> struct check_ids : etl::true_type
|
||||
template <size_t Id, typename...> struct check_ids : etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <size_t Id, typename TState0, typename... TRest>
|
||||
struct check_ids<Id, TState0, TRest...>
|
||||
: etl::integral_constant<bool, (TState0::STATE_ID == Id) && private_fsm::check_ids<Id + 1, TRest...>::value>
|
||||
: etl::integral_constant<bool, (TState0::STATE_ID == Id) && private_fsm::check_ids<Id + 1, TRest...>::value>
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// RAII detection mechanism to catch reentrant calls to methods that might
|
||||
@ -250,11 +251,11 @@ namespace etl
|
||||
{
|
||||
is_locked = false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// Reference to the flag signifying a lock on the state machine.
|
||||
bool& is_locked;
|
||||
|
||||
|
||||
// Copy & move semantics disabled since this is a guard.
|
||||
fsm_reentrancy_guard(fsm_reentrancy_guard const&) ETL_DELETE;
|
||||
fsm_reentrancy_guard& operator= (fsm_reentrancy_guard const&) ETL_DELETE;
|
||||
@ -272,7 +273,7 @@ namespace etl
|
||||
/// A class to store FSM states.
|
||||
//***************************************************************************
|
||||
template <typename... TStates>
|
||||
class fsm_state_pack
|
||||
class fsm_state_pack
|
||||
{
|
||||
public:
|
||||
|
||||
@ -294,18 +295,18 @@ namespace etl
|
||||
/// Gets a reference to the state.
|
||||
//*********************************
|
||||
template <typename TState>
|
||||
TState& get()
|
||||
{
|
||||
return etl::get<TState>(storage);
|
||||
TState& get()
|
||||
{
|
||||
return etl::get<TState>(storage);
|
||||
}
|
||||
|
||||
//*********************************
|
||||
/// Gets a const reference to the state.
|
||||
//*********************************
|
||||
template <typename TState>
|
||||
const TState& get() const
|
||||
{
|
||||
return etl::get<TState>(storage);
|
||||
const TState& get() const
|
||||
{
|
||||
return etl::get<TState>(storage);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -341,14 +342,14 @@ namespace etl
|
||||
using private_fsm::ifsm_state_helper<>::Pass_To_Parent;
|
||||
using private_fsm::ifsm_state_helper<>::Self_Transition;
|
||||
|
||||
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||||
#if ETL_USING_CPP11 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++11 and above
|
||||
template <typename, typename, etl::fsm_state_id_t, typename...>
|
||||
friend class fsm_state;
|
||||
#else
|
||||
template <typename, typename, etl::fsm_state_id_t,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename,
|
||||
typename, typename, typename, typename>
|
||||
friend class etl::fsm_state;
|
||||
#endif
|
||||
@ -560,7 +561,7 @@ namespace etl
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(message);
|
||||
|
||||
process_state_change(next_state_id);
|
||||
process_state_change(next_state_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -691,7 +692,7 @@ namespace etl
|
||||
p_state->on_exit_state();
|
||||
next_state_id = p_state->on_enter_state();
|
||||
}
|
||||
|
||||
|
||||
if (have_changed_state(next_state_id))
|
||||
{
|
||||
ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id());
|
||||
@ -722,17 +723,249 @@ namespace etl
|
||||
};
|
||||
|
||||
//*************************************************************************************************
|
||||
// For C++17 and above.
|
||||
// For C++11 and above.
|
||||
//*************************************************************************************************
|
||||
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||||
#if ETL_USING_CPP11 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++11 and above
|
||||
//***************************************************************************
|
||||
// The definition for all types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
class fsm_state : public ifsm_state
|
||||
{
|
||||
private:
|
||||
|
||||
using message_id_sequence = etl::index_sequence<TMessageTypes::ID...>;
|
||||
|
||||
public:
|
||||
|
||||
using message_types = etl::type_list<TMessageTypes...>;
|
||||
using sorted_message_types = etl::type_list_sort_t<message_types, etl::compare_message_id_less>;
|
||||
|
||||
static_assert(etl::type_list_is_unique<message_types>::value, "All TMessageTypes must be unique");
|
||||
static_assert(etl::type_list_all_of<message_types, etl::is_message_type>::value, "All TMessageTypes must satisfy the condition etl::is_message_type");
|
||||
static_assert(etl::index_sequence_is_unique<message_id_sequence>::value, "All message IDs must be unique");
|
||||
|
||||
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||||
|
||||
fsm_state()
|
||||
: ifsm_state(STATE_ID)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
~fsm_state()
|
||||
{
|
||||
}
|
||||
|
||||
TContext& get_fsm_context() const
|
||||
{
|
||||
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static constexpr size_t Number_Of_Messages = sizeof...(TMessageTypes);
|
||||
static constexpr etl::message_id_t Message_Id_Start = etl::type_list_type_at_index_t<sorted_message_types, 0>::ID;
|
||||
|
||||
static_assert(Number_Of_Messages > 0, "Zero messages");
|
||||
|
||||
//**********************************************
|
||||
// Checks that the message ids are contiguous.
|
||||
//**********************************************
|
||||
template <size_t Index, bool Last = (Index + 1U >= Number_Of_Messages)>
|
||||
struct contiguous_impl;
|
||||
|
||||
template <size_t Index>
|
||||
struct contiguous_impl<Index, true> : etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <size_t Index>
|
||||
struct contiguous_impl<Index, false>
|
||||
: etl::bool_constant<(etl::type_list_type_at_index_t<sorted_message_types, Index>::ID + 1U ==
|
||||
etl::type_list_type_at_index_t<sorted_message_types, Index + 1U>::ID) &&
|
||||
contiguous_impl<Index + 1U>::value>
|
||||
{
|
||||
|
||||
|
||||
};
|
||||
|
||||
// The message ids are contiguous if there are 0 or 1 message types, or if each message id is one greater than the previous message id.
|
||||
static constexpr bool Message_Ids_Are_Contiguous = (Number_Of_Messages <= 1U) ? true : contiguous_impl<0U>::value;
|
||||
|
||||
using handler_ptr = etl::fsm_state_id_t (*)(TDerived&, const etl::imessage&); ///< Pointer to a handler function that takes a reference to the derived class and a reference to the message.
|
||||
using message_dispatch_table_t = etl::array<handler_ptr, Number_Of_Messages>; ///< The dispatch table type. An array of handler pointers, one for each message type.
|
||||
using message_id_table_t = etl::array<etl::message_id_t, Number_Of_Messages>; ///< The message id table type. An array of message ids, one for each message type.
|
||||
|
||||
//********************************************
|
||||
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||||
{
|
||||
const etl::message_id_t id = message.get_message_id();
|
||||
|
||||
// The IDs are sorted, so an ID less than the first is not handled by this router.
|
||||
if (id >= Message_Id_Start)
|
||||
{
|
||||
const size_t index = get_dispatch_index_from_message_id(id);
|
||||
|
||||
// If the index is less than Number_Of_Messages, then we have a handler for this message type, so dispatch it.
|
||||
if (index < Number_Of_Messages)
|
||||
{
|
||||
const etl::fsm_state_id_t new_state_id = dispatch(message, index);
|
||||
|
||||
if (new_state_id != Pass_To_Parent)
|
||||
{
|
||||
return new_state_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "etl/private/diagnostic_array_bounds_push.h"
|
||||
// If we get here, then we don't have a handler for this message type, so pass it to the parent if we have one, otherwise call on_event_unknown.
|
||||
return (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Call for a single message type
|
||||
//**********************************************
|
||||
template <typename TMessage>
|
||||
static etl::fsm_state_id_t call_on_event(TDerived& derived, const imessage& msg)
|
||||
{
|
||||
return derived.on_event(static_cast<const TMessage&>(msg));
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Get the handler for a single message type at the index in the sorted type_list.
|
||||
// This will be called for each message type to generate the dispatch table.
|
||||
//**********************************************
|
||||
template <size_t Index>
|
||||
static constexpr handler_ptr get_message_handler()
|
||||
{
|
||||
return &call_on_event<etl::type_list_type_at_index_t<sorted_message_types, Index>>;
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Generate the dispatch table at compile time.
|
||||
// This will create an array of handler pointers, one for each message type.
|
||||
//**********************************************
|
||||
template <size_t... Indices>
|
||||
static constexpr message_dispatch_table_t make_message_dispatch_table(etl::index_sequence<Indices...>)
|
||||
{
|
||||
return message_dispatch_table_t{ { get_message_handler<Indices>()... } };
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Get the message id for a single message type at an index in the sorted type_list.
|
||||
// This will be called for each message type to generate the message id table.
|
||||
//**********************************************
|
||||
template <size_t Index>
|
||||
static constexpr etl::message_id_t get_message_id_from_index()
|
||||
{
|
||||
return etl::type_list_type_at_index_t<sorted_message_types, Index>::ID;
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Generate the message id table at compile time.
|
||||
// This will create an array of message ids, one for each message type.
|
||||
//**********************************************
|
||||
template <size_t... Indices>
|
||||
static constexpr message_id_table_t make_message_id_table(etl::index_sequence<Indices...>)
|
||||
{
|
||||
return message_id_table_t{ { get_message_id_from_index<Indices>()... } };
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Get the dispatch index for a message id.
|
||||
// This will be used at runtime to find the handler for a message id.
|
||||
// If the message ids are contiguous, we can calculate the index directly. If they are not contiguous, we need to do a binary search.
|
||||
// This will return Number_Of_Messages if the message id is not found.
|
||||
//**********************************************
|
||||
static size_t get_dispatch_index_from_message_id(etl::message_id_t id)
|
||||
{
|
||||
if ETL_IF_CONSTEXPR(Message_Ids_Are_Contiguous)
|
||||
{
|
||||
// The IDs are contiguous, so we can calculate the index directly.
|
||||
return static_cast<size_t>(id - Message_Id_Start);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The IDs are not contiguous, so we need to do a binary search.
|
||||
size_t left = 0;
|
||||
size_t right = Number_Of_Messages;
|
||||
|
||||
while (left < right)
|
||||
{
|
||||
size_t mid = (left + right) / 2;
|
||||
|
||||
if (message_id_table[mid] == id)
|
||||
{
|
||||
return mid;
|
||||
}
|
||||
else if (message_id_table[mid] < id)
|
||||
{
|
||||
left = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Number_Of_Messages; // Not found
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Dispatch the message to the appropriate handler based on the index in the dispatch table.
|
||||
//**********************************************
|
||||
etl::fsm_state_id_t dispatch(const etl::imessage& msg, size_t index)
|
||||
{
|
||||
return message_dispatch_table[index](static_cast<TDerived&>(*this), msg);
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// The dispatch table is generated at compile time. The dispatch table contains pointers to the on_receive handlers for each message type.
|
||||
//**********************************************
|
||||
static ETL_INLINE_VAR constexpr message_dispatch_table_t message_dispatch_table =
|
||||
etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::make_message_dispatch_table(etl::make_index_sequence<etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::Number_Of_Messages>{});
|
||||
|
||||
//**********************************************
|
||||
// The message id table is generated at compile time. The message id table contains the corresponding message ids for each message type.
|
||||
//**********************************************
|
||||
static ETL_INLINE_VAR constexpr message_id_table_t message_id_table =
|
||||
etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::make_message_id_table(etl::make_index_sequence<etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::Number_Of_Messages>{});
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11 && !ETL_USING_CPP17
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
constexpr const typename etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::message_dispatch_table_t
|
||||
etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::message_dispatch_table;
|
||||
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
constexpr const typename etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::message_id_table_t
|
||||
etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::message_id_table;
|
||||
#endif
|
||||
|
||||
/// Definition of STATE_ID
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
|
||||
|
||||
//***************************************************************************
|
||||
// The definition for no messages.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_> : public ifsm_state
|
||||
{
|
||||
private:
|
||||
|
||||
using message_id_sequence = etl::index_sequence<>;
|
||||
|
||||
public:
|
||||
|
||||
using message_types = etl::type_list<>;
|
||||
using sorted_message_types = etl::type_list<>;
|
||||
|
||||
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||||
|
||||
fsm_state()
|
||||
@ -753,59 +986,24 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
//********************************************
|
||||
struct result_t
|
||||
{
|
||||
bool was_handled;
|
||||
etl::fsm_state_id_t state_id;
|
||||
};
|
||||
|
||||
//********************************************
|
||||
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||||
{
|
||||
etl::fsm_state_id_t new_state_id;
|
||||
|
||||
const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
|
||||
|
||||
if (!was_handled || (new_state_id == Pass_To_Parent))
|
||||
{
|
||||
new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
|
||||
}
|
||||
|
||||
return new_state_id;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
template <typename TMessage>
|
||||
bool process_event_type(const etl::imessage& msg, etl::fsm_state_id_t& new_state_id)
|
||||
{
|
||||
if (TMessage::ID == msg.get_message_id())
|
||||
{
|
||||
new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const TMessage&>(msg));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
|
||||
}
|
||||
};
|
||||
|
||||
/// Definition of STATE_ID
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
|
||||
|
||||
#else
|
||||
//*************************************************************************************************
|
||||
// For C++14 and below.
|
||||
// For C++03 and below.
|
||||
//*************************************************************************************************
|
||||
//***************************************************************************
|
||||
// The definition for all 16 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
|
||||
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
|
||||
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
|
||||
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
|
||||
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
|
||||
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
|
||||
class fsm_state : public ifsm_state
|
||||
{
|
||||
@ -864,10 +1062,10 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 15 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
typename T13, typename T14, typename T15>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void> : public ifsm_state
|
||||
{
|
||||
@ -925,10 +1123,10 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 14 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
typename T13, typename T14>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, void, void> : public ifsm_state
|
||||
{
|
||||
@ -985,10 +1183,10 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 13 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
typename T13>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1044,9 +1242,9 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 12 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1101,9 +1299,9 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 11 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1157,9 +1355,9 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 10 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1212,9 +1410,9 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 9 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, void, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1266,8 +1464,8 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 8 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, void, void, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1318,8 +1516,8 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 7 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1369,8 +1567,8 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 6 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1419,8 +1617,8 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 5 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1468,7 +1666,7 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 4 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1515,7 +1713,7 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 3 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1561,7 +1759,7 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 2 message types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1606,7 +1804,7 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Specialisation for 1 message type.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_, T1, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||||
{
|
||||
@ -1680,10 +1878,10 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
typename T13, typename T14, typename T15, typename T16>
|
||||
ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::STATE_ID;
|
||||
#endif
|
||||
|
||||
@ -43,7 +43,7 @@ SOFTWARE.
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// A definition of reference_wrapper for those that don't have C++ 0x11 support.
|
||||
/// A definition of reference_wrapper for those that don't have C++11 support.
|
||||
///\ingroup reference
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
@ -224,9 +224,9 @@ namespace etl
|
||||
typedef int is_transparent;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(!(static_cast<T2&&>(rhs) < static_cast<T1&&>(lhs)))
|
||||
{
|
||||
return !(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs));
|
||||
return !(static_cast<T2&&>(rhs) < static_cast<T1&&>(lhs));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@ -250,7 +250,7 @@ namespace etl
|
||||
typedef int is_transparent;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T2&&>(rhs) < static_cast<T1&&>(lhs))
|
||||
{
|
||||
return static_cast<T2&&>(rhs) < static_cast<T1&&>(lhs);
|
||||
}
|
||||
@ -276,9 +276,9 @@ namespace etl
|
||||
typedef int is_transparent;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(!(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs)))
|
||||
{
|
||||
return static_cast<T1&&>(rhs) < static_cast<T2&&>(lhs);
|
||||
return !(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@ -303,7 +303,7 @@ namespace etl
|
||||
typedef int is_transparent;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) == static_cast<T2&&>(rhs))
|
||||
{
|
||||
return static_cast<T1&&>(lhs) == static_cast<T2&&>(rhs);
|
||||
}
|
||||
@ -329,7 +329,7 @@ namespace etl
|
||||
typedef int is_transparent;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
|
||||
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(!(static_cast<T1&&>(lhs) == static_cast<T2&&>(rhs)))
|
||||
{
|
||||
return !(static_cast<T1&&>(lhs) == static_cast<T2&&>(rhs));
|
||||
}
|
||||
|
||||
@ -74,6 +74,7 @@ cog.outl("//********************************************************************
|
||||
#include "largest.h"
|
||||
#if ETL_USING_CPP11
|
||||
#include "tuple.h"
|
||||
#include "type_list.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
@ -95,20 +96,20 @@ namespace etl
|
||||
// For internal FSM use.
|
||||
typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
|
||||
|
||||
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||||
#if ETL_USING_CPP11 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++11 and above
|
||||
template <typename, typename, etl::fsm_state_id_t, typename...>
|
||||
class fsm_state;
|
||||
#else
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("template <typename, typename, etl::fsm_state_id_t,")
|
||||
cog.out(" ")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("typename, ")
|
||||
cog.out(" typename,")
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename>")
|
||||
cog.out(" ")
|
||||
cog.outl(" typename>")
|
||||
cog.outl("class fsm_state;")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
@ -214,7 +215,7 @@ namespace etl
|
||||
// Pass this whenever no state change is desired.
|
||||
// The highest unsigned value of fsm_state_id_t.
|
||||
static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
|
||||
|
||||
|
||||
// Pass this when this event also needs to be passed to the parent.
|
||||
static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
|
||||
|
||||
@ -232,15 +233,15 @@ namespace etl
|
||||
ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Self_Transition;
|
||||
|
||||
// Compile-time: TState::ID must equal its index in the type list (0..N-1)
|
||||
template <size_t Id, typename...> struct check_ids : etl::true_type
|
||||
template <size_t Id, typename...> struct check_ids : etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <size_t Id, typename TState0, typename... TRest>
|
||||
struct check_ids<Id, TState0, TRest...>
|
||||
: etl::integral_constant<bool, (TState0::STATE_ID == Id) && private_fsm::check_ids<Id + 1, TRest...>::value>
|
||||
: etl::integral_constant<bool, (TState0::STATE_ID == Id) && private_fsm::check_ids<Id + 1, TRest...>::value>
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// RAII detection mechanism to catch reentrant calls to methods that might
|
||||
@ -269,11 +270,11 @@ namespace etl
|
||||
{
|
||||
is_locked = false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// Reference to the flag signifying a lock on the state machine.
|
||||
bool& is_locked;
|
||||
|
||||
|
||||
// Copy & move semantics disabled since this is a guard.
|
||||
fsm_reentrancy_guard(fsm_reentrancy_guard const&) ETL_DELETE;
|
||||
fsm_reentrancy_guard& operator= (fsm_reentrancy_guard const&) ETL_DELETE;
|
||||
@ -291,7 +292,7 @@ namespace etl
|
||||
/// A class to store FSM states.
|
||||
//***************************************************************************
|
||||
template <typename... TStates>
|
||||
class fsm_state_pack
|
||||
class fsm_state_pack
|
||||
{
|
||||
public:
|
||||
|
||||
@ -313,18 +314,18 @@ namespace etl
|
||||
/// Gets a reference to the state.
|
||||
//*********************************
|
||||
template <typename TState>
|
||||
TState& get()
|
||||
{
|
||||
return etl::get<TState>(storage);
|
||||
TState& get()
|
||||
{
|
||||
return etl::get<TState>(storage);
|
||||
}
|
||||
|
||||
//*********************************
|
||||
/// Gets a const reference to the state.
|
||||
//*********************************
|
||||
template <typename TState>
|
||||
const TState& get() const
|
||||
{
|
||||
return etl::get<TState>(storage);
|
||||
const TState& get() const
|
||||
{
|
||||
return etl::get<TState>(storage);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -360,20 +361,20 @@ namespace etl
|
||||
using private_fsm::ifsm_state_helper<>::Pass_To_Parent;
|
||||
using private_fsm::ifsm_state_helper<>::Self_Transition;
|
||||
|
||||
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||||
#if ETL_USING_CPP11 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++11 and above
|
||||
template <typename, typename, etl::fsm_state_id_t, typename...>
|
||||
friend class fsm_state;
|
||||
#else
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl(" template <typename, typename, etl::fsm_state_id_t,")
|
||||
cog.out(" ")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("typename, ")
|
||||
cog.out(" typename,")
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename>")
|
||||
cog.out(" ")
|
||||
cog.outl(" typename>")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
friend class etl::fsm_state;
|
||||
@ -586,7 +587,7 @@ namespace etl
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(message);
|
||||
|
||||
process_state_change(next_state_id);
|
||||
process_state_change(next_state_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -717,7 +718,7 @@ namespace etl
|
||||
p_state->on_exit_state();
|
||||
next_state_id = p_state->on_enter_state();
|
||||
}
|
||||
|
||||
|
||||
if (have_changed_state(next_state_id))
|
||||
{
|
||||
ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id());
|
||||
@ -748,17 +749,249 @@ namespace etl
|
||||
};
|
||||
|
||||
//*************************************************************************************************
|
||||
// For C++17 and above.
|
||||
// For C++11 and above.
|
||||
//*************************************************************************************************
|
||||
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||||
#if ETL_USING_CPP11 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++11 and above
|
||||
//***************************************************************************
|
||||
// The definition for all types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
class fsm_state : public ifsm_state
|
||||
{
|
||||
private:
|
||||
|
||||
using message_id_sequence = etl::index_sequence<TMessageTypes::ID...>;
|
||||
|
||||
public:
|
||||
|
||||
using message_types = etl::type_list<TMessageTypes...>;
|
||||
using sorted_message_types = etl::type_list_sort_t<message_types, etl::compare_message_id_less>;
|
||||
|
||||
static_assert(etl::type_list_is_unique<message_types>::value, "All TMessageTypes must be unique");
|
||||
static_assert(etl::type_list_all_of<message_types, etl::is_message_type>::value, "All TMessageTypes must satisfy the condition etl::is_message_type");
|
||||
static_assert(etl::index_sequence_is_unique<message_id_sequence>::value, "All message IDs must be unique");
|
||||
|
||||
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||||
|
||||
fsm_state()
|
||||
: ifsm_state(STATE_ID)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
~fsm_state()
|
||||
{
|
||||
}
|
||||
|
||||
TContext& get_fsm_context() const
|
||||
{
|
||||
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static constexpr size_t Number_Of_Messages = sizeof...(TMessageTypes);
|
||||
static constexpr etl::message_id_t Message_Id_Start = etl::type_list_type_at_index_t<sorted_message_types, 0>::ID;
|
||||
|
||||
static_assert(Number_Of_Messages > 0, "Zero messages");
|
||||
|
||||
//**********************************************
|
||||
// Checks that the message ids are contiguous.
|
||||
//**********************************************
|
||||
template <size_t Index, bool Last = (Index + 1U >= Number_Of_Messages)>
|
||||
struct contiguous_impl;
|
||||
|
||||
template <size_t Index>
|
||||
struct contiguous_impl<Index, true> : etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <size_t Index>
|
||||
struct contiguous_impl<Index, false>
|
||||
: etl::bool_constant<(etl::type_list_type_at_index_t<sorted_message_types, Index>::ID + 1U ==
|
||||
etl::type_list_type_at_index_t<sorted_message_types, Index + 1U>::ID) &&
|
||||
contiguous_impl<Index + 1U>::value>
|
||||
{
|
||||
|
||||
|
||||
};
|
||||
|
||||
// The message ids are contiguous if there are 0 or 1 message types, or if each message id is one greater than the previous message id.
|
||||
static constexpr bool Message_Ids_Are_Contiguous = (Number_Of_Messages <= 1U) ? true : contiguous_impl<0U>::value;
|
||||
|
||||
using handler_ptr = etl::fsm_state_id_t (*)(TDerived&, const etl::imessage&); ///< Pointer to a handler function that takes a reference to the derived class and a reference to the message.
|
||||
using message_dispatch_table_t = etl::array<handler_ptr, Number_Of_Messages>; ///< The dispatch table type. An array of handler pointers, one for each message type.
|
||||
using message_id_table_t = etl::array<etl::message_id_t, Number_Of_Messages>; ///< The message id table type. An array of message ids, one for each message type.
|
||||
|
||||
//********************************************
|
||||
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||||
{
|
||||
const etl::message_id_t id = message.get_message_id();
|
||||
|
||||
// The IDs are sorted, so an ID less than the first is not handled by this router.
|
||||
if (id >= Message_Id_Start)
|
||||
{
|
||||
const size_t index = get_dispatch_index_from_message_id(id);
|
||||
|
||||
// If the index is less than Number_Of_Messages, then we have a handler for this message type, so dispatch it.
|
||||
if (index < Number_Of_Messages)
|
||||
{
|
||||
const etl::fsm_state_id_t new_state_id = dispatch(message, index);
|
||||
|
||||
if (new_state_id != Pass_To_Parent)
|
||||
{
|
||||
return new_state_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "etl/private/diagnostic_array_bounds_push.h"
|
||||
// If we get here, then we don't have a handler for this message type, so pass it to the parent if we have one, otherwise call on_event_unknown.
|
||||
return (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Call for a single message type
|
||||
//**********************************************
|
||||
template <typename TMessage>
|
||||
static etl::fsm_state_id_t call_on_event(TDerived& derived, const imessage& msg)
|
||||
{
|
||||
return derived.on_event(static_cast<const TMessage&>(msg));
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Get the handler for a single message type at the index in the sorted type_list.
|
||||
// This will be called for each message type to generate the dispatch table.
|
||||
//**********************************************
|
||||
template <size_t Index>
|
||||
static constexpr handler_ptr get_message_handler()
|
||||
{
|
||||
return &call_on_event<etl::type_list_type_at_index_t<sorted_message_types, Index>>;
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Generate the dispatch table at compile time.
|
||||
// This will create an array of handler pointers, one for each message type.
|
||||
//**********************************************
|
||||
template <size_t... Indices>
|
||||
static constexpr message_dispatch_table_t make_message_dispatch_table(etl::index_sequence<Indices...>)
|
||||
{
|
||||
return message_dispatch_table_t{ { get_message_handler<Indices>()... } };
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Get the message id for a single message type at an index in the sorted type_list.
|
||||
// This will be called for each message type to generate the message id table.
|
||||
//**********************************************
|
||||
template <size_t Index>
|
||||
static constexpr etl::message_id_t get_message_id_from_index()
|
||||
{
|
||||
return etl::type_list_type_at_index_t<sorted_message_types, Index>::ID;
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Generate the message id table at compile time.
|
||||
// This will create an array of message ids, one for each message type.
|
||||
//**********************************************
|
||||
template <size_t... Indices>
|
||||
static constexpr message_id_table_t make_message_id_table(etl::index_sequence<Indices...>)
|
||||
{
|
||||
return message_id_table_t{ { get_message_id_from_index<Indices>()... } };
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Get the dispatch index for a message id.
|
||||
// This will be used at runtime to find the handler for a message id.
|
||||
// If the message ids are contiguous, we can calculate the index directly. If they are not contiguous, we need to do a binary search.
|
||||
// This will return Number_Of_Messages if the message id is not found.
|
||||
//**********************************************
|
||||
static size_t get_dispatch_index_from_message_id(etl::message_id_t id)
|
||||
{
|
||||
if ETL_IF_CONSTEXPR(Message_Ids_Are_Contiguous)
|
||||
{
|
||||
// The IDs are contiguous, so we can calculate the index directly.
|
||||
return static_cast<size_t>(id - Message_Id_Start);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The IDs are not contiguous, so we need to do a binary search.
|
||||
size_t left = 0;
|
||||
size_t right = Number_Of_Messages;
|
||||
|
||||
while (left < right)
|
||||
{
|
||||
size_t mid = (left + right) / 2;
|
||||
|
||||
if (message_id_table[mid] == id)
|
||||
{
|
||||
return mid;
|
||||
}
|
||||
else if (message_id_table[mid] < id)
|
||||
{
|
||||
left = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Number_Of_Messages; // Not found
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// Dispatch the message to the appropriate handler based on the index in the dispatch table.
|
||||
//**********************************************
|
||||
etl::fsm_state_id_t dispatch(const etl::imessage& msg, size_t index)
|
||||
{
|
||||
return message_dispatch_table[index](static_cast<TDerived&>(*this), msg);
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
// The dispatch table is generated at compile time. The dispatch table contains pointers to the on_receive handlers for each message type.
|
||||
//**********************************************
|
||||
static ETL_INLINE_VAR constexpr message_dispatch_table_t message_dispatch_table =
|
||||
etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::make_message_dispatch_table(etl::make_index_sequence<etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::Number_Of_Messages>{});
|
||||
|
||||
//**********************************************
|
||||
// The message id table is generated at compile time. The message id table contains the corresponding message ids for each message type.
|
||||
//**********************************************
|
||||
static ETL_INLINE_VAR constexpr message_id_table_t message_id_table =
|
||||
etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::make_message_id_table(etl::make_index_sequence<etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::Number_Of_Messages>{});
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11 && !ETL_USING_CPP17
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
constexpr const typename etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::message_dispatch_table_t
|
||||
etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::message_dispatch_table;
|
||||
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
constexpr const typename etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::message_id_table_t
|
||||
etl::fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::message_id_table;
|
||||
#endif
|
||||
|
||||
/// Definition of STATE_ID
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
|
||||
|
||||
//***************************************************************************
|
||||
// The definition for no messages.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_>
|
||||
class fsm_state<TContext, TDerived, STATE_ID_> : public ifsm_state
|
||||
{
|
||||
private:
|
||||
|
||||
using message_id_sequence = etl::index_sequence<>;
|
||||
|
||||
public:
|
||||
|
||||
using message_types = etl::type_list<>;
|
||||
using sorted_message_types = etl::type_list<>;
|
||||
|
||||
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||||
|
||||
fsm_state()
|
||||
@ -779,51 +1012,16 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
//********************************************
|
||||
struct result_t
|
||||
{
|
||||
bool was_handled;
|
||||
etl::fsm_state_id_t state_id;
|
||||
};
|
||||
|
||||
//********************************************
|
||||
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||||
{
|
||||
etl::fsm_state_id_t new_state_id;
|
||||
|
||||
const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
|
||||
|
||||
if (!was_handled || (new_state_id == Pass_To_Parent))
|
||||
{
|
||||
new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
|
||||
}
|
||||
|
||||
return new_state_id;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
template <typename TMessage>
|
||||
bool process_event_type(const etl::imessage& msg, etl::fsm_state_id_t& new_state_id)
|
||||
{
|
||||
if (TMessage::ID == msg.get_message_id())
|
||||
{
|
||||
new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const TMessage&>(msg));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
|
||||
}
|
||||
};
|
||||
|
||||
/// Definition of STATE_ID
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
|
||||
|
||||
#else
|
||||
//*************************************************************************************************
|
||||
// For C++14 and below.
|
||||
// For C++03 and below.
|
||||
//*************************************************************************************************
|
||||
/*[[[cog
|
||||
import cog
|
||||
@ -833,14 +1031,14 @@ namespace etl
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// The definition for all %s message types." % Handlers)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
cog.out(" typename T%s = void," % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % Handlers)
|
||||
cog.out(" ")
|
||||
cog.outl(" typename T%s = void>" % Handlers)
|
||||
cog.outl("class fsm_state : public ifsm_state")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
@ -896,26 +1094,26 @@ namespace etl
|
||||
else:
|
||||
cog.outl("// Specialisation for %d message types." % n)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,")
|
||||
cog.out(" ")
|
||||
for t in range(1, n):
|
||||
cog.out("typename T%d, " % t)
|
||||
cog.out(" typename T%d," % t)
|
||||
if t % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%d>" % n)
|
||||
cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
cog.outl(" typename T%d>" % n)
|
||||
cog.out("class fsm_state<TContext, TDerived, STATE_ID_,")
|
||||
for t in range(1, n + 1):
|
||||
cog.out("T%d, " % t)
|
||||
cog.out(" T%d," % t)
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
for t in range(n + 1, int(Handlers)):
|
||||
cog.out("void, ")
|
||||
cog.out(" void,")
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("void> : public ifsm_state")
|
||||
cog.outl(" void> : public ifsm_state")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
@ -966,13 +1164,13 @@ namespace etl
|
||||
cog.outl("// Specialisation for 0 message types.")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_>")
|
||||
cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
|
||||
cog.out("class fsm_state<TContext, TDerived, STATE_ID_,")
|
||||
for t in range(1, int(Handlers)):
|
||||
cog.out("void, ")
|
||||
cog.out(" void,")
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("void> : public ifsm_state")
|
||||
cog.outl(" void> : public ifsm_state")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
@ -1002,18 +1200,18 @@ namespace etl
|
||||
cog.outl("};")
|
||||
|
||||
cog.outl("")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("typename T%s, " % n)
|
||||
cog.out(" typename T%s," % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s>" % Handlers)
|
||||
cog.out("ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
cog.outl(" typename T%s>" % Handlers)
|
||||
cog.out("ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_,")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::STATE_ID;" % Handlers)
|
||||
cog.out(" T%s," % n)
|
||||
cog.outl(" T%s>::STATE_ID;" % Handlers)
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#endif
|
||||
|
||||
@ -525,33 +525,31 @@ namespace etl
|
||||
//***********************************************
|
||||
void receive(const etl::imessage& msg) ETL_OVERRIDE
|
||||
{
|
||||
etl::message_id_t id = msg.get_message_id();
|
||||
size_t index = Number_Of_Messages;
|
||||
const etl::message_id_t id = msg.get_message_id();
|
||||
|
||||
// The IDs are sorted, so an ID less than the first is not handled by this router.
|
||||
if (id >= Message_Id_Start)
|
||||
{
|
||||
index = get_dispatch_index_from_message_id(id);
|
||||
const size_t index = get_dispatch_index_from_message_id(id);
|
||||
|
||||
// If the index is less than Number_Of_Messages, then we have a handler for this message type, so dispatch it.
|
||||
if (index < Number_Of_Messages)
|
||||
{
|
||||
dispatch(msg, index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the index is less than Number_Of_Messages, then we have a handler for this message type, so dispatch it.
|
||||
if (index < Number_Of_Messages)
|
||||
// We don't have a handler for this message type, so pass it to a successor if there is one, or call on_receive_unknown() if there isn't.
|
||||
if (has_successor())
|
||||
{
|
||||
dispatch(msg, index);
|
||||
get_successor().receive(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't have a handler for this message type, so pass it to a successor if there is one, or call on_receive_unknown() if there isn't.
|
||||
if (has_successor())
|
||||
{
|
||||
get_successor().receive(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
#include "etl/private/diagnostic_array_bounds_push.h"
|
||||
static_cast<TDerived*>(this)->on_receive_unknown(msg);
|
||||
static_cast<TDerived*>(this)->on_receive_unknown(msg);
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -601,29 +599,17 @@ namespace etl
|
||||
//***********************************************
|
||||
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
|
||||
{
|
||||
size_t index = Number_Of_Messages;
|
||||
|
||||
// The IDs are sorted, so an ID less than the first is not handled by this router.
|
||||
if (id >= Message_Id_Start)
|
||||
{
|
||||
index = get_dispatch_index_from_message_id(id);
|
||||
const size_t index = get_dispatch_index_from_message_id(id);
|
||||
|
||||
if (index < Number_Of_Messages)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < Number_Of_Messages)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (has_successor())
|
||||
{
|
||||
return get_successor().accepts(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return has_successor() ? get_successor().accepts(id) : false;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
|
||||
@ -765,11 +765,11 @@ namespace etl
|
||||
///\ingroup type_traits
|
||||
/// Implemented by checking if type is convertible to an integer through static_cast
|
||||
|
||||
namespace private_type_traits
|
||||
namespace private_type_traits
|
||||
{
|
||||
// Base case
|
||||
template <typename T, typename = int>
|
||||
struct is_convertible_to_int
|
||||
struct is_convertible_to_int
|
||||
: false_type
|
||||
{
|
||||
};
|
||||
@ -778,7 +778,7 @@ namespace etl
|
||||
// 2nd template argument of base case defaults to int to ensure that this partial specialization is always tried first
|
||||
template <typename T>
|
||||
struct is_convertible_to_int<T, decltype(static_cast<int>(declval<T>()))>
|
||||
: true_type
|
||||
: true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -788,7 +788,7 @@ namespace etl
|
||||
: integral_constant<bool, private_type_traits::is_convertible_to_int<T>::value &&
|
||||
!is_class<T>::value &&
|
||||
!is_arithmetic<T>::value &&
|
||||
!is_reference<T>::value>
|
||||
!is_reference<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
@ -872,6 +872,42 @@ namespace etl
|
||||
public:
|
||||
static ETL_CONSTANT bool value = decltype(test<TFrom>(0))::value;
|
||||
};
|
||||
#else
|
||||
namespace private_type_traits
|
||||
{
|
||||
typedef char yes;
|
||||
struct no { char dummy[2]; };
|
||||
|
||||
template <typename TFrom, typename TTo>
|
||||
struct is_convertible_impl
|
||||
{
|
||||
static yes test(TTo);
|
||||
static no test(...);
|
||||
static TFrom make();
|
||||
static const bool value = (sizeof(test(make())) == sizeof(yes));
|
||||
};
|
||||
|
||||
template <typename TTo>
|
||||
struct is_convertible_impl<void, TTo>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename TFrom>
|
||||
struct is_convertible_impl<TFrom, void>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_convertible_impl<void, void>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename TFrom, typename TTo>
|
||||
struct is_convertible : etl::bool_constant<private_type_traits::is_convertible_impl<TFrom, TTo>::value> {};
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
@ -1420,6 +1456,42 @@ typedef integral_constant<bool, true> true_type;
|
||||
public:
|
||||
static ETL_CONSTANT bool value = decltype(test<TFrom>(0))::value;
|
||||
};
|
||||
#else
|
||||
namespace private_type_traits
|
||||
{
|
||||
typedef char yes;
|
||||
struct no { char dummy[2]; };
|
||||
|
||||
template <typename TFrom, typename TTo>
|
||||
struct is_convertible_impl
|
||||
{
|
||||
static yes test(TTo);
|
||||
static no test(...);
|
||||
static TFrom make();
|
||||
static const bool value = (sizeof(test(make())) == sizeof(yes));
|
||||
};
|
||||
|
||||
template <typename TTo>
|
||||
struct is_convertible_impl<void, TTo>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename TFrom>
|
||||
struct is_convertible_impl<TFrom, void>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_convertible_impl<void, void>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename TFrom, typename TTo>
|
||||
struct is_convertible : etl::bool_constant<private_type_traits::is_convertible_impl<TFrom, TTo>::value> {};
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
@ -1556,17 +1628,17 @@ typedef integral_constant<bool, true> true_type;
|
||||
cog.outl("/// Template to determine if a type is one of a specified list.")
|
||||
cog.outl("///\\ingroup types")
|
||||
cog.outl("template <typename T,")
|
||||
cog.out(" ")
|
||||
cog.out("typename T1, ")
|
||||
cog.out(" ")
|
||||
cog.out(" typename T1,")
|
||||
for n in range(2, int(IsOneOf)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
cog.out(" typename T%s = void," % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % IsOneOf)
|
||||
cog.out(" ")
|
||||
cog.outl(" typename T%s = void>" % IsOneOf)
|
||||
cog.outl("struct is_one_of")
|
||||
cog.outl("{")
|
||||
cog.outl(" static const bool value = ")
|
||||
cog.outl(" static const bool value =")
|
||||
for n in range(1, int(IsOneOf)):
|
||||
cog.outl(" etl::is_same<T, T%s>::value ||" % n)
|
||||
cog.outl(" etl::is_same<T, T%s>::value;" % IsOneOf)
|
||||
@ -1647,7 +1719,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
//***************************************************************************
|
||||
/// Get the Nth base of a recursively inherited type.
|
||||
/// Requires that the class has defined 'base_type'.
|
||||
//***************************************************************************
|
||||
//***************************************************************************
|
||||
// Recursive definition of the type.
|
||||
template <size_t Index, typename TType>
|
||||
struct nth_base
|
||||
@ -2192,7 +2264,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// is_constructible
|
||||
namespace private_type_traits
|
||||
namespace private_type_traits
|
||||
{
|
||||
template <class, class T, class... TArgs>
|
||||
struct is_constructible_ : etl::false_type {};
|
||||
@ -2371,7 +2443,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct common_type_2_impl
|
||||
struct common_type_2_impl
|
||||
: decay_conditional_result<const T1&, const T2&>
|
||||
{
|
||||
};
|
||||
@ -2716,7 +2788,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
struct is_member_pointer_helper<T TObject::*> : etl::true_type {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T>
|
||||
struct is_member_pointer : private_type_traits::is_member_pointer_helper<typename etl::remove_cv<T>::type> {};
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
@ -2809,10 +2881,10 @@ typedef integral_constant<bool, true> true_type;
|
||||
//***************************************************************************
|
||||
namespace private_type_traits
|
||||
{
|
||||
template<typename>
|
||||
template<typename>
|
||||
struct is_member_object_pointer_helper : public etl::false_type {};
|
||||
|
||||
template<typename T, typename TObject>
|
||||
template<typename T, typename TObject>
|
||||
struct is_member_object_pointer_helper<T TObject::*> : public etl::negation<etl::is_function<T>> {};
|
||||
}
|
||||
|
||||
@ -3034,6 +3106,60 @@ typedef integral_constant<bool, true> true_type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename, typename = void>
|
||||
struct has_size : etl::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct has_size<T, void_t<decltype(etl::declval<T>().size())> >
|
||||
: etl::true_type {};
|
||||
#else
|
||||
template <typename T>
|
||||
struct has_size
|
||||
{
|
||||
private:
|
||||
typedef char yes;
|
||||
struct no { char dummy[2]; };
|
||||
|
||||
template <typename U>
|
||||
static yes test_size(char (*)[sizeof(&U::size)]);
|
||||
|
||||
template <typename U>
|
||||
static no test_size(...);
|
||||
|
||||
public:
|
||||
|
||||
static const bool value = (sizeof(test_size<T>(0)) == sizeof(yes));
|
||||
};
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename, typename = void>
|
||||
struct has_data : etl::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct has_data<T, void_t<decltype(etl::declval<T>().data())> >
|
||||
: etl::true_type {};
|
||||
#else
|
||||
template <typename T>
|
||||
struct has_data
|
||||
{
|
||||
private:
|
||||
typedef char yes;
|
||||
struct no { char dummy[2]; };
|
||||
|
||||
template <typename U>
|
||||
static yes test_data(char (*)[sizeof(&U::data)]);
|
||||
|
||||
template <typename U>
|
||||
static no test_data(...);
|
||||
|
||||
public:
|
||||
|
||||
static const bool value = (sizeof(test_data<T>(0)) == sizeof(yes));
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helper macros
|
||||
|
||||
@ -67,7 +67,7 @@ namespace etl
|
||||
typedef typename TIterator::pointer pointer;
|
||||
typedef typename TIterator::reference reference;
|
||||
};
|
||||
|
||||
|
||||
// For pointers.
|
||||
template <typename T>
|
||||
struct iterator_traits<T*, void>
|
||||
@ -606,7 +606,7 @@ namespace etl
|
||||
ETL_CONSTEXPR14 back_insert_iterator& operator =(const typename TContainer::value_type& value)
|
||||
{
|
||||
container->push_back(value);
|
||||
|
||||
|
||||
return (*this);
|
||||
}
|
||||
|
||||
@ -617,7 +617,7 @@ namespace etl
|
||||
ETL_CONSTEXPR14 back_insert_iterator& operator =(typename TContainer::value_type&& value)
|
||||
{
|
||||
container->push_back(etl::move(value));
|
||||
|
||||
|
||||
return (*this);
|
||||
}
|
||||
#endif // ETL_USING_CPP11
|
||||
@ -655,8 +655,8 @@ namespace etl
|
||||
/// Creates a back_insert_iterator from a container.
|
||||
//***************************************************************************
|
||||
template <typename TContainer>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
etl::back_insert_iterator<TContainer> back_inserter(TContainer& container)
|
||||
{
|
||||
return etl::back_insert_iterator<TContainer>(container);
|
||||
@ -1211,6 +1211,48 @@ namespace etl
|
||||
char(&array_size(T(&array)[Array_Size]))[Array_Size];
|
||||
|
||||
#define ETL_ARRAY_SIZE(a) sizeof(etl::array_size(a))
|
||||
|
||||
#if ETL_NOT_USING_STL || ETL_CPP17_NOT_SUPPORTED
|
||||
//**************************************************************************
|
||||
/// Returns a pointer to the block of memory containing the elements of the range.
|
||||
///\ingroup container
|
||||
//**************************************************************************
|
||||
template<typename TContainer>
|
||||
ETL_CONSTEXPR typename TContainer::pointer data(TContainer& container)
|
||||
{
|
||||
return container.data();
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
/// Returns a const_pointer to the block of memory containing the elements of the range.
|
||||
///\ingroup container
|
||||
//**************************************************************************
|
||||
template<typename TContainer>
|
||||
ETL_CONSTEXPR typename TContainer::const_pointer data(const TContainer& container)
|
||||
{
|
||||
return container.data();
|
||||
}
|
||||
|
||||
///**************************************************************************
|
||||
/// Returns a pointer to the block of memory containing the elements of the range.
|
||||
///\ingroup container
|
||||
///**************************************************************************
|
||||
template<typename TValue, size_t Array_Size>
|
||||
ETL_CONSTEXPR TValue* data(TValue(&a)[Array_Size])
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
///**************************************************************************
|
||||
/// Returns a const pointer to the block of memory containing the elements of the range.
|
||||
///\ingroup container
|
||||
///**************************************************************************
|
||||
template<typename TValue, size_t Array_Size>
|
||||
ETL_CONSTEXPR const TValue* data(const TValue(&a)[Array_Size])
|
||||
{
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -513,33 +513,31 @@ namespace etl
|
||||
//***********************************************
|
||||
void receive(const etl::imessage& msg) ETL_OVERRIDE
|
||||
{
|
||||
etl::message_id_t id = msg.get_message_id();
|
||||
size_t index = Number_Of_Messages;
|
||||
const etl::message_id_t id = msg.get_message_id();
|
||||
|
||||
// The IDs are sorted, so an ID less than the first is not handled by this router.
|
||||
if (id >= Message_Id_Start)
|
||||
{
|
||||
index = get_dispatch_index_from_message_id(id);
|
||||
const size_t index = get_dispatch_index_from_message_id(id);
|
||||
|
||||
// If the index is less than Number_Of_Messages, then we have a handler for this message type, so dispatch it.
|
||||
if (index < Number_Of_Messages)
|
||||
{
|
||||
dispatch(msg, index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the index is less than Number_Of_Messages, then we have a handler for this message type, so dispatch it.
|
||||
if (index < Number_Of_Messages)
|
||||
// We don't have a handler for this message type, so pass it to a successor if there is one, or call on_receive_unknown() if there isn't.
|
||||
if (has_successor())
|
||||
{
|
||||
dispatch(msg, index);
|
||||
get_successor().receive(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't have a handler for this message type, so pass it to a successor if there is one, or call on_receive_unknown() if there isn't.
|
||||
if (has_successor())
|
||||
{
|
||||
get_successor().receive(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
#include "etl/private/diagnostic_array_bounds_push.h"
|
||||
static_cast<TDerived*>(this)->on_receive_unknown(msg);
|
||||
static_cast<TDerived*>(this)->on_receive_unknown(msg);
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -589,29 +587,17 @@ namespace etl
|
||||
//***********************************************
|
||||
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
|
||||
{
|
||||
size_t index = Number_Of_Messages;
|
||||
|
||||
// The IDs are sorted, so an ID less than the first is not handled by this router.
|
||||
if (id >= Message_Id_Start)
|
||||
{
|
||||
index = get_dispatch_index_from_message_id(id);
|
||||
const size_t index = get_dispatch_index_from_message_id(id);
|
||||
|
||||
if (index < Number_Of_Messages)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < Number_Of_Messages)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (has_successor())
|
||||
{
|
||||
return get_successor().accepts(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return has_successor() ? get_successor().accepts(id) : false;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
|
||||
@ -47,7 +47,7 @@ namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// iota
|
||||
/// Reverse engineered version of std::iota for non C++ 0x11 compilers.
|
||||
/// Reverse engineered version of std::iota for non C++11 compilers.
|
||||
/// Fills a range of elements with sequentially increasing values starting with <b>value</b>.
|
||||
///\param first An iterator to the first position to fill.
|
||||
///\param last An iterator to the last + 1 position.
|
||||
|
||||
@ -154,6 +154,16 @@ SOFTWARE.
|
||||
#define ETL_NOT_USING_WIDE_CHARACTERS 0
|
||||
#endif
|
||||
|
||||
//*************************************
|
||||
// Helper macro for ETL_FORMAT_NO_FLOATING_POINT.
|
||||
#if defined(ETL_FORMAT_NO_FLOATING_POINT)
|
||||
#define ETL_USING_FORMAT_FLOATING_POINT 0
|
||||
#define ETL_NOT_USING_FORMAT_FLOATING_POINT 1
|
||||
#else
|
||||
#define ETL_USING_FORMAT_FLOATING_POINT 1
|
||||
#define ETL_NOT_USING_FORMAT_FLOATING_POINT 0
|
||||
#endif
|
||||
|
||||
//*************************************
|
||||
// Figure out things about the compiler, if haven't already done so in etl_profile.h
|
||||
#include "profiles/determine_compiler_version.h"
|
||||
@ -372,11 +382,13 @@ SOFTWARE.
|
||||
#if ETL_USING_EXCEPTIONS
|
||||
#define ETL_NOEXCEPT noexcept
|
||||
#define ETL_NOEXCEPT_EXPR(...) noexcept(__VA_ARGS__)
|
||||
#define ETL_NOEXCEPT_IF(b) noexcept((b))
|
||||
#define ETL_NOEXCEPT_FROM(x) noexcept(noexcept(x))
|
||||
#else
|
||||
#define ETL_NOEXCEPT
|
||||
#define ETL_NOEXCEPT_EXPR(...)
|
||||
#define ETL_NOEXCEPT_FROM(x)
|
||||
#define ETL_NOEXCEPT_IF(b)
|
||||
#define ETL_NOEXCEPT_FROM(x)
|
||||
#endif
|
||||
#else
|
||||
#define ETL_CONSTEXPR
|
||||
@ -389,7 +401,8 @@ SOFTWARE.
|
||||
#define ETL_NORETURN
|
||||
#define ETL_NOEXCEPT
|
||||
#define ETL_NOEXCEPT_EXPR(...)
|
||||
#define ETL_NOEXCEPT_FROM(x)
|
||||
#define ETL_NOEXCEPT_IF(b)
|
||||
#define ETL_NOEXCEPT_FROM(x)
|
||||
#define ETL_MOVE(x) x
|
||||
#define ETL_ENUM_CLASS(name) enum name
|
||||
#define ETL_ENUM_CLASS_TYPE(name, type) enum name
|
||||
@ -402,7 +415,7 @@ SOFTWARE.
|
||||
#if ETL_USING_CPP14
|
||||
#define ETL_CONSTEXPR14 constexpr
|
||||
|
||||
#if !defined(ETL_IN_UNIT_TEST)
|
||||
#if !defined(ETL_IN_UNIT_TEST)
|
||||
#define ETL_DEPRECATED [[deprecated]]
|
||||
#define ETL_DEPRECATED_REASON(reason) [[deprecated(reason)]]
|
||||
#else
|
||||
@ -448,7 +461,13 @@ SOFTWARE.
|
||||
#define ETL_UNLIKELY
|
||||
#define ETL_CONSTEXPR20
|
||||
#define ETL_CONSTEVAL
|
||||
#define ETL_CONSTINIT
|
||||
#if ETL_USING_CLANG_COMPILER && ETL_COMPILER_FULL_VERSION >= 40000
|
||||
#define ETL_CONSTINIT __attribute__((require_constant_initialization))
|
||||
#elif ETL_USING_GCC_COMPILER && ETL_COMPILER_FULL_VERSION >= 100000
|
||||
#define ETL_CONSTINIT __constinit
|
||||
#else
|
||||
#define ETL_CONSTINIT
|
||||
#endif
|
||||
#define ETL_NO_UNIQUE_ADDRESS
|
||||
#define ETL_EXPLICIT_EXPR(...) explicit
|
||||
#endif
|
||||
@ -601,7 +620,7 @@ SOFTWARE.
|
||||
#elif defined(ETL_COMPILER_MICROSOFT)
|
||||
#define ETL_PACKED_CLASS(class_type) __pragma(pack(push, 1)) class class_type
|
||||
#define ETL_PACKED_STRUCT(struct_type) __pragma(pack(push, 1)) struct struct_type
|
||||
#define ETL_PACKED
|
||||
#define ETL_PACKED
|
||||
#define ETL_END_PACKED __pragma(pack(pop))
|
||||
#define ETL_HAS_PACKED 1
|
||||
#else
|
||||
@ -651,7 +670,8 @@ namespace etl
|
||||
static ETL_CONSTANT bool using_exceptions = (ETL_USING_EXCEPTIONS == 1);
|
||||
static ETL_CONSTANT bool using_libc_wchar_h = (ETL_USING_LIBC_WCHAR_H == 1);
|
||||
static ETL_CONSTANT bool using_std_exception = (ETL_USING_STD_EXCEPTION == 1);
|
||||
|
||||
static ETL_CONSTANT bool using_format_floating_point = (ETL_USING_FORMAT_FLOATING_POINT == 1);
|
||||
|
||||
// Has...
|
||||
static ETL_CONSTANT bool has_initializer_list = (ETL_HAS_INITIALIZER_LIST == 1);
|
||||
static ETL_CONSTANT bool has_8bit_types = (ETL_USING_8BIT_TYPES == 1);
|
||||
|
||||
@ -454,7 +454,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Removes the oldest value from the back of the queue.
|
||||
/// Removes the oldest value from the front of the queue.
|
||||
/// Does nothing if the queue is already empty.
|
||||
/// If asserts or exceptions are enabled, throws an etl::queue_empty if the queue is empty.
|
||||
//*************************************************************************
|
||||
|
||||
@ -47,6 +47,12 @@ SOFTWARE.
|
||||
#include "array.h"
|
||||
#include "byte.h"
|
||||
#include "static_assert.h"
|
||||
#include "container.h"
|
||||
#include "private/tuple_size.h"
|
||||
|
||||
#if ETL_USING_STL && ETL_USING_CPP20
|
||||
#include <span>
|
||||
#endif
|
||||
|
||||
#include "private/dynamic_extent.h"
|
||||
|
||||
@ -72,7 +78,28 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Tag to indicate a class is a span.
|
||||
//***************************************************************************
|
||||
class span_tag {};
|
||||
|
||||
// Forward declaration for trait
|
||||
template <typename T, size_t Extent>
|
||||
class span;
|
||||
|
||||
namespace private_span
|
||||
{
|
||||
template <typename T>
|
||||
struct is_span_helper : etl::false_type {};
|
||||
|
||||
template <typename T, size_t Extent>
|
||||
struct is_span_helper<etl::span<T, Extent> > : etl::true_type {};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct is_span
|
||||
: private_span::is_span_helper<typename etl::remove_cvref<T>::type> {};
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
template <typename T>
|
||||
inline constexpr bool is_span_v = is_span<T>::value;
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup span
|
||||
@ -130,6 +157,12 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup span
|
||||
/// Tag to indicate a class is a span.
|
||||
/// Deprecated, use is_span trait instead.
|
||||
class span_tag {};
|
||||
|
||||
//***************************************************************************
|
||||
/// Span - Fixed Extent
|
||||
//***************************************************************************
|
||||
@ -141,13 +174,13 @@ namespace etl
|
||||
typedef T element_type;
|
||||
typedef typename etl::remove_cv<T>::type value_type;
|
||||
typedef size_t size_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
@ -157,72 +190,92 @@ namespace etl
|
||||
static ETL_CONSTANT size_t extent = Extent;
|
||||
|
||||
//*************************************************************************
|
||||
/// Construct from iterators + size
|
||||
/// Default constructor
|
||||
/// Enabled only for zero extent, creates an empty span.
|
||||
//*************************************************************************
|
||||
template <typename TIterator, typename TSize>
|
||||
ETL_CONSTEXPR explicit span(const TIterator begin_, const TSize /*size_*/) ETL_NOEXCEPT
|
||||
#if ETL_USING_CPP11
|
||||
template <size_t E = Extent, typename = typename etl::enable_if<E == 0, void>::type>
|
||||
ETL_CONSTEXPR span() ETL_NOEXCEPT
|
||||
: pbegin(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
#else
|
||||
ETL_CONSTEXPR span() ETL_NOEXCEPT
|
||||
: pbegin(ETL_NULLPTR)
|
||||
{
|
||||
ETL_STATIC_ASSERT(Extent == 0, "Default constructor only available for zero extent");
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Construct from iterator + size
|
||||
//*************************************************************************
|
||||
template <typename TIterator>
|
||||
explicit ETL_CONSTEXPR14 span(const TIterator begin_, const size_t size_) ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS)
|
||||
: pbegin(etl::to_address(begin_))
|
||||
{
|
||||
ETL_ASSERT(size_ == Extent, ETL_ERROR(span_size_mismatch));
|
||||
(void)size_;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Construct from iterators
|
||||
//*************************************************************************
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR explicit span(const TIterator begin_, const TIterator /*end_*/) ETL_NOEXCEPT
|
||||
template <typename TIteratorBegin, typename TIteratorEnd>
|
||||
ETL_CONSTEXPR14 span(const TIteratorBegin begin_, const TIteratorEnd end_,
|
||||
typename etl::enable_if<!etl::is_integral<TIteratorEnd>::value, void>::type* = 0) ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS)
|
||||
: pbegin(etl::to_address(begin_))
|
||||
{
|
||||
ETL_ASSERT(etl::distance(begin_, end_) == Extent, ETL_ERROR(span_size_mismatch));
|
||||
(void)end_;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Construct from C array
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template<size_t Array_Size, typename = typename etl::enable_if<(Array_Size == Extent), void>::type>
|
||||
ETL_CONSTEXPR span(element_type(&begin_)[Array_Size]) ETL_NOEXCEPT
|
||||
: pbegin(begin_)
|
||||
{
|
||||
}
|
||||
#else
|
||||
//*************************************************************************
|
||||
/// Construct from C array
|
||||
//*************************************************************************
|
||||
template<size_t Array_Size>
|
||||
ETL_CONSTEXPR span(element_type(&begin_)[Array_Size], typename etl::enable_if<(Array_Size == Extent), void>::type* = 0) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR span(typename etl::type_identity<element_type>::type(&begin_)[Array_Size], typename etl::enable_if<(Array_Size == Extent), void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(begin_)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*************************************************************************
|
||||
/// Construct from a container or other type that supports
|
||||
/// data() and size() member functions.
|
||||
//*************************************************************************
|
||||
template <typename TContainer, typename = typename etl::enable_if<!etl::is_base_of<span_tag, etl::remove_reference_t<TContainer>>::value &&
|
||||
!etl::is_std_array<etl::remove_reference_t<TContainer>>::value &&
|
||||
!etl::is_etl_array<etl::remove_reference_t<TContainer>>::value &&
|
||||
!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
|
||||
!etl::is_array<etl::remove_reference_t<TContainer>>::value &&
|
||||
etl::is_same<etl::remove_cv_t<T>, etl::remove_cv_t<typename etl::remove_reference_t<TContainer>::value_type>>::value, void>::type>
|
||||
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
|
||||
: pbegin(a.data())
|
||||
{
|
||||
}
|
||||
template <typename TContainer>
|
||||
ETL_CONSTEXPR14 span(TContainer&& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
|
||||
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_array<TContainer>::value &&
|
||||
etl::is_lvalue_reference<TContainer&&>::value &&
|
||||
has_size<TContainer>::value &&
|
||||
has_data<TContainer>::value &&
|
||||
etl::is_convertible<decltype(etl::declval<typename etl::remove_reference<TContainer>::type&>().data()), pointer>::value &&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS)
|
||||
: pbegin(a.data())
|
||||
{
|
||||
ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch));
|
||||
}
|
||||
#else
|
||||
//*************************************************************************
|
||||
/// Construct from a container or other type that supports
|
||||
/// data() and size() member functions.
|
||||
//*************************************************************************
|
||||
template <typename TContainer>
|
||||
span(TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
|
||||
span(TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
|
||||
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_array<TContainer>::value &&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
has_size<TContainer>::value &&
|
||||
has_data<TContainer>::value &&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0)
|
||||
: pbegin(a.data())
|
||||
{
|
||||
ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -230,17 +283,69 @@ namespace etl
|
||||
/// data() and size() member functions.
|
||||
//*************************************************************************
|
||||
template <typename TContainer>
|
||||
span(const TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
|
||||
span(const TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
|
||||
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_array<TContainer>::value&&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
has_size<TContainer>::value &&
|
||||
has_data<TContainer>::value &&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0)
|
||||
: pbegin(a.data())
|
||||
{
|
||||
ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch));
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from etl array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(etl::array<U, Size>& other, typename etl::enable_if<(Size == Extent) &&
|
||||
etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from const etl array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(const etl::array<U, Size>& other, typename etl::enable_if<(Size == Extent) &&
|
||||
etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
{
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename U, size_t Size>
|
||||
span(etl::array<U, Size>&&) = delete;
|
||||
#endif
|
||||
|
||||
#if ETL_USING_STL && ETL_USING_CPP11
|
||||
//*************************************************************************
|
||||
/// Constructor from std array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(std::array<U, Size>& other, typename etl::enable_if<(Size == Extent) &&
|
||||
etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from const std array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(const std::array<U, Size>& other, typename etl::enable_if<(Size == Extent) &&
|
||||
etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U, size_t Size>
|
||||
span(std::array<U, Size>&&) = delete;
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Copy constructor
|
||||
//*************************************************************************
|
||||
@ -254,7 +359,7 @@ namespace etl
|
||||
/// From fixed extent span.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(const etl::span<U, Size>& other, typename etl::enable_if<Size == Extent, void>::type* = 0) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR span(const etl::span<U, Size>& other, typename etl::enable_if<(Size == Extent) && (Size != etl::dynamic_extent), void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
{
|
||||
}
|
||||
@ -264,50 +369,37 @@ namespace etl
|
||||
/// From dynamic extent span.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR14 span(const etl::span<U, Size>& other, typename etl::enable_if<Size == etl::dynamic_extent, void>::type* = 0)
|
||||
ETL_CONSTEXPR14 explicit span(const etl::span<U, Size>& other, typename etl::enable_if<(Size == etl::dynamic_extent), void>::type* = 0)
|
||||
: pbegin(other.data())
|
||||
{
|
||||
ETL_ASSERT(other.size() == Extent, ETL_ERROR(span_size_mismatch));
|
||||
}
|
||||
|
||||
#if ETL_USING_STL && ETL_USING_CPP11
|
||||
#if ETL_USING_STL && ETL_USING_CPP20
|
||||
//*************************************************************************
|
||||
/// Constructor from std array.
|
||||
/// Copy constructor
|
||||
/// From fixed extent std::span.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(std::array<U, Size>& other, typename etl::enable_if<Size == Extent, void>::type* = 0) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR span(const std::span<U, Size>& other, typename etl::enable_if<(Size == Extent) &&
|
||||
etl::is_convertible<U(*)[], T(*)[]>::value, int>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from const std array.
|
||||
/// Copy constructor
|
||||
/// From dynamic extent std::span.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(const std::array<U, Size>& other, typename etl::enable_if<Size == Extent && etl::is_const<T>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 span(const std::span<U, Size>& other, typename etl::enable_if<(Size == etl::dynamic_extent &&
|
||||
etl::is_convertible<U(*)[], T(*)[]>::value), int>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
{
|
||||
ETL_ASSERT(other.size() == Extent, ETL_ERROR(span_size_mismatch));
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from etl array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(etl::array<U, Size>& other, typename etl::enable_if<Size == Extent, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from const etl array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(const etl::array<U, Size>& other, typename etl::enable_if<Size == Extent && etl::is_const<T>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns a reference to the first element.
|
||||
//*************************************************************************
|
||||
@ -455,7 +547,7 @@ namespace etl
|
||||
{
|
||||
pbegin = other.pbegin;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns a reference to the value at index 'i'.
|
||||
@ -506,13 +598,13 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Obtains a span that is a view over the first count elements of this span.
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> first(size_t count) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> first(size_t count) const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return count <= size() ? etl::span<element_type, etl::dynamic_extent>(pbegin, pbegin + count) : throw(ETL_ERROR(span_out_of_range));
|
||||
#else
|
||||
ETL_ASSERT_CHECK_EXTRA(count <= size(), ETL_ERROR(span_out_of_range));
|
||||
|
||||
|
||||
return etl::span<element_type, etl::dynamic_extent>(pbegin, pbegin + count);
|
||||
#endif
|
||||
}
|
||||
@ -532,11 +624,11 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Obtains a span that is a view over the last count elements of this span.
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> last(size_t count) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> last(size_t count) const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return count <= size() ?
|
||||
etl::span<element_type, etl::dynamic_extent>((pbegin + Extent) - count, (pbegin + Extent)) :
|
||||
return count <= size() ?
|
||||
etl::span<element_type, etl::dynamic_extent>((pbegin + Extent) - count, (pbegin + Extent)) :
|
||||
throw(ETL_ERROR(span_out_of_range));
|
||||
#else
|
||||
ETL_ASSERT_CHECK_EXTRA(count <= size(), ETL_ERROR(span_out_of_range));
|
||||
@ -589,7 +681,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Obtains a span that is a view from 'offset' over the next 'count' elements of this span.
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return (offset <= size()) && (count != etl::dynamic_extent ? count <= (size() - offset) : true) ?
|
||||
@ -636,7 +728,7 @@ namespace etl
|
||||
/// Span - Dynamic Extent
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
class span<T, etl::dynamic_extent> : public span_tag
|
||||
class span<T, etl::dynamic_extent> : public span_tag
|
||||
{
|
||||
public:
|
||||
|
||||
@ -668,10 +760,10 @@ namespace etl
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Construct from pointer + size
|
||||
/// Construct from iterator + size
|
||||
//*************************************************************************
|
||||
template <typename TIterator, typename TSize>
|
||||
ETL_CONSTEXPR span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR span(const TIterator begin_, size_t size_) ETL_NOEXCEPT
|
||||
: pbegin(etl::to_address(begin_))
|
||||
, pend(etl::to_address(begin_) + size_)
|
||||
{
|
||||
@ -680,8 +772,9 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Construct from iterators
|
||||
//*************************************************************************
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR span(const TIterator begin_, const TIterator end_) ETL_NOEXCEPT
|
||||
template <typename TIteratorBegin, typename TIteratorEnd>
|
||||
ETL_CONSTEXPR span(const TIteratorBegin begin_, const TIteratorEnd end_,
|
||||
typename etl::enable_if<!etl::is_integral<TIteratorEnd>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(etl::to_address(begin_))
|
||||
, pend(etl::to_address(begin_) + etl::distance(begin_, end_))
|
||||
{
|
||||
@ -702,11 +795,17 @@ namespace etl
|
||||
/// Construct from a container or other type that supports
|
||||
/// data() and size() member functions.
|
||||
//*************************************************************************
|
||||
template <typename TContainer, typename = typename etl::enable_if<!etl::is_base_of<span_tag, etl::remove_reference_t<TContainer>>::value &&
|
||||
!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
|
||||
!etl::is_array<etl::remove_reference_t<TContainer>>::value &&
|
||||
etl::is_same<etl::remove_cv_t<T>, etl::remove_cv_t<typename etl::remove_reference_t<TContainer>::value_type>>::value, void>::type>
|
||||
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
|
||||
template <typename TContainer>
|
||||
ETL_CONSTEXPR span(TContainer&& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
|
||||
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_array<TContainer>::value &&
|
||||
etl::is_lvalue_reference<TContainer&&>::value &&
|
||||
has_size<TContainer>::value &&
|
||||
has_data<TContainer>::value &&
|
||||
etl::is_convertible<decltype(etl::declval<typename etl::remove_reference<TContainer>::type&>().data()), pointer>::value &&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(a.data())
|
||||
, pend(a.data() + a.size())
|
||||
{
|
||||
@ -717,10 +816,14 @@ namespace etl
|
||||
/// data() and size() member functions.
|
||||
//*************************************************************************
|
||||
template <typename TContainer>
|
||||
ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_array<TContainer>::value &&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
span(TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
|
||||
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_array<TContainer>::value &&
|
||||
has_size<TContainer>::value &&
|
||||
has_data<TContainer>::value &&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(a.data())
|
||||
, pend(a.data() + a.size())
|
||||
{
|
||||
@ -731,16 +834,92 @@ namespace etl
|
||||
/// data() and size() member functions.
|
||||
//*************************************************************************
|
||||
template <typename TContainer>
|
||||
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_array<TContainer>::value &&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
span(const TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
|
||||
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
|
||||
!etl::is_array<TContainer>::value &&
|
||||
has_size<TContainer>::value &&
|
||||
has_data<TContainer>::value &&
|
||||
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(a.data())
|
||||
, pend(a.data() + a.size())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_STL && ETL_USING_CPP20
|
||||
//*************************************************************************
|
||||
/// Constructor from std span.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(std::span<U, Size>& other, typename etl::enable_if<etl::is_convertible<U(*)[], T(*)[]>::value, int>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
, pend(other.data() + other.size())
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from const std span.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(const std::span<U, Size>& other, typename etl::enable_if<etl::is_convertible<U(*)[], T(*)[]>::value, int>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data())
|
||||
, pend(other.data() + other.size())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from etl array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(etl::array<U, Size>& other, typename etl::enable_if<etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data()),
|
||||
pend(other.data() + Size)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from const etl array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(const etl::array<U, Size>& other, typename etl::enable_if<etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data()),
|
||||
pend(other.data() + Size)
|
||||
{
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename U, size_t Size>
|
||||
span(etl::array<U, Size>&&) = delete;
|
||||
#endif
|
||||
|
||||
#if ETL_USING_STL && ETL_USING_CPP11
|
||||
//*************************************************************************
|
||||
/// Constructor from std array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(std::array<U, Size>& other, typename etl::enable_if<etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data()),
|
||||
pend(other.data() + Size)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from const std array.
|
||||
//*************************************************************************
|
||||
template <typename U, size_t Size>
|
||||
ETL_CONSTEXPR span(const std::array<U, Size>& other, typename etl::enable_if<etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
|
||||
: pbegin(other.data()),
|
||||
pend(other.data() + Size)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U, size_t Size>
|
||||
span(std::array<U, Size>&&) = delete;
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Copy constructor
|
||||
//*************************************************************************
|
||||
@ -763,7 +942,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Returns a reference to the first element.
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return size() > 0 ? *pbegin : throw(ETL_ERROR(span_out_of_range));
|
||||
@ -777,7 +956,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Returns a reference to the last element.
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return size() > 0 ? *(pend - 1) : throw(ETL_ERROR(span_out_of_range));
|
||||
@ -956,7 +1135,7 @@ namespace etl
|
||||
/// Obtains a span that is a view over the first COUNT elements of this span.
|
||||
//*************************************************************************
|
||||
template <size_t COUNT>
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, COUNT> first() const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, COUNT> first() const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return COUNT <= size() ? etl::span<element_type, COUNT>(pbegin, pbegin + COUNT) : throw(ETL_ERROR(span_out_of_range));
|
||||
@ -970,7 +1149,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Obtains a span that is a view over the first count elements of this span.
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> first(size_t count) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> first(size_t count) const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return count <= size() ? etl::span<element_type, etl::dynamic_extent>(pbegin, pbegin + count) : throw(ETL_ERROR(span_out_of_range));
|
||||
@ -985,7 +1164,7 @@ namespace etl
|
||||
/// Obtains a span that is a view over the last COUNT elements of this span.
|
||||
//*************************************************************************
|
||||
template <size_t COUNT>
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, COUNT> last() const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, COUNT> last() const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return COUNT <= size() ? etl::span<element_type, COUNT>(pend - COUNT, pend) : throw(ETL_ERROR(span_out_of_range));
|
||||
@ -999,7 +1178,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Obtains a span that is a view over the last count elements of this span.
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> last(size_t count) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> last(size_t count) const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return count <= size() ? etl::span<element_type, etl::dynamic_extent>(pend - count, pend) : throw(ETL_ERROR(span_out_of_range));
|
||||
@ -1016,7 +1195,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
template <size_t OFFSET, size_t COUNT = etl::dynamic_extent>
|
||||
ETL_NODISCARD ETL_CONSTEXPR
|
||||
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent> subspan() const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent> subspan() const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
|
||||
return (OFFSET <= size()) && (COUNT != etl::dynamic_extent ? COUNT <= (size() - OFFSET) : true) ?
|
||||
@ -1055,7 +1234,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Obtains a span that is a view from 'offset' over the next 'count' elements of this span.
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR14 etl::span<element_type, etl::dynamic_extent> subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
ETL_NODISCARD ETL_CONSTEXPR14 etl::span<element_type, etl::dynamic_extent> subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
|
||||
{
|
||||
ETL_ASSERT_CHECK_EXTRA(offset <= size(), ETL_ERROR(span_out_of_range));
|
||||
ETL_ASSERT_CHECK_EXTRA(count != etl::dynamic_extent ? count <= (size() - offset) : true, ETL_ERROR(span_out_of_range));
|
||||
@ -1161,7 +1340,7 @@ namespace etl
|
||||
/// Compare two spans for equality.
|
||||
//*************************************************************************
|
||||
template <typename T1, size_t N1, typename T2, size_t N2>
|
||||
ETL_NODISCARD
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR
|
||||
typename etl::enable_if<etl::is_same<typename etl::remove_cv<T1>::type, typename etl::remove_cv<T2>::type>::value, bool>::type
|
||||
operator ==(const etl::span<T1, N1>& lhs, const etl::span<T2, N2>& rhs) ETL_NOEXCEPT
|
||||
@ -1255,7 +1434,7 @@ namespace etl
|
||||
template<typename T>
|
||||
span(etl::ivector<T>&)
|
||||
-> span<T>;
|
||||
|
||||
|
||||
template<typename T>
|
||||
span(const etl::ivector<T>&)
|
||||
-> span<const T>;
|
||||
@ -1269,7 +1448,7 @@ namespace etl
|
||||
span(const std::array<T, Size>&)
|
||||
->span<const T, Size>;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Hash function.
|
||||
@ -1290,7 +1469,7 @@ namespace etl
|
||||
/// Obtains a view to the byte representation of the elements of the span s.
|
||||
//*************************************************************************
|
||||
template <class T, size_t Size>
|
||||
span<const byte, (Size == etl::dynamic_extent) ? (etl::dynamic_extent) : (Size * sizeof(T))>
|
||||
span<const byte, (Size == etl::dynamic_extent) ? (etl::dynamic_extent) : (Size * sizeof(T))>
|
||||
as_bytes(span<T, Size> s) ETL_NOEXCEPT
|
||||
{
|
||||
return span<const byte, (Size == etl::dynamic_extent) ? (etl::dynamic_extent) : (Size * sizeof(T))>(reinterpret_cast<const byte*>(s.data()), s.size_bytes());
|
||||
@ -1300,7 +1479,7 @@ namespace etl
|
||||
/// Obtains a view to the byte representation of the elements of the span s.
|
||||
//*************************************************************************
|
||||
template <class T, size_t Size>
|
||||
span<byte, (Size == etl::dynamic_extent) ? (etl::dynamic_extent) : (Size * sizeof(T))>
|
||||
span<byte, (Size == etl::dynamic_extent) ? (etl::dynamic_extent) : (Size * sizeof(T))>
|
||||
as_writable_bytes(span<T, Size> s) ETL_NOEXCEPT
|
||||
{
|
||||
ETL_STATIC_ASSERT(!etl::is_const<T>::value, "span<T> must be of non-const type");
|
||||
|
||||
@ -753,11 +753,11 @@ namespace etl
|
||||
///\ingroup type_traits
|
||||
/// Implemented by checking if type is convertible to an integer through static_cast
|
||||
|
||||
namespace private_type_traits
|
||||
namespace private_type_traits
|
||||
{
|
||||
// Base case
|
||||
template <typename T, typename = int>
|
||||
struct is_convertible_to_int
|
||||
struct is_convertible_to_int
|
||||
: false_type
|
||||
{
|
||||
};
|
||||
@ -766,7 +766,7 @@ namespace etl
|
||||
// 2nd template argument of base case defaults to int to ensure that this partial specialization is always tried first
|
||||
template <typename T>
|
||||
struct is_convertible_to_int<T, decltype(static_cast<int>(declval<T>()))>
|
||||
: true_type
|
||||
: true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -776,7 +776,7 @@ namespace etl
|
||||
: integral_constant<bool, private_type_traits::is_convertible_to_int<T>::value &&
|
||||
!is_class<T>::value &&
|
||||
!is_arithmetic<T>::value &&
|
||||
!is_reference<T>::value>
|
||||
!is_reference<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
@ -860,6 +860,42 @@ namespace etl
|
||||
public:
|
||||
static ETL_CONSTANT bool value = decltype(test<TFrom>(0))::value;
|
||||
};
|
||||
#else
|
||||
namespace private_type_traits
|
||||
{
|
||||
typedef char yes;
|
||||
struct no { char dummy[2]; };
|
||||
|
||||
template <typename TFrom, typename TTo>
|
||||
struct is_convertible_impl
|
||||
{
|
||||
static yes test(TTo);
|
||||
static no test(...);
|
||||
static TFrom make();
|
||||
static const bool value = (sizeof(test(make())) == sizeof(yes));
|
||||
};
|
||||
|
||||
template <typename TTo>
|
||||
struct is_convertible_impl<void, TTo>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename TFrom>
|
||||
struct is_convertible_impl<TFrom, void>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_convertible_impl<void, void>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename TFrom, typename TTo>
|
||||
struct is_convertible : etl::bool_constant<private_type_traits::is_convertible_impl<TFrom, TTo>::value> {};
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
@ -1408,6 +1444,42 @@ typedef integral_constant<bool, true> true_type;
|
||||
public:
|
||||
static ETL_CONSTANT bool value = decltype(test<TFrom>(0))::value;
|
||||
};
|
||||
#else
|
||||
namespace private_type_traits
|
||||
{
|
||||
typedef char yes;
|
||||
struct no { char dummy[2]; };
|
||||
|
||||
template <typename TFrom, typename TTo>
|
||||
struct is_convertible_impl
|
||||
{
|
||||
static yes test(TTo);
|
||||
static no test(...);
|
||||
static TFrom make();
|
||||
static const bool value = (sizeof(test(make())) == sizeof(yes));
|
||||
};
|
||||
|
||||
template <typename TTo>
|
||||
struct is_convertible_impl<void, TTo>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename TFrom>
|
||||
struct is_convertible_impl<TFrom, void>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_convertible_impl<void, void>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename TFrom, typename TTo>
|
||||
struct is_convertible : etl::bool_constant<private_type_traits::is_convertible_impl<TFrom, TTo>::value> {};
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
@ -1542,13 +1614,13 @@ typedef integral_constant<bool, true> true_type;
|
||||
/// Template to determine if a type is one of a specified list.
|
||||
///\ingroup types
|
||||
template <typename T,
|
||||
typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
|
||||
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
|
||||
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
|
||||
typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
|
||||
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
|
||||
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
|
||||
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
|
||||
struct is_one_of
|
||||
{
|
||||
static const bool value =
|
||||
static const bool value =
|
||||
etl::is_same<T, T1>::value ||
|
||||
etl::is_same<T, T2>::value ||
|
||||
etl::is_same<T, T3>::value ||
|
||||
@ -1640,7 +1712,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
//***************************************************************************
|
||||
/// Get the Nth base of a recursively inherited type.
|
||||
/// Requires that the class has defined 'base_type'.
|
||||
//***************************************************************************
|
||||
//***************************************************************************
|
||||
// Recursive definition of the type.
|
||||
template <size_t Index, typename TType>
|
||||
struct nth_base
|
||||
@ -2185,7 +2257,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// is_constructible
|
||||
namespace private_type_traits
|
||||
namespace private_type_traits
|
||||
{
|
||||
template <class, class T, class... TArgs>
|
||||
struct is_constructible_ : etl::false_type {};
|
||||
@ -2364,7 +2436,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct common_type_2_impl
|
||||
struct common_type_2_impl
|
||||
: decay_conditional_result<const T1&, const T2&>
|
||||
{
|
||||
};
|
||||
@ -2709,7 +2781,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
struct is_member_pointer_helper<T TObject::*> : etl::true_type {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T>
|
||||
struct is_member_pointer : private_type_traits::is_member_pointer_helper<typename etl::remove_cv<T>::type> {};
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
@ -2802,10 +2874,10 @@ typedef integral_constant<bool, true> true_type;
|
||||
//***************************************************************************
|
||||
namespace private_type_traits
|
||||
{
|
||||
template<typename>
|
||||
template<typename>
|
||||
struct is_member_object_pointer_helper : public etl::false_type {};
|
||||
|
||||
template<typename T, typename TObject>
|
||||
template<typename T, typename TObject>
|
||||
struct is_member_object_pointer_helper<T TObject::*> : public etl::negation<etl::is_function<T>> {};
|
||||
}
|
||||
|
||||
@ -3027,6 +3099,60 @@ typedef integral_constant<bool, true> true_type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename, typename = void>
|
||||
struct has_size : etl::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct has_size<T, void_t<decltype(etl::declval<T>().size())> >
|
||||
: etl::true_type {};
|
||||
#else
|
||||
template <typename T>
|
||||
struct has_size
|
||||
{
|
||||
private:
|
||||
typedef char yes;
|
||||
struct no { char dummy[2]; };
|
||||
|
||||
template <typename U>
|
||||
static yes test_size(char (*)[sizeof(&U::size)]);
|
||||
|
||||
template <typename U>
|
||||
static no test_size(...);
|
||||
|
||||
public:
|
||||
|
||||
static const bool value = (sizeof(test_size<T>(0)) == sizeof(yes));
|
||||
};
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename, typename = void>
|
||||
struct has_data : etl::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct has_data<T, void_t<decltype(etl::declval<T>().data())> >
|
||||
: etl::true_type {};
|
||||
#else
|
||||
template <typename T>
|
||||
struct has_data
|
||||
{
|
||||
private:
|
||||
typedef char yes;
|
||||
struct no { char dummy[2]; };
|
||||
|
||||
template <typename U>
|
||||
static yes test_data(char (*)[sizeof(&U::data)]);
|
||||
|
||||
template <typename U>
|
||||
static no test_data(...);
|
||||
|
||||
public:
|
||||
|
||||
static const bool value = (sizeof(test_data<T>(0)) == sizeof(yes));
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helper macros
|
||||
|
||||
48
scripts/clang-format-wrapper
Executable file
48
scripts/clang-format-wrapper
Executable file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
from shutil import which
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def get_correct_clang_format():
|
||||
path = which("clang-format-18")
|
||||
if path:
|
||||
return path
|
||||
|
||||
if which("clang-format") is None:
|
||||
raise Exception("no clang-format found")
|
||||
|
||||
result = subprocess.run(
|
||||
["clang-format", "--version"], capture_output=True, text=True, check=True
|
||||
)
|
||||
match = re.search(r"\b(\d+\.\d+\.\d+)\b", result.stdout)
|
||||
if not match:
|
||||
raise Exception(
|
||||
f"could not determine clang-format version from: {result.stdout.strip()}"
|
||||
)
|
||||
version = match.group(1)
|
||||
if version.split(".")[0] != "18":
|
||||
raise Exception(f"clang-format version 18 required. Found {version}")
|
||||
|
||||
return "clang-format"
|
||||
|
||||
|
||||
def main():
|
||||
clang_format = get_correct_clang_format()
|
||||
try:
|
||||
completed = subprocess.run([clang_format] + sys.argv[1:])
|
||||
except FileNotFoundError:
|
||||
print(f"error: clang-format not found at '{clang_format}'", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except PermissionError:
|
||||
print(f"error: permission denied when running '{clang_format}'", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except OSError as exc:
|
||||
print(f"error: failed to run '{clang_format}': {exc}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
sys.exit(completed.returncode)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -129,6 +129,29 @@ def update_library_properties(filename):
|
||||
f.write(line)
|
||||
f.write('\n')
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def update_zephyr_module():
|
||||
print('')
|
||||
print('Updating zephyr/module.yml')
|
||||
|
||||
zephyr_module = os.path.join(etl_dir, 'zephyr', 'module.yml')
|
||||
|
||||
with open(zephyr_module, 'r') as f:
|
||||
text = f.read().splitlines()
|
||||
|
||||
search_purl = 'pkg:github/ETLCPP/etl@'
|
||||
|
||||
for i in range(len(text)):
|
||||
if search_purl in text[i]:
|
||||
idx = text[i].find(search_purl)
|
||||
text[i] = text[i][:idx] + search_purl + full_version
|
||||
print(text[i])
|
||||
|
||||
with open(zephyr_module, 'w') as f:
|
||||
for line in text:
|
||||
f.write(line)
|
||||
f.write('\n')
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def update_versions():
|
||||
print('')
|
||||
@ -149,6 +172,8 @@ def update_versions():
|
||||
|
||||
update_library_properties(os.path.join(etl_dir, 'library.properties'))
|
||||
|
||||
update_zephyr_module()
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
update_versions()
|
||||
|
||||
@ -86,6 +86,7 @@ add_executable(etl_tests
|
||||
test_closure.cpp
|
||||
test_closure_constexpr.cpp
|
||||
test_compare.cpp
|
||||
test_concepts.cpp
|
||||
test_constant.cpp
|
||||
test_const_map.cpp
|
||||
test_const_map_constexpr.cpp
|
||||
@ -172,6 +173,7 @@ add_executable(etl_tests
|
||||
test_endian.cpp
|
||||
test_enum_type.cpp
|
||||
test_error_handler.cpp
|
||||
test_etl_assert.cpp
|
||||
test_etl_traits.cpp
|
||||
test_exception.cpp
|
||||
test_expected.cpp
|
||||
@ -183,6 +185,7 @@ add_executable(etl_tests
|
||||
test_flat_multiset.cpp
|
||||
test_flat_set.cpp
|
||||
test_fnv_1.cpp
|
||||
test_format.cpp
|
||||
test_format_spec.cpp
|
||||
test_forward_list.cpp
|
||||
test_forward_list_shared_pool.cpp
|
||||
@ -194,10 +197,12 @@ add_executable(etl_tests
|
||||
test_hash.cpp
|
||||
test_hfsm.cpp
|
||||
test_hfsm_recurse_to_inner_state_on_start.cpp
|
||||
test_hfsm_transition_on_enter.cpp
|
||||
test_histogram.cpp
|
||||
test_index_of_type.cpp
|
||||
test_indirect_vector.cpp
|
||||
test_indirect_vector_external_buffer.cpp
|
||||
test_inplace_function.cpp
|
||||
test_instance_count.cpp
|
||||
test_integral_limits.cpp
|
||||
test_intrusive_forward_list.cpp
|
||||
@ -206,7 +211,9 @@ add_executable(etl_tests
|
||||
test_intrusive_queue.cpp
|
||||
test_intrusive_stack.cpp
|
||||
test_invert.cpp
|
||||
test_invoke.cpp
|
||||
test_io_port.cpp
|
||||
test_is_invocable.cpp
|
||||
test_iterator.cpp
|
||||
test_jenkins.cpp
|
||||
test_largest.cpp
|
||||
@ -259,6 +266,7 @@ add_executable(etl_tests
|
||||
test_pool.cpp
|
||||
test_pool_external_buffer.cpp
|
||||
test_priority_queue.cpp
|
||||
test_print.cpp
|
||||
test_pseudo_moving_average.cpp
|
||||
test_quantize.cpp
|
||||
test_queue.cpp
|
||||
@ -286,6 +294,7 @@ add_executable(etl_tests
|
||||
test_scaled_rounding.cpp
|
||||
test_set.cpp
|
||||
test_shared_message.cpp
|
||||
test_signal.cpp
|
||||
test_singleton.cpp
|
||||
test_singleton_base.cpp
|
||||
test_smallest.cpp
|
||||
|
||||
@ -113,6 +113,12 @@ struct non_random_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iter
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool operator ==(const non_random_iterator<T>& lhs, const non_random_iterator<T>& rhs)
|
||||
{
|
||||
return lhs.ptr == rhs.ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator !=(const non_random_iterator<T>& lhs, const non_random_iterator<T>& rhs)
|
||||
{
|
||||
|
||||
0
test/run-syntax-checks.sh
Normal file → Executable file
0
test/run-syntax-checks.sh
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,7 @@ SOFTWARE.
|
||||
#include "etl/container.h"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#if ETL_NOT_USING_STL
|
||||
|
||||
@ -145,6 +146,34 @@ namespace
|
||||
size_t compiletime_size = sizeof(etl::array_size(data));
|
||||
CHECK_EQUAL(SIZE, compiletime_size);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_stl_style_container_data)
|
||||
{
|
||||
const size_t SIZE = 10UL;
|
||||
std::vector<int> data(SIZE);
|
||||
const std::vector<int> cdata(SIZE);
|
||||
|
||||
int* pdata = ETL_OR_STD17::data(data);
|
||||
const int* pcdata = ETL_OR_STD17::data(cdata);
|
||||
|
||||
CHECK(data.data() == pdata);
|
||||
CHECK(cdata.data() == pcdata);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_c_array_data)
|
||||
{
|
||||
const size_t SIZE = 10UL;
|
||||
int data[SIZE];
|
||||
const int cdata[SIZE] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
|
||||
int* pdata = ETL_OR_STD17::data(data);
|
||||
const int* pcdata = ETL_OR_STD17::data(cdata);
|
||||
|
||||
CHECK(&data[0] == pdata);
|
||||
CHECK(&cdata[0] == pcdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,8 @@ SOFTWARE.
|
||||
#include "etl/error_handler.h"
|
||||
#include "etl/exception.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace
|
||||
{
|
||||
class TestException1 : public etl::exception
|
||||
|
||||
@ -197,6 +197,7 @@ namespace
|
||||
CHECK_EQUAL("-6759414", test_format(s, "{}", static_cast<int32_t>(-6759414)));
|
||||
}
|
||||
|
||||
#if ETL_USING_FORMAT_FLOATING_POINT
|
||||
//*************************************************************************
|
||||
TEST(test_format_float)
|
||||
{
|
||||
@ -266,6 +267,7 @@ namespace
|
||||
CHECK_EQUAL("0x1.92a738p-5", test_format(s, "{:a}", 0.0000015f));
|
||||
CHECK_EQUAL("0x1.6345785d8ap+e", test_format(s, "{:a}", 100000000000000000.l));
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_format_char_array)
|
||||
|
||||
@ -515,7 +515,7 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST(test_fsm_emergency_stop)
|
||||
{
|
||||
motorControl.Initialise(stateList, ETL_OR_STD17::size(stateList));
|
||||
motorControl.Initialise(stateList, ETL_OR_STD17::size(stateList));
|
||||
motorControl.reset();
|
||||
motorControl.ClearStatistics();
|
||||
|
||||
@ -758,7 +758,7 @@ namespace
|
||||
CHECK_EQUAL(StateId::Running, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
auto id2 = motorControl.transition_to(StateId::Idle);
|
||||
|
||||
|
||||
// Now in Locked state.
|
||||
CHECK_EQUAL(StateId::Locked, int(id2));
|
||||
CHECK_EQUAL(StateId::Locked, int(motorControl.get_state_id()));
|
||||
|
||||
@ -85,6 +85,24 @@ namespace
|
||||
mutable std::string result;
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
// Lightweight type used to verify transparent heterogeneous comparison.
|
||||
// Only operator<(int, Wrapper) is defined; operator<(Wrapper, int) is
|
||||
// intentionally absent. less_equal<void> is implemented as
|
||||
// !(rhs < lhs), so less_equal<void>{}(Wrapper, int) needs
|
||||
// operator<(int, Wrapper) which IS provided.
|
||||
struct Wrapper
|
||||
{
|
||||
int value;
|
||||
constexpr explicit Wrapper(int v) : value(v) {}
|
||||
};
|
||||
|
||||
// int < Wrapper -- defined
|
||||
constexpr bool operator<(int lhs, const Wrapper& rhs) { return lhs < rhs.value; }
|
||||
|
||||
// Wrapper < int -- intentionally NOT defined
|
||||
#endif
|
||||
|
||||
SUITE(test_functional)
|
||||
{
|
||||
//*************************************************************************
|
||||
@ -101,6 +119,32 @@ namespace
|
||||
CHECK((compare<etl::less_equal<int>>(1, 2)));
|
||||
CHECK(!(compare<etl::less_equal<int>>(2, 1)));
|
||||
CHECK((compare<etl::less_equal<int>>(1, 1)));
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
CHECK((compare<etl::less_equal<void>>(1, 2)));
|
||||
CHECK(!(compare<etl::less_equal<void>>(2, 1)));
|
||||
CHECK((compare<etl::less_equal<void>>(1, 1)));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_less_equal_void_heterogeneous)
|
||||
{
|
||||
#if ETL_USING_CPP11
|
||||
// less_equal<void>{}(lhs, rhs) is !(rhs < lhs).
|
||||
// With only operator<(int, Wrapper) defined, we can call
|
||||
// less_equal<void>{}(Wrapper, int) because the implementation
|
||||
// evaluates !(int < Wrapper).
|
||||
|
||||
// Wrapper(1) <= 2 → !(2 < Wrapper(1)) → !(2 < 1) → !false → true
|
||||
CHECK((etl::less_equal<void>{}(Wrapper(1), 2)));
|
||||
|
||||
// Wrapper(2) <= 1 → !(1 < Wrapper(2)) → !(1 < 2) → !true → false
|
||||
CHECK(!(etl::less_equal<void>{}(Wrapper(2), 1)));
|
||||
|
||||
// Wrapper(3) <= 3 → !(3 < Wrapper(3)) → !(3 < 3) → !false → true
|
||||
CHECK((etl::less_equal<void>{}(Wrapper(3), 3)));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -117,6 +161,32 @@ namespace
|
||||
CHECK(!(compare<etl::greater_equal<int>>(1, 2)));
|
||||
CHECK((compare<etl::greater_equal<int>>(2, 1)));
|
||||
CHECK((compare<etl::greater_equal<int>>(1, 1)));
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
CHECK(!(compare<etl::greater_equal<void>>(1, 2)));
|
||||
CHECK((compare<etl::greater_equal<void>>(2, 1)));
|
||||
CHECK((compare<etl::greater_equal<void>>(1, 1)));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_greater_equal_void_heterogeneous)
|
||||
{
|
||||
#if ETL_USING_CPP11
|
||||
// greater_equal<void>{}(lhs, rhs) is !(lhs < rhs).
|
||||
// With only operator<(int, Wrapper) defined, we can call
|
||||
// greater_equal<void>{}(int, Wrapper) because the implementation
|
||||
// evaluates !(int < Wrapper).
|
||||
|
||||
// 2 >= Wrapper(1) → !(2 < Wrapper(1)) → !(2 < 1) → !false → true
|
||||
CHECK((etl::greater_equal<void>{}(2, Wrapper(1))));
|
||||
|
||||
// 1 >= Wrapper(2) → !(1 < Wrapper(2)) → !(1 < 2) → !true → false
|
||||
CHECK(!(etl::greater_equal<void>{}(1, Wrapper(2))));
|
||||
|
||||
// 3 >= Wrapper(3) → !(3 < Wrapper(3)) → !(3 < 3) → !false → true
|
||||
CHECK((etl::greater_equal<void>{}(3, Wrapper(3))));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -574,12 +574,11 @@ namespace
|
||||
constexpr uint16_t absolute1 = etl::absolute(int16_t(0));
|
||||
constexpr uint16_t absolute2 = etl::absolute(int16_t(32767));
|
||||
constexpr uint16_t absolute3 = etl::absolute(int16_t(-32767));
|
||||
constexpr uint16_t absolute4 = etl::absolute(int16_t(-32768));
|
||||
//constexpr uint16_t absolute4 = etl::absolute(int16_t(-32768)); // Compile error
|
||||
|
||||
CHECK_EQUAL(uint16_t(0), absolute1);
|
||||
CHECK_EQUAL(uint16_t(32767), absolute2);
|
||||
CHECK_EQUAL(uint16_t(32767), absolute3);
|
||||
CHECK_EQUAL(uint16_t(32768), absolute4);
|
||||
|
||||
constexpr uint16_t absolute5 = etl::absolute(uint16_t(0));
|
||||
constexpr uint16_t absolute6 = etl::absolute(uint16_t(65535));
|
||||
|
||||
@ -1627,5 +1627,23 @@ namespace
|
||||
}
|
||||
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_not_constructible_from_rvalue_container)
|
||||
{
|
||||
#if ETL_USING_CPP17
|
||||
CHECK(!(etl::is_constructible_v<View, StlVData&&>));
|
||||
CHECK(!(etl::is_constructible_v<CView, StlVData&&>));
|
||||
|
||||
CHECK(!(etl::is_constructible_v<View, EtlData&&>));
|
||||
CHECK(!(etl::is_constructible_v<View, StlData&&>));
|
||||
#else
|
||||
CHECK(!(etl::is_constructible<View, StlVData&&>::value));
|
||||
CHECK(!(etl::is_constructible<CView, StlVData&&>::value));
|
||||
|
||||
CHECK(!(etl::is_constructible<View, EtlData&&>::value));
|
||||
CHECK(!(etl::is_constructible<View, StlData&&>::value));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -496,13 +496,19 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST(test_empty)
|
||||
{
|
||||
View view1(etldata.begin(), etldata.begin());
|
||||
CHECK(!view1.empty());
|
||||
|
||||
EView view2(etldata.begin(), etldata.begin());
|
||||
CHECK(view2.empty());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_construction_from_mismatched_size)
|
||||
{
|
||||
CHECK_THROW((View(etldata.begin(), etldata.begin())), etl::span_size_mismatch);
|
||||
CHECK_THROW((View(etldata.begin(), 1)), etl::span_size_mismatch);
|
||||
CHECK_THROW((View(etldata.begin(), etldata.size() - 1)), etl::span_size_mismatch);
|
||||
CHECK_THROW((View(etldata.begin(), etldata.size() + 1)), etl::span_size_mismatch);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_size)
|
||||
{
|
||||
@ -664,7 +670,7 @@ namespace
|
||||
CHECK_EQUAL(sub1.size(), cspan1.extent);
|
||||
CHECK_EQUAL(sub1.size(), cspan1.size());
|
||||
|
||||
auto span2 = view.subspan<2>();
|
||||
auto span2 = view.subspan<2>();
|
||||
isEqual = std::equal(sub2.begin(), sub2.end(), span2.begin());
|
||||
CHECK(isEqual);
|
||||
CHECK_EQUAL(span2.size(), span2.extent);
|
||||
@ -804,7 +810,7 @@ namespace
|
||||
|
||||
//*************************************************************************
|
||||
#include "etl/private/diagnostic_unused_function_push.h"
|
||||
|
||||
|
||||
struct C_issue_482 {};
|
||||
|
||||
void f_issue_482(etl::span<char>)
|
||||
@ -1220,7 +1226,7 @@ namespace
|
||||
etl::span<int, 5> span2(span1);
|
||||
//etl::span<int, 10> span3(span1); // This line should fail to compile.
|
||||
}
|
||||
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_reinterpret_as)
|
||||
{
|
||||
@ -1306,5 +1312,23 @@ namespace
|
||||
}
|
||||
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_not_constructible_from_rvalue_container)
|
||||
{
|
||||
#if ETL_USING_CPP17
|
||||
CHECK(!(etl::is_constructible_v<View, StlVData&&>));
|
||||
CHECK(!(etl::is_constructible_v<CView, StlVData&&>));
|
||||
|
||||
CHECK(!(etl::is_constructible_v<View, EtlData&&>));
|
||||
CHECK(!(etl::is_constructible_v<View, StlData&&>));
|
||||
#else
|
||||
CHECK(!(etl::is_constructible<View, StlVData&&>::value));
|
||||
CHECK(!(etl::is_constructible<CView, StlVData&&>::value));
|
||||
|
||||
CHECK(!(etl::is_constructible<View, EtlData&&>::value));
|
||||
CHECK(!(etl::is_constructible<View, StlData&&>::value));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3552,6 +3552,7 @@
|
||||
<ClInclude Include="..\..\include\etl\monostate.h" />
|
||||
<ClInclude Include="..\..\include\etl\not_null.h" />
|
||||
<ClInclude Include="..\..\include\etl\poly_span.h" />
|
||||
<ClInclude Include="..\..\include\etl\print.h" />
|
||||
<ClInclude Include="..\..\include\etl\private\bitset_legacy.h" />
|
||||
<ClInclude Include="..\..\include\etl\private\bitset_new.h" />
|
||||
<ClInclude Include="..\..\include\etl\private\chrono\day.h" />
|
||||
@ -10362,6 +10363,7 @@
|
||||
<ClCompile Include="..\test_not_null_unique_pointer.cpp" />
|
||||
<ClCompile Include="..\test_poly_span_dynamic_extent.cpp" />
|
||||
<ClCompile Include="..\test_poly_span_fixed_extent.cpp" />
|
||||
<ClCompile Include="..\test_print.cpp" />
|
||||
<ClCompile Include="..\test_pseudo_moving_average.cpp" />
|
||||
<ClCompile Include="..\test_delegate.cpp" />
|
||||
<ClCompile Include="..\test_delegate_cpp03.cpp" />
|
||||
|
||||
@ -2,3 +2,6 @@ name: etl
|
||||
build:
|
||||
cmake: zephyr
|
||||
kconfig: zephyr/Kconfig
|
||||
security:
|
||||
external-references:
|
||||
- pkg:github/ETLCPP/etl@20.46.2
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user