mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Merge branch 'development' into fix-warnings-uninitialized
This commit is contained in:
commit
beee205bf1
72
.github/workflows/coverage.yml
vendored
Normal file
72
.github/workflows/coverage.yml
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
name: coverage
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master, pull-request/* ]
|
||||
pull_request:
|
||||
branches: [ master, pull-request/* ]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
# Allow only one concurrent deployment to GitHub Pages
|
||||
concurrency:
|
||||
group: coverage-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
# Grant GITHUB_TOKEN the minimum permissions needed at the workflow level
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
coverage:
|
||||
name: Generate Coverage Report
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y lcov llvm gcc g++ clang cmake
|
||||
|
||||
- name: Build, test, and collect coverage
|
||||
run: |
|
||||
cd test
|
||||
./run-coverage.sh
|
||||
|
||||
- name: Upload coverage report artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-report
|
||||
path: test/build-coverage/coverage/
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload Pages artifact
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: test/build-coverage/coverage/
|
||||
|
||||
deploy-pages:
|
||||
name: Deploy to GitHub Pages
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
needs: coverage
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
# GitHub Repository settings
|
||||
# -> Settings -> Pages
|
||||
# -> Source: gh actions
|
||||
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.
|
||||
|
||||
6
docs/_config.yml
Normal file
6
docs/_config.yml
Normal file
@ -0,0 +1,6 @@
|
||||
plugins:
|
||||
- jekyll-relative-links
|
||||
relative_links:
|
||||
enabled: true
|
||||
include:
|
||||
- manchester.md
|
||||
7
docs/index.md
Normal file
7
docs/index.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: ETL documentation
|
||||
---
|
||||
|
||||
## Pages
|
||||
|
||||
* [Manchester](manchester.md)
|
||||
258
docs/manchester.md
Normal file
258
docs/manchester.md
Normal file
@ -0,0 +1,258 @@
|
||||
---
|
||||
title: Manchester encoding and decoding
|
||||
---
|
||||
|
||||
Efficient Manchester encoding and decoding of data. The Manchester code represents a data bit as a sequence of a 'high' and a 'low' value. In software this translates to a conversion from one to two bits, or in a practical situation, from `n` bytes to `n*2` bytes.
|
||||
|
||||
## See also
|
||||
|
||||
[Manchester code](https://en.wikipedia.org/wiki/Manchester_code)
|
||||
|
||||
## Features
|
||||
|
||||
- Normal and inverted Manchester encoding
|
||||
- Support for multiple encoding chunk sizes: 8-bit, 16-bit and 32-bit
|
||||
- Span-based operations or chunk-based operations
|
||||
- Constexpr functions for compile-time encoding/decoding (8-bit chunk size only)
|
||||
- Validation of encoded data
|
||||
|
||||
## Algorithm background
|
||||
|
||||
To encode the value `0b11001100` we must first duplicate all bits to create the value `0b1111000011110000`. We then perform an XOR of this value with the constant `0b1010101010101010` (`0xAAAA`) to obtain the Manchester coded value of `0b1010010110100101`. We have now replaced each `1` bit with the sequence `10` and each `0` bit with the sequence `01`.
|
||||
|
||||
### 2. Bit duplication
|
||||
|
||||
Bit duplication is achieved with the following steps. This is also called binary interleaving. The example shows encoding of an 8-bit value.
|
||||
|
||||
| Step | High Byte | Low Byte | Operation |
|
||||
|------|--------------------|--------------------|----------------------------|
|
||||
| 0 | `_ _ _ _ _ _ _ _` | `A B C D E F G H` | input value (i) |
|
||||
| 1 | `_ _ _ _ A B C D` | `_ _ _ _ E F G H` | `(i \| (i << 4)) & 0x0F0F` |
|
||||
| 2 | `_ _ A B _ _ C D` | `_ _ E F _ _ G H` | `(i \| (i << 2)) & 0x3333` |
|
||||
| 3 | `_ A _ B _ C _ D` | `_ E _ F _ G _ H` | `(i \| (i << 1)) & 0x5555` |
|
||||
| 4 | `A A B B C C D D` | `E E F F G G H H` | `(i \| (i << 1))` |
|
||||
|
||||
This process can be easily extended to 16-bit or 32-bit values by adding additional steps to the bit duplication.
|
||||
|
||||
### 3. Manchester Decoding
|
||||
|
||||
Manchester decoding is done in a similar, but reversed way.
|
||||
|
||||
### 4. Error Detection
|
||||
|
||||
Error detection in Manchester coded data is done by comparing 2 neighboring bits. If they are
|
||||
equal, then there is an error in the encoded input data.
|
||||
|
||||
Comparing all 8 bit pairs in a 16-bit word is done as follows.
|
||||
|
||||
| Step | Binary Value | Operation | Description |
|
||||
|------|--------------|-------------------|-----------------------------------------------------------------------------------------------|
|
||||
| 1 | `11011000` | Original | First bit pair (lsb, 00) is invalid. Last bit pair is also invalid. Other bit pairs are valid |
|
||||
| 2 | `01101100` | Shift right by 1 | Shift the original value right by one bit |
|
||||
| 3 | `10110100` | XOR | XOR the original with the shifted value |
|
||||
| 4 | `01010101` | Mask with 0x55 | Apply mask to isolate bit pairs |
|
||||
| 5 | `00010100` | Result | If result is not equal to 0x55, there was an error in the input |
|
||||
|
||||
## Analysis
|
||||
|
||||
Most traditional ways to Manchester encode data consist of a loop over all bits and a nested if-statement to check the value of the current bit. This approach does not scale well to increasing number of bits. The algorithm implemented here contains no conditional code and scales well. Doubling the number of processed bits per step (the chunk size) adds a single row to the bit duplication table. Because of the lack of loops and conditional code, this algorithm is likely to perform better than traditional ones on simple processors or when compiler optimization is disabled. On modern, powerful processors with caches and advanced optimization possibilities this algorithm may not show much benefit. In any case, the performance of the algorithm depends heavily on the processor type, compiler and compiler (optimization) settings.
|
||||
|
||||
## API Reference
|
||||
|
||||
### Classes
|
||||
|
||||
Classes `etl::manchester` and `etl::manchester_inverted` contain static functions for encoding, decoding and validity checking. It is not necessary to instantiate objects of these classes.
|
||||
|
||||
#### etl::manchester
|
||||
|
||||
```cpp
|
||||
typedef manchester_base<private_manchester::manchester_type_normal> manchester;
|
||||
```
|
||||
|
||||
Manchester encoder using normal encoding (no inversion).
|
||||
|
||||
#### etl::manchester_inverted
|
||||
|
||||
```cpp
|
||||
typedef manchester_base<private_manchester::manchester_type_inverted> manchester_inverted;
|
||||
```
|
||||
|
||||
Manchester encoder using inverted encoding.
|
||||
|
||||
### Encoding Functions
|
||||
|
||||
#### Encode single value
|
||||
|
||||
```cpp
|
||||
template <typename TDecoded>
|
||||
static ETL_CONSTEXPR14 typename encoded<TDecoded>::type encode(TDecoded decoded)
|
||||
```
|
||||
|
||||
Encodes a single value using Manchester encoding.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `decoded`: The value to encode (`uint8_t`, `uint16_t`, or `uint32_t`)
|
||||
|
||||
**Returns:**
|
||||
|
||||
- The Manchester encoded value (twice the bit width of input)
|
||||
|
||||
**Example:**
|
||||
|
||||
```cpp
|
||||
uint16_t encoded = etl::manchester::encode(0x55);
|
||||
```
|
||||
|
||||
#### Encode range
|
||||
|
||||
```cpp
|
||||
template <typename TChunk = uint_least8_t>
|
||||
static ETL_CONSTEXPR14 void encode(etl::span<const uint_least8_t> decoded,
|
||||
etl::span<uint_least8_t> encoded)
|
||||
```
|
||||
|
||||
Encodes a span of data using the specified chunk size.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `decoded`: Source data to encode
|
||||
- `encoded`: Destination for encoded data (must be twice the size of `decoded`)
|
||||
|
||||
**Template Parameters:**
|
||||
|
||||
- `TChunk`: Chunk size for encoding (`uint8_t`, `uint16_t` or `uint32_t`)
|
||||
|
||||
**Example:**
|
||||
|
||||
```cpp
|
||||
std::array<uint8_t, 4> data = {0x12, 0x34, 0x56, 0x78};
|
||||
std::array<uint8_t, 8> encoded_data1{};
|
||||
std::array<uint8_t, 8> encoded_data2{};
|
||||
|
||||
// Encode with TChunk == uint8_t
|
||||
etl::manchester::encode(data, encoded_data1);
|
||||
|
||||
// Encode with TChunk == uint32_t
|
||||
etl::manchester::encode<uint32_t>(data, encoded_data2);
|
||||
```
|
||||
|
||||
### Decoding Functions
|
||||
|
||||
#### Decode single value
|
||||
|
||||
```cpp
|
||||
template <typename TEncoded>
|
||||
static ETL_CONSTEXPR14 typename decoded<TEncoded>::type decode(TEncoded encoded)
|
||||
```
|
||||
|
||||
Decodes a single Manchester encoded value.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `encoded`: The encoded value to decode (`uint16_t`, `uint32_t`, or `uint64_t`)
|
||||
|
||||
**Returns:**
|
||||
|
||||
- The Manchester decoded value (half the bit width of input)
|
||||
|
||||
**Example:**
|
||||
|
||||
```cpp
|
||||
uint8_t decoded = etl::manchester::decode(0x5A5A);
|
||||
```
|
||||
|
||||
#### Decode range
|
||||
|
||||
```cpp
|
||||
template <typename TChunk = typename private_manchester::encoded<uint_least8_t>::type>
|
||||
static ETL_CONSTEXPR14 void decode(etl::span<const uint_least8_t> encoded,
|
||||
etl::span<uint_least8_t> decoded)
|
||||
```
|
||||
|
||||
Decodes a span of Manchester encoded data.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `encoded`: Source data to decode
|
||||
- `decoded`: Destination for decoded data (must be half the size of `encoded`)
|
||||
|
||||
**Template Parameters:**
|
||||
|
||||
- `TChunk`: Chunk type for decoding (`uint16_t`, `uint32_t`, or `uint64_t`)
|
||||
|
||||
**Example:**
|
||||
|
||||
```cpp
|
||||
std::array<uint8_t, 8> encoded = {/* ... */};
|
||||
std::array<uint8_t, 4> decoded1 {};
|
||||
std::array<uint8_t, 4> decoded2 {};
|
||||
|
||||
// Decode with TChunk == uint16_t
|
||||
etl::manchester::decode(encoded, decoded1);
|
||||
|
||||
// Decode with TChunk == uint64_t
|
||||
etl::manchester::decode<uint64_t>(encoded, decoded2);
|
||||
```
|
||||
|
||||
### Validation Functions
|
||||
|
||||
#### Single value
|
||||
|
||||
```cpp
|
||||
template <typename TChunk>
|
||||
static ETL_CONSTEXPR14 bool is_valid(TChunk encoded)
|
||||
```
|
||||
|
||||
Validates that a single value contains valid Manchester encoded data.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `encoded`: The encoded value to validate
|
||||
|
||||
**Returns:**
|
||||
|
||||
- `true` if the value contains valid Manchester encoded data, `false` otherwise
|
||||
|
||||
**Example:**
|
||||
|
||||
```cpp
|
||||
bool valid = etl::manchester::is_valid(0x5A5A);
|
||||
```
|
||||
|
||||
#### Range
|
||||
|
||||
```cpp
|
||||
static ETL_CONSTEXPR14 bool is_valid(etl::span<const uint_least8_t> encoded)
|
||||
```
|
||||
|
||||
Validates that a range contains valid Manchester encoded data.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `encoded`: The range of encoded data to validate
|
||||
|
||||
**Returns:**
|
||||
|
||||
- `true` if all data is valid Manchester encoding, `false` otherwise
|
||||
|
||||
**Example:**
|
||||
|
||||
```cpp
|
||||
std::array<uint8_t, 8> encoded_data = {/* ... */};
|
||||
bool valid = etl::manchester::is_valid(encoded_data);
|
||||
```
|
||||
|
||||
## Supported Types
|
||||
|
||||
### Input/chunk types for encoding
|
||||
|
||||
- `uint8_t` → `uint16_t` (if 8-bit types are supported)
|
||||
- `uint16_t` → `uint32_t`
|
||||
- `uint32_t` → `uint64_t` (if 64-bit types are supported)
|
||||
|
||||
### Input/chunk types for decoding
|
||||
|
||||
- `uint16_t` → `uint8_t` (if 8-bit types are supported)
|
||||
- `uint32_t` → `uint16_t`
|
||||
- `uint64_t` → `uint32_t` (if 64-bit types are supported)
|
||||
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;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
|
||||
@ -169,21 +169,19 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructor from value type.
|
||||
/// Converting constructor from value type.
|
||||
/// Constructs T in-place from U&&, without requiring T to be
|
||||
/// copy/move constructible.
|
||||
//***************************************************************************
|
||||
template <typename U,
|
||||
typename etl::enable_if<
|
||||
etl::is_constructible<T, U&&>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, optional_impl>::value, int>::type = 0>
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional_impl(const T& value_)
|
||||
optional_impl(U&& value_)
|
||||
{
|
||||
storage.construct(value_);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructor from value type.
|
||||
//***************************************************************************
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional_impl(T&& value_)
|
||||
{
|
||||
storage.construct(etl::move(value_));
|
||||
storage.construct(etl::forward<U>(value_));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
@ -280,23 +278,24 @@ namespace etl
|
||||
//***************************************************************************
|
||||
/// Assignment operator from value type.
|
||||
//***************************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename U,
|
||||
typename etl::enable_if<
|
||||
etl::is_constructible<T, U&&>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, optional_impl>::value, int>::type = 0>
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional_impl& operator =(U&& value_)
|
||||
{
|
||||
storage.construct(etl::forward<U>(value_));
|
||||
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional_impl& operator =(const T& value_)
|
||||
{
|
||||
storage.construct(value_);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Assignment operator from value type.
|
||||
//***************************************************************************
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional_impl& operator =(T&& value_)
|
||||
{
|
||||
storage.construct(etl::move(value_));
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@ -1442,22 +1441,36 @@ namespace etl
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Construct from value type.
|
||||
/// Converting constructor from value type.
|
||||
/// Constructs T in-place from U&&, without requiring T to be
|
||||
/// copy/move constructible.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
template <typename U,
|
||||
typename etl::enable_if<
|
||||
etl::is_constructible<T, U&&>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value &&
|
||||
etl::is_pod<typename etl::remove_cv<T>::type>::value, int>::type = 0>
|
||||
ETL_CONSTEXPR14
|
||||
optional(const T& value_)
|
||||
: impl_t(value_)
|
||||
optional(U&& value_)
|
||||
: impl_t(etl::forward<U>(value_))
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from value type.
|
||||
/// Converting constructor from value type.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
template <typename U,
|
||||
typename etl::enable_if<
|
||||
etl::is_constructible<T, U&&>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value &&
|
||||
!etl::is_pod<typename etl::remove_cv<T>::type>::value, int>::type = 0>
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional(const T& value_)
|
||||
: impl_t(value_)
|
||||
optional(U&& value_)
|
||||
: impl_t(etl::forward<U>(value_))
|
||||
{
|
||||
}
|
||||
#else
|
||||
@ -1470,29 +1483,6 @@ namespace etl
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Move construct from value type.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14
|
||||
optional(T&& value_)
|
||||
: impl_t(etl::move(value_))
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Move construct from value type.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional(T&& value_)
|
||||
: impl_t(etl::move(value_))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Emplace construct from arguments.
|
||||
@ -1641,25 +1631,35 @@ namespace etl
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Assignment operator from value type.
|
||||
/// Converting assignment operator from value type.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
template <typename U,
|
||||
typename etl::enable_if<
|
||||
etl::is_constructible<T, U&&>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value &&
|
||||
etl::is_pod<typename etl::remove_cv<T>::type>::value, int>::type = 0>
|
||||
ETL_CONSTEXPR14
|
||||
optional& operator =(const T& value_)
|
||||
optional& operator =(U&& value_)
|
||||
{
|
||||
impl_t::operator=(value_);
|
||||
impl_t::operator=(etl::forward<U>(value_));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Assignment operator from value type.
|
||||
/// Converting assignment operator from value type.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
template <typename U,
|
||||
typename etl::enable_if<
|
||||
etl::is_constructible<T, U&&>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value &&
|
||||
!etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value &&
|
||||
!etl::is_pod<typename etl::remove_cv<T>::type>::value, int>::type = 0>
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional& operator =(const T& value_)
|
||||
optional& operator =(U&& value_)
|
||||
{
|
||||
impl_t::operator=(value_);
|
||||
impl_t::operator=(etl::forward<U>(value_));
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -1675,32 +1675,6 @@ namespace etl
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Move assignment operator from value type.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14
|
||||
optional& operator =(T&& value_)
|
||||
{
|
||||
impl_t::operator=(etl::move(value_));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Move assignment operator from value type.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional& operator =(T&& value_)
|
||||
{
|
||||
impl_t::operator=(etl::move(value_));
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns an iterator to the beginning of the optional.
|
||||
//***************************************************************************
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -33,7 +33,11 @@ SOFTWARE.
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_CHRONO_SYSTEM_CLOCK_DURATION)
|
||||
#define ETL_CHRONO_SYSTEM_CLOCK_DURATION etl::chrono::nanoseconds
|
||||
#if (INT_MAX >= INT32_MAX)
|
||||
#define ETL_CHRONO_SYSTEM_CLOCK_DURATION etl::chrono::nanoseconds
|
||||
#else
|
||||
#define ETL_CHRONO_SYSTEM_CLOCK_DURATION etl::chrono::milliseconds
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_CHRONO_SYSTEM_CLOCK_IS_STEADY)
|
||||
@ -41,7 +45,11 @@ SOFTWARE.
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION)
|
||||
#define ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION etl::chrono::nanoseconds
|
||||
#if (INT_MAX >= INT32_MAX)
|
||||
#define ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION etl::chrono::nanoseconds
|
||||
#else
|
||||
#define ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION etl::chrono::milliseconds
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_CHRONO_HIGH_RESOLUTION_CLOCK_IS_STEADY)
|
||||
@ -49,7 +57,11 @@ SOFTWARE.
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_CHRONO_STEADY_CLOCK_DURATION)
|
||||
#define ETL_CHRONO_STEADY_CLOCK_DURATION etl::chrono::nanoseconds
|
||||
#if (INT_MAX >= INT32_MAX)
|
||||
#define ETL_CHRONO_STEADY_CLOCK_DURATION etl::chrono::nanoseconds
|
||||
#else
|
||||
#define ETL_CHRONO_STEADY_CLOCK_DURATION etl::chrono::milliseconds
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern "C" ETL_CHRONO_SYSTEM_CLOCK_DURATION::rep etl_get_system_clock();
|
||||
|
||||
@ -315,13 +315,17 @@ namespace etl
|
||||
/// Duration types
|
||||
//***********************************************************************
|
||||
#if (ETL_USING_64BIT_TYPES)
|
||||
#if (INT_MAX >= INT32_MAX)
|
||||
using nanoseconds = etl::chrono::duration<int64_t, etl::nano>;
|
||||
using microseconds = etl::chrono::duration<int64_t, etl::micro>;
|
||||
#endif
|
||||
using milliseconds = etl::chrono::duration<int64_t, etl::milli>;
|
||||
using seconds = etl::chrono::duration<int64_t, etl::ratio<1U>>;
|
||||
#else
|
||||
#if (INT_MAX >= INT32_MAX)
|
||||
using nanoseconds = etl::chrono::duration<int32_t, etl::nano>;
|
||||
using microseconds = etl::chrono::duration<int32_t, etl::micro>;
|
||||
#endif
|
||||
using milliseconds = etl::chrono::duration<int32_t, etl::milli>;
|
||||
using seconds = etl::chrono::duration<int32_t, etl::ratio<1U>>;
|
||||
#endif
|
||||
@ -811,6 +815,7 @@ namespace etl
|
||||
return etl::chrono::duration<double, milli>(s);
|
||||
}
|
||||
|
||||
#if (INT_MAX >= INT32_MAX)
|
||||
//***********************************************************************
|
||||
/// Literal for microseconds duration
|
||||
//***********************************************************************
|
||||
@ -848,7 +853,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
/// Literal for floating point microseconds duration
|
||||
/// Literal for floating point nanoseconds duration
|
||||
//***********************************************************************
|
||||
#if ETL_USING_VERBOSE_CHRONO_LITERALS
|
||||
inline ETL_CONSTEXPR14 etl::chrono::duration<double, nano> operator ""_nanoseconds(long double s) ETL_NOEXCEPT
|
||||
@ -858,6 +863,7 @@ namespace etl
|
||||
{
|
||||
return etl::chrono::duration<double, nano>(s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
@ -889,7 +1068,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT
|
||||
{
|
||||
return (pend - pbegin);
|
||||
return static_cast<size_t>(pend - pbegin);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -897,7 +1076,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT
|
||||
{
|
||||
return sizeof(element_type) * (pend - pbegin);
|
||||
return sizeof(element_type) * static_cast<size_t>(pend - pbegin);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -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));
|
||||
@ -1083,7 +1262,7 @@ namespace etl
|
||||
ETL_ASSERT(etl::is_aligned<etl::alignment_of<TNew>::value>(pbegin), ETL_ERROR(span_alignment_exception));
|
||||
|
||||
return etl::span<TNew, etl::dynamic_extent>(reinterpret_cast<TNew*>(pbegin),
|
||||
(pend - pbegin) * sizeof(element_type) / sizeof(TNew));
|
||||
static_cast<size_t>(pend - pbegin) * sizeof(element_type) / sizeof(TNew));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -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");
|
||||
|
||||
@ -276,7 +276,7 @@ namespace etl
|
||||
/// Implicit conversion
|
||||
//*********************************
|
||||
template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
etl::is_convertible<UHead, THead>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
tuple(tuple<UHead, UTail...>& other)
|
||||
@ -290,7 +290,7 @@ namespace etl
|
||||
/// Explicit conversion
|
||||
//*********************************
|
||||
template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
!etl::is_convertible<UHead, THead>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
explicit tuple(tuple<UHead, UTail...>& other)
|
||||
@ -304,7 +304,7 @@ namespace etl
|
||||
/// Implicit conversion
|
||||
//*********************************
|
||||
template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
etl::is_convertible<UHead, THead>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
tuple(const tuple<UHead, UTail...>& other)
|
||||
@ -318,7 +318,7 @@ namespace etl
|
||||
/// Explicit conversion
|
||||
//*********************************
|
||||
template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
!etl::is_convertible<UHead, THead>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
explicit tuple(const tuple<UHead, UTail...>& other)
|
||||
@ -332,7 +332,7 @@ namespace etl
|
||||
/// Implicit conversion
|
||||
//*********************************
|
||||
template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
etl::is_convertible<UHead, THead>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
tuple(tuple<UHead, UTail...>&& other)
|
||||
@ -399,7 +399,7 @@ namespace etl
|
||||
//*********************************
|
||||
template <typename UHead, typename... UTail, etl::enable_if_t<!is_tuple<etl::remove_reference_t<UHead>>::value &&
|
||||
(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
(number_of_types<THead, TTail...>() >= 1U) &&
|
||||
etl::is_convertible<UHead, THead>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
tuple(UHead&& head, UTail&&... tail) ETL_NOEXCEPT
|
||||
@ -428,8 +428,8 @@ namespace etl
|
||||
/// Implicit conversion.
|
||||
//*********************************
|
||||
template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
|
||||
etl ::is_convertible<U1, THead>::value &&
|
||||
etl ::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
|
||||
etl::is_convertible<U1, THead>::value &&
|
||||
etl::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
|
||||
: base_type(p.second)
|
||||
@ -442,8 +442,8 @@ namespace etl
|
||||
/// Explicit conversion.
|
||||
//*********************************
|
||||
template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
|
||||
(!etl ::is_convertible<U1, THead>::value ||
|
||||
!etl ::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
|
||||
(!etl::is_convertible<U1, THead>::value ||
|
||||
!etl::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
explicit tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
|
||||
: base_type(p.second)
|
||||
@ -456,8 +456,8 @@ namespace etl
|
||||
/// Implicit conversion.
|
||||
//*********************************
|
||||
template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
|
||||
etl ::is_convertible<U1, THead>::value &&
|
||||
etl ::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
|
||||
etl::is_convertible<U1, THead>::value &&
|
||||
etl::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
tuple(const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
|
||||
: base_type(p.second)
|
||||
@ -470,8 +470,8 @@ namespace etl
|
||||
/// Explicit conversion.
|
||||
//*********************************
|
||||
template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
|
||||
(!etl ::is_convertible<U1, THead>::value ||
|
||||
!etl ::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
|
||||
(!etl::is_convertible<U1, THead>::value ||
|
||||
!etl::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
explicit tuple(const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
|
||||
: base_type(p.second)
|
||||
@ -484,8 +484,8 @@ namespace etl
|
||||
/// Implicit conversion.
|
||||
//*********************************
|
||||
template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
|
||||
etl ::is_convertible<U1, THead>::value &&
|
||||
etl ::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
|
||||
etl::is_convertible<U1, THead>::value &&
|
||||
etl::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
|
||||
: base_type(etl::forward<U2>(p.second))
|
||||
@ -498,8 +498,8 @@ namespace etl
|
||||
/// Explicit conversion.
|
||||
//*********************************
|
||||
template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
|
||||
(!etl ::is_convertible<U1, THead>::value ||
|
||||
!etl ::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
|
||||
(!etl::is_convertible<U1, THead>::value ||
|
||||
!etl::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
explicit tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
|
||||
: base_type(etl::forward<U2>(p.second))
|
||||
@ -512,12 +512,12 @@ namespace etl
|
||||
/// Implicit conversion.
|
||||
//*********************************
|
||||
template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
|
||||
etl ::is_convertible<U1, THead>::value &&
|
||||
etl ::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
|
||||
etl::is_convertible<U1, THead>::value &&
|
||||
etl::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
tuple(const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
|
||||
: base_type(etl::forward<U2>(p.second))
|
||||
, value(etl::forward<U1>(p.first))
|
||||
: base_type(etl::forward<const U2>(p.second))
|
||||
, value(etl::forward<const U1>(p.first))
|
||||
{
|
||||
}
|
||||
|
||||
@ -526,12 +526,12 @@ namespace etl
|
||||
/// Explicit conversion.
|
||||
//*********************************
|
||||
template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
|
||||
(!etl ::is_convertible<U1, THead>::value ||
|
||||
!etl ::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
|
||||
(!etl::is_convertible<U1, THead>::value ||
|
||||
!etl::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
|
||||
ETL_CONSTEXPR14
|
||||
explicit tuple(const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
|
||||
: base_type(p.second)
|
||||
, value(p.first)
|
||||
: base_type(etl::forward<const U2>(p.second))
|
||||
, value(etl::forward<const U1>(p.first))
|
||||
{
|
||||
}
|
||||
|
||||
@ -605,8 +605,8 @@ namespace etl
|
||||
ETL_CONSTEXPR14
|
||||
tuple& operator =(const ETL_OR_STD::pair<U1, U2>&& p)
|
||||
{
|
||||
get_value() = p.first;
|
||||
get_base().get_value() = p.second;
|
||||
get_value() = etl::forward<const U1>(p.first);
|
||||
get_base().get_value() = etl::forward<const U2>(p.second);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -763,7 +763,7 @@ namespace etl
|
||||
|
||||
//***************************************************************************
|
||||
/// Extracts the element at Index from the tuple.
|
||||
/// Index must be an integer value in sizeof...(TTypes)).
|
||||
/// Index must be an integer value in [0, sizeof...(TTypes)).
|
||||
/// Returns a reference.
|
||||
//***************************************************************************
|
||||
template <size_t Index, typename... TTypes>
|
||||
@ -782,7 +782,7 @@ namespace etl
|
||||
|
||||
//***************************************************************************
|
||||
/// Extracts the element at Index from the tuple.
|
||||
/// Index must be an integer value in [?0?, sizeof...(TTypes)).
|
||||
/// Index must be an integer value in [0, sizeof...(TTypes)).
|
||||
/// Returns a const reference.
|
||||
//***************************************************************************
|
||||
template <size_t Index, typename... TTypes>
|
||||
@ -801,7 +801,7 @@ namespace etl
|
||||
|
||||
//***************************************************************************
|
||||
/// Extracts the element at Index from the tuple.
|
||||
/// Index must be an integer value in [?0?, sizeof...(TTypes)).
|
||||
/// Index must be an integer value in [0, sizeof...(TTypes)).
|
||||
/// Returns an rvalue reference.
|
||||
//***************************************************************************
|
||||
template <size_t Index, typename... TTypes>
|
||||
@ -820,7 +820,7 @@ namespace etl
|
||||
|
||||
//***************************************************************************
|
||||
/// Extracts the element at Index from the tuple.
|
||||
/// Index must be an integer value in [?0?, sizeof...(TTypes)).
|
||||
/// Index must be an integer value in [0, sizeof...(TTypes)).
|
||||
/// Returns a const rvalue reference.
|
||||
//***************************************************************************
|
||||
template <size_t Index, typename... TTypes>
|
||||
@ -1017,17 +1017,17 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
auto tuple_cat(Tuple1&& t1, Tuple2&& t2, Tuples&&... ts)
|
||||
-> decltype(private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
|
||||
etl::forward<Tuple2>(t2),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple2>>::value>{}))
|
||||
-> decltype(tuple_cat(private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
|
||||
etl::forward<Tuple2>(t2),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple2>>::value>{}),
|
||||
etl::forward<Tuples>(ts)...))
|
||||
{
|
||||
auto concatenated = private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
|
||||
etl::forward<Tuple2>(t2),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple2>>::value>{});
|
||||
|
||||
return tuple_cat(etl::move(concatenated), etl::forward<Tuples>(ts)...);
|
||||
return tuple_cat(private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
|
||||
etl::forward<Tuple2>(t2),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple2>>::value>{}),
|
||||
etl::forward<Tuples>(ts)...);
|
||||
}
|
||||
|
||||
#if ETL_USING_STL
|
||||
@ -1317,7 +1317,7 @@ namespace std
|
||||
template <size_t Index, typename... Types>
|
||||
struct tuple_element<Index, etl::tuple<Types...>>
|
||||
{
|
||||
using type = typename etl::nth_type_t<Index, Types...>;
|
||||
using type = etl::nth_type_t<Index, Types...>;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -345,8 +345,8 @@ namespace etl
|
||||
{
|
||||
memcpy(store, &value, Size_);
|
||||
|
||||
#if ETL_HAS_CONSTEXPR_ENDIANESS
|
||||
if ETL_IF_CONSTEXPR(Endian_ == etl::endianness::value())
|
||||
#if ETL_HAS_CONSTEXPR_ENDIANNESS
|
||||
if ETL_IF_CONSTEXPR(Endian_ != etl::endianness::value())
|
||||
#else
|
||||
if (Endian_ != etl::endianness::value())
|
||||
#endif
|
||||
@ -361,8 +361,8 @@ namespace etl
|
||||
{
|
||||
memcpy(&value, store, Size_);
|
||||
|
||||
#if ETL_HAS_CONSTEXPR_ENDIANESS
|
||||
if ETL_IF_CONSTEXPR(Endian == etl::endianness::value())
|
||||
#if ETL_HAS_CONSTEXPR_ENDIANNESS
|
||||
if ETL_IF_CONSTEXPR(Endian_ != etl::endianness::value())
|
||||
#else
|
||||
if (Endian_ != etl::endianness::value())
|
||||
#endif
|
||||
@ -402,8 +402,8 @@ namespace etl
|
||||
{
|
||||
memcpy(store, &value, Size_);
|
||||
|
||||
#if ETL_HAS_CONSTEXPR_ENDIANESS
|
||||
if ETL_IF_CONSTEXPR(Endian_ == etl::endianness::value())
|
||||
#if ETL_HAS_CONSTEXPR_ENDIANNESS
|
||||
if ETL_IF_CONSTEXPR(Endian_ != etl::endianness::value())
|
||||
#else
|
||||
if (Endian_ != etl::endianness::value())
|
||||
#endif
|
||||
@ -418,14 +418,14 @@ namespace etl
|
||||
{
|
||||
memcpy(&value, store, Size_);
|
||||
|
||||
#if ETL_HAS_CONSTEXPR_ENDIANESS
|
||||
if ETL_IF_CONSTEXPR(Endian == etl::endianness::value())
|
||||
#if ETL_HAS_CONSTEXPR_ENDIANNESS
|
||||
if ETL_IF_CONSTEXPR(Endian_ != etl::endianness::value())
|
||||
#else
|
||||
if (Endian_ != etl::endianness::value())
|
||||
if (Endian_ != etl::endianness::value())
|
||||
#endif
|
||||
{
|
||||
etl::reverse(reinterpret_cast<pointer>(&value), reinterpret_cast<pointer>(&value) + Size_);
|
||||
}
|
||||
{
|
||||
etl::reverse(reinterpret_cast<pointer>(&value), reinterpret_cast<pointer>(&value) + Size_);
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
|
||||
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
|
||||
@ -371,6 +380,10 @@ target_compile_definitions(etl_tests PRIVATE -DETL_DEBUG)
|
||||
|
||||
option(ETL_NO_STL "No STL" OFF)
|
||||
|
||||
set(EXTRA_COMPILE_OPTIONS "" CACHE STRING "Additional compiler options")
|
||||
set(EXTRA_LINK_OPTIONS "" CACHE STRING "Additional linker options")
|
||||
set(EXTRA_LINK_LIBS "" CACHE STRING "Additional libraries to link")
|
||||
|
||||
if (ETL_CXX_STANDARD MATCHES "98")
|
||||
message(STATUS "Compiling for C++98")
|
||||
set_property(TARGET etl_tests PROPERTY CXX_STANDARD 98)
|
||||
@ -468,7 +481,9 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
-Wnull-dereference
|
||||
-Wextra-semi
|
||||
-g
|
||||
${EXTRA_COMPILE_OPTIONS}
|
||||
)
|
||||
target_link_options(etl_tests PRIVATE ${EXTRA_LINK_OPTIONS})
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
@ -487,7 +502,9 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
-Wextra-semi-stmt
|
||||
-Wc++11-extra-semi
|
||||
-g
|
||||
${EXTRA_COMPILE_OPTIONS}
|
||||
)
|
||||
target_link_options(etl_tests PRIVATE ${EXTRA_LINK_OPTIONS})
|
||||
endif ()
|
||||
|
||||
if ((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
@ -513,7 +530,7 @@ target_include_directories(etl_tests
|
||||
${PROJECT_SOURCE_DIR}/../include)
|
||||
|
||||
add_subdirectory(UnitTest++)
|
||||
target_link_libraries(etl_tests PRIVATE UnitTestpp)
|
||||
target_link_libraries(etl_tests PRIVATE UnitTestpp ${EXTRA_LINK_LIBS})
|
||||
|
||||
# Enable the 'make test' CMake target using the executable defined above
|
||||
add_test(etl_unit_tests etl_tests)
|
||||
@ -522,4 +539,3 @@ add_test(etl_unit_tests etl_tests)
|
||||
# define a target that will output all of the failing or passing tests
|
||||
# as they appear from UnitTest++
|
||||
add_custom_target(test_verbose COMMAND ${CMAKE_CTEST_COMMAND} --verbose)
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
81
test/run-coverage.sh
Executable file
81
test/run-coverage.sh
Executable file
@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# run-coverage.sh [gcc|clang]
|
||||
#
|
||||
# defaults:
|
||||
# compiler: clang
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
|
||||
|
||||
# Choose gcc or clang via cmdline
|
||||
if [ "$1" = "gcc" ] ; then
|
||||
COMPILER=gcc
|
||||
else
|
||||
# default
|
||||
COMPILER=clang
|
||||
fi
|
||||
|
||||
if [ "$COMPILER" = "gcc" ]; then
|
||||
C_COMPILER=gcc
|
||||
CXX_COMPILER=g++
|
||||
GCOV="$(command -v gcov)" || { echo "gcov not found in PATH"; exit 1; }
|
||||
GCOV_ADD=""
|
||||
EXTRA_LINK_OPTIONS=""
|
||||
EXTRA_LINK_LIBS="gcov"
|
||||
elif [ "$COMPILER" = "clang" ]; then
|
||||
C_COMPILER=clang
|
||||
CXX_COMPILER=clang++
|
||||
GCOV="$(command -v llvm-cov)" || { echo "llvm-cov not found in PATH"; exit 1; }
|
||||
GCOV_ADD="--gcov-tool gcov"
|
||||
EXTRA_LINK_OPTIONS="--coverage"
|
||||
EXTRA_LINK_LIBS=""
|
||||
else
|
||||
echo "Unsupported compiler: $COMPILER"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BUILD=build-coverage
|
||||
|
||||
rm -rf -- "${BUILD:?}"
|
||||
mkdir -p "$BUILD"
|
||||
cd "$BUILD" || exit 1
|
||||
touch total.info
|
||||
|
||||
for CXXSTD in 11 14 17 20 23; do
|
||||
for NOSTL in OFF ON; do
|
||||
rm -rf CMakeFiles
|
||||
cmake -DEXTRA_COMPILE_OPTIONS="--coverage" \
|
||||
-DEXTRA_LINK_OPTIONS="$EXTRA_LINK_OPTIONS" \
|
||||
-DEXTRA_LINK_LIBS="$EXTRA_LINK_LIBS" \
|
||||
-DCMAKE_C_COMPILER=$C_COMPILER \
|
||||
-DCMAKE_CXX_COMPILER=$CXX_COMPILER \
|
||||
-DNO_STL=$NOSTL \
|
||||
-DETL_USE_TYPE_TRAITS_BUILTINS=OFF \
|
||||
-DETL_USER_DEFINED_TYPE_TRAITS=OFF \
|
||||
-DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
|
||||
-DETL_OPTIMISATION=-O0 \
|
||||
-DETL_CXX_STANDARD=$CXXSTD \
|
||||
-DETL_ENABLE_SANITIZER=Off \
|
||||
-DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF \
|
||||
-DETL_USE_BUILTIN_MEM_FUNCTIONS=ON ..
|
||||
cmake --build .
|
||||
./etl_tests
|
||||
lcov --gcov-tool "$GCOV" $GCOV_ADD --capture --directory CMakeFiles/etl_tests.dir \
|
||||
--rc "geninfo_unexecuted_blocks=1" --output-file coverage.info --include '*/include/etl/*' --rc "lcov_branch_coverage=1" \
|
||||
--ignore-errors inconsistent \
|
||||
--ignore-errors mismatch
|
||||
|
||||
lcov -a total.info -a coverage.info -o total.info --rc "lcov_branch_coverage=1" \
|
||||
--ignore-errors inconsistent \
|
||||
--ignore-errors corrupt \
|
||||
--ignore-errors empty
|
||||
done
|
||||
done
|
||||
|
||||
genhtml total.info --output-directory coverage --rc "genhtml_branch_coverage=1" --branch-coverage -t $COMPILER \
|
||||
--ignore-errors inconsistent
|
||||
|
||||
cd ..
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +35,8 @@ SOFTWARE.
|
||||
|
||||
#include "etl/crc8_nrsc5.h"
|
||||
|
||||
#include <etl/endianness.h>
|
||||
|
||||
//*****************************************************************************
|
||||
// The results for these tests were created from https://crccalc.com/
|
||||
//*****************************************************************************
|
||||
@ -115,7 +117,15 @@ namespace
|
||||
TEST(test_crc8_nrsc5_4_add_range_endian)
|
||||
{
|
||||
std::vector<uint8_t> data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U };
|
||||
std::vector<uint32_t> data2 = { 0x04030201UL, 0x08070605UL };
|
||||
std::vector<uint32_t> data2;
|
||||
if (etl::endianness::value() == etl::endian::little)
|
||||
{
|
||||
data2 = { 0x04030201UL, 0x08070605UL };
|
||||
}
|
||||
else
|
||||
{
|
||||
data2 = { 0x01020304UL, 0x05060708UL };
|
||||
}
|
||||
std::vector<uint8_t> data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U };
|
||||
|
||||
uint8_t crc1 = etl::crc8_nrsc5_t4(data1.begin(), data1.end());
|
||||
@ -198,7 +208,15 @@ namespace
|
||||
TEST(test_crc8_nrsc5_16_add_range_endian)
|
||||
{
|
||||
std::vector<uint8_t> data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U };
|
||||
std::vector<uint32_t> data2 = { 0x04030201UL, 0x08070605UL };
|
||||
std::vector<uint32_t> data2;
|
||||
if (etl::endianness::value() == etl::endian::little)
|
||||
{
|
||||
data2 = { 0x04030201UL, 0x08070605UL };
|
||||
}
|
||||
else
|
||||
{
|
||||
data2 = { 0x01020304UL, 0x05060708UL };
|
||||
}
|
||||
std::vector<uint8_t> data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U };
|
||||
|
||||
uint8_t crc1 = etl::crc8_nrsc5_t16(data1.begin(), data1.end());
|
||||
@ -281,7 +299,15 @@ namespace
|
||||
TEST(test_crc8_nrsc5_256_add_range_endian)
|
||||
{
|
||||
std::vector<uint8_t> data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U };
|
||||
std::vector<uint32_t> data2 = { 0x04030201UL, 0x08070605UL };
|
||||
std::vector<uint32_t> data2;
|
||||
if (etl::endianness::value() == etl::endian::little)
|
||||
{
|
||||
data2 = { 0x04030201UL, 0x08070605UL };
|
||||
}
|
||||
else
|
||||
{
|
||||
data2 = { 0x01020304UL, 0x05060708UL };
|
||||
}
|
||||
std::vector<uint8_t> data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U };
|
||||
|
||||
uint8_t crc1 = etl::crc8_nrsc5(data1.begin(), data1.end());
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -1118,5 +1118,46 @@ namespace
|
||||
|
||||
CHECK_EQUAL(42, *opt);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// GitHub issue #146: etl::optional doesn't compile with deleted copy constructor
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
struct Issue146_NonCopyable
|
||||
{
|
||||
Issue146_NonCopyable(int some) : _some(some) {}
|
||||
Issue146_NonCopyable(const Issue146_NonCopyable&) = delete;
|
||||
Issue146_NonCopyable(Issue146_NonCopyable&&) = delete;
|
||||
Issue146_NonCopyable& operator=(const Issue146_NonCopyable&) = delete;
|
||||
|
||||
int _some;
|
||||
};
|
||||
|
||||
struct Issue146_Container
|
||||
{
|
||||
Issue146_Container(int a_val) : a(a_val) {}
|
||||
Issue146_Container() : a(etl::nullopt) {}
|
||||
|
||||
etl::optional<Issue146_NonCopyable> a;
|
||||
};
|
||||
|
||||
TEST(test_optional_issue_146_deleted_copy_ctor)
|
||||
{
|
||||
// etl::optional<T> should compile when T has deleted copy/move constructors,
|
||||
// as long as T is constructible from the given arguments.
|
||||
Issue146_Container with_value(42);
|
||||
Issue146_Container without_value;
|
||||
|
||||
CHECK_TRUE(with_value.a.has_value());
|
||||
CHECK_EQUAL(42, with_value.a->_some);
|
||||
|
||||
CHECK_FALSE(without_value.a.has_value());
|
||||
|
||||
// in_place construction should also work
|
||||
etl::optional<Issue146_NonCopyable> opt(etl::in_place_t{}, 99);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(99, opt->_some);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ SOFTWARE.
|
||||
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -486,6 +487,56 @@ namespace
|
||||
CHECK_EQUAL(std::string("2"), d.value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_construct_from_rvalue_pair_implicit_conversion)
|
||||
{
|
||||
ETL_OR_STD::pair<int, Data> p(1, Data("2"));
|
||||
|
||||
etl::tuple<int, Data> tp(etl::move(p));
|
||||
|
||||
int i = etl::get<0>(tp);
|
||||
Data d = etl::get<1>(tp);
|
||||
|
||||
CHECK_EQUAL(1, i);
|
||||
CHECK_EQUAL(std::string("2"), d.value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_construct_from_rvalue_pair_explicit_conversion)
|
||||
{
|
||||
ETL_OR_STD::pair<From, From> p(From(1), From(2));
|
||||
|
||||
etl::tuple<To, To> tp(etl::move(p));
|
||||
|
||||
CHECK_EQUAL(1, etl::get<0>(tp).i);
|
||||
CHECK_EQUAL(2, etl::get<1>(tp).i);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_construct_from_const_rvalue_pair_implicit_conversion)
|
||||
{
|
||||
const ETL_OR_STD::pair<int, Data> p(1, Data("2"));
|
||||
|
||||
etl::tuple<int, Data> tp(etl::move(p));
|
||||
|
||||
int i = etl::get<0>(tp);
|
||||
Data d = etl::get<1>(tp);
|
||||
|
||||
CHECK_EQUAL(1, i);
|
||||
CHECK_EQUAL(std::string("2"), d.value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_construct_from_const_rvalue_pair_explicit_conversion)
|
||||
{
|
||||
const ETL_OR_STD::pair<From, From> p(From(1), From(2));
|
||||
|
||||
etl::tuple<To, To> tp(etl::move(p));
|
||||
|
||||
CHECK_EQUAL(1, etl::get<0>(tp).i);
|
||||
CHECK_EQUAL(2, etl::get<1>(tp).i);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD bool Get()
|
||||
{
|
||||
@ -553,7 +604,7 @@ namespace
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_tuple_cat)
|
||||
TEST(test_tuple_cat_2)
|
||||
{
|
||||
etl::tuple<int, double> tp1{1, 2.3};
|
||||
etl::tuple<int, Data> tp2{4, Data("Data", 5)};
|
||||
@ -566,6 +617,46 @@ namespace
|
||||
CHECK_EQUAL(etl::get<3>(tp3), etl::get<1>(tp2));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_tuple_cat_3)
|
||||
{
|
||||
etl::tuple<int, double> tp1{1, 2.3};
|
||||
etl::tuple<int, Data> tp2{4, Data("Data", 5)};
|
||||
etl::tuple<bool, int> tp3{true, 5};
|
||||
|
||||
auto tp4 = etl::tuple_cat(tp1, tp2, tp3);
|
||||
static_assert(std::is_same<decltype(tp4), etl::tuple<int, double, int, Data, bool, int>>::value, "tp4 type mismatch");
|
||||
|
||||
CHECK_EQUAL(etl::get<0>(tp4), etl::get<0>(tp1));
|
||||
CHECK_EQUAL(etl::get<1>(tp4), etl::get<1>(tp1));
|
||||
CHECK_EQUAL(etl::get<2>(tp4), etl::get<0>(tp2));
|
||||
CHECK_EQUAL(etl::get<3>(tp4), etl::get<1>(tp2));
|
||||
CHECK_EQUAL(etl::get<4>(tp4), etl::get<0>(tp3));
|
||||
CHECK_EQUAL(etl::get<5>(tp4), etl::get<1>(tp3));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_tuple_cat_4)
|
||||
{
|
||||
etl::tuple<int, double> tp1{1, 2.3};
|
||||
etl::tuple<int, Data> tp2{4, Data("Data", 5)};
|
||||
etl::tuple<bool, int> tp3{true, 5};
|
||||
etl::tuple<double, int, bool> tp4{1.01, 6, false};
|
||||
|
||||
auto tp5 = etl::tuple_cat(tp1, tp2, tp3, tp4);
|
||||
static_assert(std::is_same<decltype(tp5), etl::tuple<int, double, int, Data, bool, int, double, int, bool>>::value, "tp5 type mismatch");
|
||||
|
||||
CHECK_EQUAL(etl::get<0>(tp5), etl::get<0>(tp1));
|
||||
CHECK_EQUAL(etl::get<1>(tp5), etl::get<1>(tp1));
|
||||
CHECK_EQUAL(etl::get<2>(tp5), etl::get<0>(tp2));
|
||||
CHECK_EQUAL(etl::get<3>(tp5), etl::get<1>(tp2));
|
||||
CHECK_EQUAL(etl::get<4>(tp5), etl::get<0>(tp3));
|
||||
CHECK_EQUAL(etl::get<5>(tp5), etl::get<1>(tp3));
|
||||
CHECK_EQUAL(etl::get<6>(tp5), etl::get<0>(tp4));
|
||||
CHECK_EQUAL(etl::get<7>(tp5), etl::get<1>(tp4));
|
||||
CHECK_EQUAL(etl::get<8>(tp5), etl::get<2>(tp4));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_forward_as_tuple)
|
||||
{
|
||||
@ -831,7 +922,7 @@ namespace
|
||||
|
||||
etl::tuple<int, Data> tp(0, Data(""));
|
||||
|
||||
tp = static_cast<const ETL_OR_STD::pair<int, Data>&&>(p);
|
||||
tp = etl::move(p);
|
||||
|
||||
int i = etl::get<0>(tp);
|
||||
Data d = etl::get<1>(tp);
|
||||
|
||||
@ -1030,6 +1030,98 @@ namespace
|
||||
CHECK_EQUAL(0x12, bev0);
|
||||
CHECK_EQUAL(0x34, bev1);
|
||||
}
|
||||
|
||||
#if ETL_HAS_CONSTEXPR_ENDIANNESS
|
||||
//*************************************************************************
|
||||
TEST(test_constexpr_endianness_integral_round_trip)
|
||||
{
|
||||
// Store a known value in LE, BE, and host-order unaligned types.
|
||||
const uint32_t value = 0x12345678U;
|
||||
|
||||
etl::le_uint32_t le_v(value);
|
||||
etl::be_uint32_t be_v(value);
|
||||
etl::host_uint32_t host_v(value);
|
||||
|
||||
// All must read back the original value.
|
||||
CHECK_EQUAL(value, uint32_t(le_v));
|
||||
CHECK_EQUAL(value, uint32_t(be_v));
|
||||
CHECK_EQUAL(value, uint32_t(host_v));
|
||||
|
||||
// Verify the storage byte order is correct.
|
||||
// LE stores LSB first: 0x78, 0x56, 0x34, 0x12
|
||||
CHECK_EQUAL(0x78, int(le_v[0]));
|
||||
CHECK_EQUAL(0x56, int(le_v[1]));
|
||||
CHECK_EQUAL(0x34, int(le_v[2]));
|
||||
CHECK_EQUAL(0x12, int(le_v[3]));
|
||||
|
||||
// BE stores MSB first: 0x12, 0x34, 0x56, 0x78
|
||||
CHECK_EQUAL(0x12, int(be_v[0]));
|
||||
CHECK_EQUAL(0x34, int(be_v[1]));
|
||||
CHECK_EQUAL(0x56, int(be_v[2]));
|
||||
CHECK_EQUAL(0x78, int(be_v[3]));
|
||||
|
||||
// Host-order must match one of the above depending on the platform.
|
||||
if (etl::endianness::value() == etl::endian::little)
|
||||
{
|
||||
CHECK_EQUAL(0x78, int(host_v[0]));
|
||||
CHECK_EQUAL(0x56, int(host_v[1]));
|
||||
CHECK_EQUAL(0x34, int(host_v[2]));
|
||||
CHECK_EQUAL(0x12, int(host_v[3]));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_EQUAL(0x12, int(host_v[0]));
|
||||
CHECK_EQUAL(0x34, int(host_v[1]));
|
||||
CHECK_EQUAL(0x56, int(host_v[2]));
|
||||
CHECK_EQUAL(0x78, int(host_v[3]));
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constexpr_endianness_float_round_trip)
|
||||
{
|
||||
// Store a known float value in LE, BE, and host-order unaligned types.
|
||||
const float value = 3.1415927f;
|
||||
|
||||
etl::le_float_t le_v(value);
|
||||
etl::be_float_t be_v(value);
|
||||
etl::host_float_t host_v(value);
|
||||
|
||||
// All must read back the original value.
|
||||
CHECK_CLOSE(value, float(le_v), 0.0001f);
|
||||
CHECK_CLOSE(value, float(be_v), 0.0001f);
|
||||
CHECK_CLOSE(value, float(host_v), 0.0001f);
|
||||
|
||||
// LE and BE storage bytes must be the reverse of each other.
|
||||
CHECK_EQUAL(int(le_v[0]), int(be_v[3]));
|
||||
CHECK_EQUAL(int(le_v[1]), int(be_v[2]));
|
||||
CHECK_EQUAL(int(le_v[2]), int(be_v[1]));
|
||||
CHECK_EQUAL(int(le_v[3]), int(be_v[0]));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constexpr_endianness_cross_endian_copy)
|
||||
{
|
||||
// Verify that converting between LE <-> BE via host works correctly.
|
||||
const uint16_t value = 0xABCDU;
|
||||
|
||||
etl::le_uint16_t le_v(value);
|
||||
etl::be_uint16_t be_v(value);
|
||||
etl::host_uint16_t host_from_le(le_v);
|
||||
etl::host_uint16_t host_from_be(be_v);
|
||||
|
||||
CHECK_EQUAL(value, uint16_t(host_from_le));
|
||||
CHECK_EQUAL(value, uint16_t(host_from_be));
|
||||
|
||||
// Round-trip: host -> le -> read back
|
||||
etl::le_uint16_t le_from_host(host_from_le);
|
||||
CHECK_EQUAL(value, uint16_t(le_from_host));
|
||||
|
||||
// Round-trip: host -> be -> read back
|
||||
etl::be_uint16_t be_from_host(host_from_be);
|
||||
CHECK_EQUAL(value, uint16_t(be_from_host));
|
||||
}
|
||||
#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