Merge branch 'feature/timer-refactor' of https://github.com/ETLCPP/etl into feature/timer-refactor

This commit is contained in:
John Wellbelove 2026-10-30 00:23:14 +00:00
commit 01a01d56e7
40 changed files with 4644 additions and 38 deletions

View File

@ -0,0 +1,57 @@
# Pinned by digest for reproducible builds.
# To update: docker buildx imagetools inspect debian:sid-slim
FROM debian:sid-slim@sha256:ec3fa4e0b2987ae47be353f56854191e300261915470e40165b1c906d22a65db
# Pin the package archive to a snapshot.debian.org timestamp so that
# `apt-get install` resolves the same package versions on every build.
# This is the snapshot the base image itself was built from - see the comment
# in /etc/apt/sources.list.d/debian.sources of the pinned image above.
ARG DEBIAN_SNAPSHOT=20260918T000000Z
# snapshot.debian.org serves archived Release files whose Valid-Until has long
# since passed, so that check has to be disabled.
# http is used rather than https because the slim base image has no
# ca-certificates; integrity is guaranteed by the archive's GPG signature.
RUN printf '%s\n' \
'Types: deb' \
"URIs: http://snapshot.debian.org/archive/debian/${DEBIAN_SNAPSHOT}/" \
'Suites: sid' \
'Components: main' \
'Check-Valid-Until: no' \
'Signed-By: /usr/share/keyrings/debian-archive-keyring.pgp' \
> /etc/apt/sources.list.d/debian.sources
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
git \
ninja-build \
python3 \
python3-cogapp \
gcc-16 \
g++-16 \
&& rm -rf /var/lib/apt/lists/*
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-16 100 \
--slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-16 \
--slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-16 \
--slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-16 \
&& update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-16 100
# Create non-root user with stable UID/GID
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /etl && chown -R ${USERNAME}:${USERNAME} /etl
WORKDIR /etl
# Switch to non-root user
USER ${USERNAME}
CMD ["/bin/bash"]

View File

@ -0,0 +1,12 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
//
// GCC 16 is the reference toolchain for the C++26 static reflection support in
// etl/meta.h. It cannot use the shared ../Dockerfile because there is no
// 'gcc:16' base image yet, so gcc-16 is taken from Debian sid instead.
{
"name": "Gcc 16",
"build": {
"dockerfile": "./Dockerfile"
}
}

View File

@ -0,0 +1,78 @@
name: gcc16-c++26-reflection
on:
push:
branches: [ master, development, pull-request/* ]
paths:
- '.github/workflows/**'
- 'include/**'
- 'test/**'
- 'CMakeLists.txt'
- 'cmake/**'
- '.devcontainer/**'
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
paths:
- '.github/workflows/**'
- 'include/**'
- 'test/**'
- 'CMakeLists.txt'
- 'cmake/**'
- '.devcontainer/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
build-gcc16-cpp26-reflection-stl:
name: GCC 16 C++26 Reflection - STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6.0.3
with:
persist-credentials: false
- name: Build Docker image
run: docker build -t etl-gcc16 -f .devcontainer/gcc16/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/etl etl-gcc16 bash -c "\
cd /etl && \
export CC=gcc-16 && \
export CXX=g++-16 && \
g++-16 --version && \
cmake -G Ninja -B /tmp/build-stl -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 -DETL_OPTIMISATION=-O0 /etl/test && \
grep -q 'ETL_GNU_HAS_FREFLECTION:INTERNAL=1' /tmp/build-stl/CMakeCache.txt || (echo 'ERROR: -freflection was not detected - C++26 reflection is not being tested.' && exit 1) && \
cmake --build /tmp/build-stl -j \$(getconf _NPROCESSORS_ONLN) && \
ctest --test-dir /tmp/build-stl --output-on-failure"
build-gcc16-cpp26-reflection-no-stl:
name: GCC 16 C++26 Reflection - No STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6.0.3
with:
persist-credentials: false
- name: Build Docker image
run: docker build -t etl-gcc16 -f .devcontainer/gcc16/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/etl etl-gcc16 bash -c "\
cd /etl && \
export CC=gcc-16 && \
export CXX=g++-16 && \
g++-16 --version && \
cmake -G Ninja -B /tmp/build-no-stl -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 -DETL_OPTIMISATION=-O0 /etl/test && \
grep -q 'ETL_GNU_HAS_FREFLECTION:INTERNAL=1' /tmp/build-no-stl/CMakeCache.txt || (echo 'ERROR: -freflection was not detected - C++26 reflection is not being tested.' && exit 1) && \
cmake --build /tmp/build-no-stl -j \$(getconf _NPROCESSORS_ONLN) && \
ctest --test-dir /tmp/build-no-stl --output-on-failure"

View File

@ -103,6 +103,7 @@ These may be defined in the project settings or the user created `etl_profile.h`
| `ETL_HAS_IDEQUE_REPAIR` | Set to `1` if the repair functionality for `etl::ideque` is enabled, otherwise `0`.|
| `ETL_IS_DEBUG_BUILD` | Set to `1` if in a debug build, otherwise `0`.|
| `ETL_HAS_POLYMORPHIC_MESSAGES` | Set to `1` if messages are polymorphic, otherwise `0`.|
| `ETL_HAS_REFLECTION` | Defined by `etl/meta.h`. Set to `1` if the compiler supports C++26 static reflection (P2996) and `etl::meta` is available, otherwise `0`.|
| `ETL_HAS_ERROR_ON_STRING_TRUNCATION` | Set to `1` if truncated strings are an error, otherwise `0`.|
| `ETL_USING_LIBC_WCHAR_H` | These macros will be defined as `0` & `1` depending on whether `ETL_NO_LIBC_WCHAR_H` is defined or not.|
| `ETL_NOT_USING_LIBC_WCHAR_H` | Inversion of `ETL_USING_LIBC_WCHAR_H`.|

View File

@ -38,7 +38,7 @@ ETL_CONSTEXPR bool is_zero(T value)
**Returns**
`true` if `value` is Zero.
## is_exactly_zero
## is_exactly_equal
```cpp
template <typename T>
@ -260,7 +260,7 @@ A wrapper around `::powl` in `<math.h>`.
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::pow` with casts to `double`.
otherwise
`::powl(base, intpart)`
`::powl(base, exponent)`
## modf

View File

@ -707,6 +707,7 @@ size_t find(char c, size_t pos = 0) const;
```cpp
size_t rfind(const etl::istring& str, size_t pos = npos) const;
size_t rfind(const etl::string_view& view, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos, size_t n) const;
size_t rfind(char c, size_t pos = npos) const;

97
docs/types/meta.md Normal file
View File

@ -0,0 +1,97 @@
---
title: "meta"
---
{{< callout type="info">}}
Header: `meta.h`
From: `20.50.0`
Similar to: `std::meta`
{{< /callout >}}
C++26 static reflection (P2996) in namespace `etl::meta`.
`etl::meta` mirrors `std::meta`, but is usable in both STL and non-STL builds.
In an STL build it is a thin layer of using-declarations over `std::meta`.
In a non-STL build ETL supplies the minimal declarations that the compiler's
reflection builtins require, so no standard library is needed.
```cpp
#include "etl/meta.h"
```
## Compiler support
Static reflection is a very new language feature, and at the time of writing
**GCC 16** is the only compiler that implements enough of P2996 to be usable.
Clang (including the Bloomberg `clang-p2996` fork) and MSVC are not supported.
`etl/meta.h` may always be included. It defines a single macro,
`ETL_HAS_REFLECTION`, as `1` or `0`; when it is `0` the header defines nothing
else. This is the only reflection feature switch in the ETL, and user code
should test it before using anything in `etl::meta`.
```cpp
#include "etl/meta.h"
#if ETL_HAS_REFLECTION
static_assert(etl::meta::identifier_of(^^my_type) == "my_type");
#endif
```
GCC requires the `-freflection` option in addition to `-std=c++26`.
The reference toolchain is defined in `.devcontainer/gcc16`.
## Usage
Names are used exactly as their `std::meta` equivalents.
```cpp
struct point
{
int x;
int y;
};
constexpr auto members =
etl::meta::nonstatic_data_members_of(^^point,
etl::meta::access_context::unchecked());
static_assert(etl::meta::identifier_of(members[0]) == "x");
static_assert(etl::meta::type_of(members[0]) == ^^int);
static_assert(etl::meta::size_of(^^point) == 2 * sizeof(int));
```
`identifier_of`, `display_string_of` and `symbol_of` return `std::string_view`
in an STL build and `etl::string_view` in a non-STL build.
## info_array
GCC cannot keep the heap allocation of a `std::vector<info>` alive across a
constant evaluation, so a `template for` over the result of `members_of` does
not compile. `etl::meta::info_array` is a fixed-size, allocation-free array of
`info` that can be iterated instead.
```cpp
constexpr auto ctx = etl::meta::access_context::unchecked();
constexpr auto count = etl::meta::nonstatic_data_members_of(^^point, ctx).size();
constexpr auto members =
etl::meta::to_info_array<count>(etl::meta::nonstatic_data_members_of(^^point, ctx));
template for (constexpr auto member : members)
{
// ...
}
```
| Member | Description |
|--------|-------------|
| `begin()` | Pointer to the first element. |
| `end()` | Pointer past the last element. |
| `size()` | The number of elements. |
| `operator[](size_t)` | The element at the index. |
All members are `consteval`.
## Tests
`test_meta.cpp`

View File

@ -126,7 +126,6 @@ struct type_list_contains
```
**Description**
Defines `value` as `true` if the `type_list` contains the specified type, otherwise `false`.
From: `C++17`
---
@ -135,7 +134,8 @@ template <typename TTypeList, typename T>
constexpr bool type_list_contains_v
```
**Description**
Defined as `true` if the `type_list` contains the specified type, otherwise `false`.
Defined as `true` if the `type_list` contains the specified type, otherwise `false`.
From: `C++17`
## type_list_has_duplicates_of
```cpp

View File

@ -4,14 +4,14 @@ title: atomic
{{< callout type="info">}}
Header: `atomic.h`
Since: `TBC`
Since: `11.0.0`
Similar to: [atomic](https://en.cppreference.com/cpp/atomic/atomic)
{{< /callout >}}
This header attempts to replicate some of the types from `std::atomic`.
If `ETL_CPP11_SUPPORTED` is defined as `1` in the profile then `etl::atomic` will be defined in terms of `std::atomic`.
Otherwise it will be implemented in terms of the built-in support, if available, from the compiler. For example, early GCC and Arm compilers will use the `__sync` built-ins.
If `ETL_USING_CPP11` and `ETL_USING_STL` are defined as `1` then `etl::atomic` will be defined in terms of `std::atomic`.
Otherwise it will be implemented in terms of the built-in support, if available, from the compiler. For example, early GCC and Arm compilers will use the `__sync` built-ins, later versions use `__atomic` built-ins.
If a type cannot be handled by the built-ins then the types are wrapped by `etl::mutex`.
@ -19,3 +19,273 @@ If there is an ETL atomic type available for your platform then `ETL_HAS_ATOMIC`
it will be set to `0`.
From: `20.40.0` `etl::atomic` supports the `is_always_lock_free` property.
For GCC and clang built-ins:
Integrals and pointers are lock free.
All other types are not lock free.
---
```cpp
template <typename T>
struct atomic;
```
```cpp
template <typename T>
struct atomic<T*>;
```
## Memory order
```cpp
memory_order_relaxed
memory_order_consume
memory_order_acquire
memory_order_release
memory_order_acq_rel
memory_order_seq_cst
```
## Constructors
```cpp
ETL_CONSTEXPR atomic()
```
**Description**
Value initialises `T`.
---
```cpp
ETL_CONSTEXPR atomic(T v)
```
**Description**
Initialises `T` with `v`.
## Assignment
```cpp
T operator=(T v)
T operator=(T v) volatile
```
**Description**
Stores the value 'v'.
## Increment
```cpp
T operator++()
T operator++() volatile
```
**Description**
Pre-increments the atomic value by one.
---
```cpp
T operator++(int)
T operator++(int) volatile
```
**Description**
Post-increments the atomic value by one.
## Decrement
```cpp
T operator--()
T operator--() volatile
```
**Description**
Pre-decrements the atomic value by one.
---
```cpp
T operator--(int)
T operator--(int) volatile
```
**Description**
Post-decrements the atomic value by one.
## Add
```cpp
T operator+=(T v)
T operator+=(T v) volatile
```
**Description**
Adds to the atomic value.
## Subtract
```cpp
T operator-=(T v)
T operator-=(T v) volatile
```
**Description**
Subtracts from the atomic value.
## And
```cpp
T operator&=(T v)
T operator&=(T v) volatile
```
**Description**
Performs bitwise AND with the atomic value.
## Or
```cpp
T operator|=(T v)
T operator|=(T v) volatile
```
**Description**
Performs bitwise OR with the atomic value.
## Exclusive or
```cpp
T operator^=(T v)
T operator^=(T v) volatile
```
**Description**
Performs bitwise XOR with the atomic value.
## Conversion operator
```cpp
operator T() const
operator T() volatile const
```
**Description**
Loads a value from an atomic object.
## Is lock free
```cpp
bool is_lock_free() const
bool is_lock_free() const volatile
```
**Description**
Checks if the atomic object is lock-free.
## Store
```cpp
void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
**Description**
Atomically replaces the value of the atomic object with a non-atomic argument.
## Load
```cpp
T load(etl::memory_order order = etl::memory_order_seq_cst) const
T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile
```
**Description**
Atomically obtains the value of the atomic object.
## Fetch add
```cpp
T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst)
T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
```cpp
T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
**Description**
Atomically adds the argument to the value stored in the atomic object and obtains the value held previously.
## Fetch subtract
```cpp
T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst)
T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
```cpp
T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
**Description**
Atomically subtracts the argument to the value stored in the atomic object and obtains the value held previously.
## Fetch or
```cpp
T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst)
T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
**Description**
Atomically performs bitwise OR between the argument and the value of the atomic object and obtains the value held previously.
## Fetch and
```cpp
T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst)
T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
**Description**
Atomically performs bitwise AND between the argument and the value of the atomic object and obtains the value held previously.
## Fetch exclusive or
```cpp
T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst)
T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
**Description**
Atomically performs bitwise XOR between the argument and the value of the atomic object and obtains the value held previously.
## Fetch max
```cpp
T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst)
T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
**Description**
Atomically performs max between the argument and the value of the atomic object and obtains the value held previously.
## Fetch min
```cpp
T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst)
T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
**Description**
Atomically performs min between the argument and the value of the atomic object and obtains the value held previously.
## Exchange
```cpp
T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst)
T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
```
**Description**
Atomically replaces the value of the atomic object and obtains the value held previously.
## Compare exchange weak
```cpp
bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile
```
**Description**
Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not.
## Compare exchange strong
```cpp
bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile
```
**Description**
Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not.

View File

@ -28,54 +28,72 @@ second_argument_type;
cmp_result;
```
`cmp_result` has the values `Less`, `Equal`, and `Greater`.
`cmp_result` defines the values `Less`, `Equal`, and `Greater`.
## Members
```cpp
static bool lt(first_argument_type lhs, second_argument_type rhs)
```
**Description**
Less than.
**Return**
`true` if `lhs < rhs`, otherwise `false`.
`true` if `TLess()(lhs, rhs)`, otherwise `false`.
---
```cpp
static bool lte(first_argument_type lhs, second_argument_type rhs)
```
**Description**
Less than or equal.
**Return**
`true` if `lhs <= rhs`, otherwise `false`.
`true` if `lhs` is less than or equal to `rhs`, otherwise `false`.
---
```cpp
static bool gt(first_argument_type lhs, second_argument_type rhs)
```
**Description**
Greater than.
**Return**
`true` if `lhs > rhs`, otherwise `false`.
`true` if `lhs` is greater than `rhs`, otherwise `false`.
---
```cpp
static bool gte(first_argument_type lhs, second_argument_type rhs)
```
**Description**
Greater than or equal.
**Return**
`true` if `lhs >= rhs`, otherwise `false`.
`true` if `lhs` is greater than or equal to `rhs`, otherwise `false`.
---
```cpp
static bool eq(first_argument_type lhs, second_argument_type rhs)
```
**Description**
Equal.
**Return**
`true` if `lhs == rhs`, otherwise `false`.
`true` if neither value compares less than the other, otherwise `false`.
---
```cpp
static bool ne(first_argument_type lhs, second_argument_type rhs)
```
**Description**
Not equal.
**Return**
`true` if `lhs != rhs`, otherwise `false`.
`true` if if either value compare less than the other, otherwise `false`.
---

View File

@ -221,10 +221,12 @@ Checks equality of two cyclic values.
Previously the first and last limits were also considered.
<= 20.49.0
`etl::cyclic_value<2, 7>(3) != etl::cyclic_value<2, 6>(3)`
`etl::cyclic_value<int, 2, 7>(3) != etl::cyclic_value<int, 2, 6>(3)`
`etl::cyclic_value<int>(2, 7, 3) != etl::cyclic_value<int>(2, 6, 3)`
&gt; 20.49.0
`etl::cyclic_value<2, 7>(3) == etl::cyclic_value<2, 6>(3)`
`etl::cyclic_value<int, 2, 7>(3) == etl::cyclic_value<int, 2, 6>(3)`
`etl::cyclic_value<int>(2, 7, 3) == etl::cyclic_value<int>(2, 6, 3)`
{{< /callout >}}
---

View File

@ -1476,6 +1476,11 @@ namespace etl
//*********************************************************************
size_type find(T c, size_type position = 0) const
{
if (position >= size())
{
return npos;
}
const_iterator i = etl::find(begin() + position, end(), c);
if (i != end())
@ -1504,7 +1509,7 @@ namespace etl
///\param pos The position to start searching from.
//*********************************************************************
template <typename TOtherTraits>
size_type rfind(const etl::basic_string_view<T, TOtherTraits>& view, size_type pos = 0) const
size_type rfind(const etl::basic_string_view<T, TOtherTraits>& view, size_type pos = npos) const
{
return rfind_impl(view.rbegin(), view.rend(), view.size(), pos);
}
@ -1544,12 +1549,8 @@ namespace etl
//*********************************************************************
size_type rfind(T c, size_type position = npos) const
{
if (position >= size())
{
position = size();
}
position = size() - position;
// Reverse offset of the first character to check, which is 'position' itself.
position = (position >= size()) ? 0 : (size() - position - 1);
const_reverse_iterator i = etl::find(rbegin() + static_cast<difference_type>(position), rend(), c);
@ -2851,11 +2852,16 @@ namespace etl
template <typename TIterator>
size_type find_impl(TIterator first, TIterator last, size_type sz, size_type pos = 0) const
{
if ((pos + sz) > size())
if ((pos > size()) || (sz > (size() - pos)))
{
return npos;
}
if (sz == 0)
{
return pos;
}
const_iterator iposition = etl::search(begin() + pos, end(), first, last);
if (iposition == end())
@ -2879,12 +2885,18 @@ namespace etl
return npos;
}
if (pos >= size())
if (pos > (size() - sz))
{
pos = size();
pos = size() - sz;
}
pos = size() - pos;
if (sz == 0)
{
return pos;
}
// Reverse offset of the last character of a match starting at 'pos'.
pos = size() - (pos + sz);
const_reverse_iterator iposition = etl::search(rbegin() + static_cast<difference_type>(pos), rend(), rfirst, rlast);

View File

@ -724,7 +724,7 @@ namespace etl
///\param last The iterator to the last element + 1.
//*********************************************************************
template <typename TIterator>
void assign(TIterator first, TIterator last)
typename etl::enable_if<!etl::is_integral<TIterator>::value, void>::type assign(TIterator first, TIterator last)
{
ETL_STATIC_ASSERT((etl::is_same<typename etl::remove_cv<T>::type,
typename etl::remove_cv< typename etl::iterator_traits< TIterator>::value_type>::type>::value),
@ -1071,7 +1071,7 @@ namespace etl
///\param last The last + 1 element to add.
//*********************************************************************
template <class TIterator>
iterator insert(const_iterator position, TIterator first, TIterator last)
typename etl::enable_if<!etl::is_integral<TIterator>::value, iterator>::type insert(const_iterator position, TIterator first, TIterator last)
{
size_t count = size_t(etl::distance(first, last));
@ -1462,7 +1462,7 @@ namespace etl
///\param last The iterator to the last element + 1.
//*************************************************************************
template <typename TIterator>
indirect_vector(TIterator first, TIterator last)
indirect_vector(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
: etl::iindirect_vector<T>(lookup_vector, storage_pool)
{
this->assign(first, last);
@ -1613,7 +1613,8 @@ namespace etl
///\param last The iterator to the last element + 1.
//*************************************************************************
template <typename TIterator>
indirect_vector_ext(TIterator first, TIterator last, etl::ivector<T*>& lookup_, etl::ipool& pool_)
indirect_vector_ext(TIterator first, TIterator last, etl::ivector<T*>& lookup_, etl::ipool& pool_,
typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
: etl::iindirect_vector<T>(lookup_, pool_)
{
ETL_ASSERT(lookup_.capacity() <= pool_.capacity(), ETL_ERROR(indirect_vector_buffer_missmatch));

73
include/etl/meta.h Normal file
View File

@ -0,0 +1,73 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2026 BMW AG
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef ETL_META_INCLUDED
#define ETL_META_INCLUDED
#include "platform.h"
//*****************************************************************************
/// \defgroup meta meta
/// C++26 static reflection (P2996).
/// \ingroup etl
//*****************************************************************************
//*****************************************************************************
// This is the one and only place where reflection support is detected.
//
// GCC 16 is currently the only compiler that implements enough of P2996 for
// etl::meta, and it does so for both STL and non-STL builds.
// See .devcontainer/gcc16 for the reference toolchain.
//
// Clang (including the Bloomberg p2996 fork) and MSVC are not supported yet.
//
// ETL_HAS_REFLECTION is always defined, as 1 or 0.
// When it is 0 this header defines nothing else, so user code can include
// etl/meta.h unconditionally and test ETL_HAS_REFLECTION.
//*****************************************************************************
#if defined(ETL_COMPILER_GCC) && defined(__cpp_impl_reflection) && (__cpp_impl_reflection >= 202506L)
#define ETL_HAS_REFLECTION 1
#else
#define ETL_HAS_REFLECTION 0
#endif
#if ETL_HAS_REFLECTION
#if ETL_USING_STL
// The full standard library is available, so etl::meta is a thin
// using-declaration layer over std::meta.
#include "private/meta/stl.h"
#else
// No standard library: etl::meta supplies the minimal std declarations
// that the reflection builtins require.
#include "private/meta/gcc.h"
#endif
#endif
#endif // ETL_META_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2026 BMW AG
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef ETL_PRIVATE_META_STL_H_INCLUDED
#define ETL_PRIVATE_META_STL_H_INCLUDED
#include <cstddef>
#include <initializer_list>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include <meta>
#include <source_location> // Workaround for GCC 16: <meta> depends on <source_location> but does not include it.
///\defgroup meta meta
///\ingroup etl
namespace etl
{
namespace meta
{
//*************************************************************************
// Standard <meta> path, used when the full standard library is available.
//
// A using-directive is sufficient here: qualified lookup for
// etl::meta::foo also searches the namespaces nominated by the
// using-directives of etl::meta ([namespace.qual]), so every std::meta
// name - including the function templates such as extract<> - is
// reachable as etl::meta::name. This mirrors the non-STL implementation
// in gcc.h, which uses the same mechanism.
//*************************************************************************
using namespace std::meta;
// Enumerators of std::meta::operators (op_equals_equals, etc.) are scoped,
// so they need a using-enum-declaration rather than the using-directive.
using enum std::meta::operators;
//*************************************************************************
/// info_array — fixed-size, zero-allocation array of info values.
///
/// GCC limitation: template-for over a std::vector<info> fails because the
/// vector's heap allocation cannot persist in a constant expression. The
/// workaround is to copy the elements into a plain aggregate array (no
/// allocation) and iterate that instead.
///
/// Usage pattern:
/// constexpr auto N = std::meta::members_of(^^T, ctx).size();
/// constexpr auto arr = etl::meta::to_info_array<N>(
/// std::meta::members_of(^^T, ctx));
/// template for (constexpr auto m : arr) { ... }
//*************************************************************************
template <size_t N>
struct info_array
{
info elems[N > 0 ? N : 1]{};
consteval const info* begin() const
{
return elems;
}
consteval const info* end() const
{
return elems + N;
}
consteval size_t size() const
{
return N;
}
consteval const info& operator[](size_t i) const
{
return elems[i];
}
};
template <size_t N>
consteval info_array<N> to_info_array(const std::vector<info>& v)
{
info_array<N> a{};
for (size_t i = 0; i < N; ++i)
{
a.elems[i] = v[i];
}
return a;
}
} // namespace meta
} // namespace etl
#endif // ETL_PRIVATE_META_STL_H_INCLUDED

View File

@ -554,11 +554,16 @@ namespace etl
//*************************************************************************
ETL_CONSTEXPR14 size_type find(etl::basic_string_view<T, TTraits> view, size_type position = 0) const ETL_NOEXCEPT
{
if ((size() < view.size()))
if ((position > size()) || (view.size() > (size() - position)))
{
return npos;
}
if (view.empty())
{
return position;
}
const_iterator iposition = etl::search(begin() + position, end(), view.begin(), view.end());
if (iposition == end())
@ -598,9 +603,11 @@ namespace etl
position = etl::min(position, size() - view.size());
const_iterator iposition = etl::find_end(begin(), begin() + position + view.size(), view.begin(), view.end());
const_iterator search_end = begin() + position + view.size();
const_iterator iposition = etl::find_end(begin(), search_end, view.begin(), view.end());
if (iposition == end())
// find_end returns the end of the searched range when there is no match.
if ((iposition == search_end) && !view.empty())
{
return npos;
}

View File

@ -3808,9 +3808,14 @@ namespace etl
template <typename T>
struct is_nothrow_relocatable
{
#if ETL_USING_CPP11
static ETL_CONSTANT bool value = etl::is_trivially_relocatable<T>::value
|| (etl::is_nothrow_move_constructible<typename etl::remove_all_extents<T>::type>::value
&& etl::is_nothrow_destructible<typename etl::remove_all_extents<T>::type>::value);
#else
// No move semantics: only trivially relocatable types are known to be nothrow relocatable.
static ETL_CONSTANT bool value = etl::is_trivially_relocatable<T>::value;
#endif
};
#elif defined(ETL_USER_DEFINED_TYPE_TRAITS) && !defined(ETL_USE_TYPE_TRAITS_BUILTINS)

View File

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.10)
project(etl_unit_tests LANGUAGES CXX)
include(CheckCXXCompilerFlag)
#include(FetchContent)
#FetchContent_Declare(
# googletest
@ -233,6 +235,7 @@ add_executable(etl_tests
test_map.cpp
test_math.cpp
test_math_functions.cpp
test_meta.cpp
test_mean.cpp
test_memory.cpp
test_mem_cast.cpp
@ -517,6 +520,16 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
${EXTRA_COMPILE_OPTIONS}
)
target_link_options(etl_tests PRIVATE ${EXTRA_LINK_OPTIONS})
if (ETL_CXX_STANDARD MATCHES "26")
# -freflection is only accepted when compiling as C++26, so probe with that standard.
set(CMAKE_REQUIRED_FLAGS "-std=c++26")
check_cxx_compiler_flag(-freflection ETL_GNU_HAS_FREFLECTION)
unset(CMAKE_REQUIRED_FLAGS)
if (ETL_GNU_HAS_FREFLECTION)
target_compile_options(etl_tests PRIVATE -freflection)
endif ()
endif ()
endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")

View File

@ -234,6 +234,7 @@ etl_test_sources = files(
'test_message_timer_atomic.cpp',
'test_message_timer_interrupt.cpp',
'test_message_timer_locked.cpp',
'test_meta.cpp',
'test_multi_array.cpp',
'test_multi_range.cpp',
'test_multi_span.cpp',

View File

@ -290,6 +290,7 @@ target_sources(tests PRIVATE
message_timer_interrupt.h.t.cpp
message_timer_locked.h.t.cpp
message_types.h.t.cpp
meta.h.t.cpp
multimap.h.t.cpp
multiset.h.t.cpp
multi_array.h.t.cpp

View File

@ -0,0 +1,40 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2026 BMW AG
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#include <etl/meta.h>
// etl/meta.h must be includable unconditionally, on every compiler and every
// language standard. Where reflection is unavailable it defines nothing
// except ETL_HAS_REFLECTION, which is always defined as either 1 or 0.
#if !defined(ETL_HAS_REFLECTION)
#error ETL_HAS_REFLECTION is not defined by etl/meta.h
#endif
#if (ETL_HAS_REFLECTION != 0) && (ETL_HAS_REFLECTION != 1)
#error ETL_HAS_REFLECTION must be defined as 0 or 1
#endif

View File

@ -1201,6 +1201,42 @@ namespace
CHECK_THROW(data.insert(data.begin() + static_cast<ptrdiff_t>(offset), INSERT_SIZE, INITIAL_VALUE), etl::vector_full);
}
//*************************************************************************
TEST(test_constructor_two_parameter_same_type_not_iterator)
{
std::vector<int> compare_data(5, 7);
etl::indirect_vector<int, 10> data(5, 7);
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(data.begin(), data.end(), compare_data.begin()));
}
//*************************************************************************
TEST(test_assign_two_parameter_same_type_not_iterator)
{
std::vector<size_t> compare_data;
etl::indirect_vector<size_t, 10> data;
compare_data.assign(5, 7);
data.assign(5, 7);
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(data.begin(), data.end(), compare_data.begin()));
}
//*************************************************************************
TEST(test_insert_three_parameter_same_type_not_iterator)
{
std::vector<int> compare_data(3UL, 1);
etl::indirect_vector<int, 10> data(3UL, 1);
compare_data.insert(compare_data.begin(), 2, 7);
data.insert(data.begin(), 2, 7);
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(data.begin(), data.end(), compare_data.begin()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_position_range)
{

View File

@ -335,6 +335,22 @@ namespace
CHECK_EQUAL(4U, *data2[3]);
}
//*************************************************************************
TEST(test_constructor_two_parameter_same_type_not_iterator)
{
LookupInt lookup;
PoolInt pool;
etl::indirect_vector_ext<int> data(5, 7, lookup, pool);
CHECK_EQUAL(5U, data.size());
CHECK_EQUAL(7, data[0]);
CHECK_EQUAL(7, data[1]);
CHECK_EQUAL(7, data[2]);
CHECK_EQUAL(7, data[3]);
CHECK_EQUAL(7, data[4]);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assignment)
{

2391
test/test_meta.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3815,6 +3815,33 @@ namespace
CHECK_EQUAL(TextL::npos, position2);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_find_rfind_all_positions)
{
const value_t the_haystack[] = STR("A haystack with a needle and another needle");
TextSTD compare_haystack(the_haystack);
TextL haystack(the_haystack);
const value_t* needles[] = {STR("needle"), STR("e"), STR("")};
// Every position up to past the end, where the search must not read outside the string.
for (size_t position = 0UL; position <= compare_haystack.size() + 2UL; ++position)
{
for (size_t i = 0UL; i < 3UL; ++i)
{
CHECK_EQUAL(compare_haystack.find(needles[i], position), haystack.find(needles[i], position));
CHECK_EQUAL(compare_haystack.rfind(needles[i], position), haystack.rfind(needles[i], position));
}
CHECK_EQUAL(compare_haystack.find(STR('e'), position), haystack.find(STR('e'), position));
CHECK_EQUAL(compare_haystack.rfind(STR('e'), position), haystack.rfind(STR('e'), position));
}
CHECK_EQUAL(TextL::npos, haystack.find(STR('e'), TextL::npos));
CHECK_EQUAL(TextL::npos, haystack.find(STR("needle"), TextL::npos));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_contains_string)
{
@ -3991,6 +4018,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -4362,6 +4362,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -4063,6 +4063,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -4464,6 +4464,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -4063,6 +4063,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -4464,6 +4464,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -4008,6 +4008,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -4383,6 +4383,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -925,6 +925,27 @@ namespace
CHECK(View::npos == view.rfind(s4, 0, 11));
}
//*************************************************************************
TEST(test_find_rfind_all_positions)
{
const std::string compare_text("abcdabcdab");
View view(compare_text.c_str());
const char* needles[] = {"cd", "d", "x", ""};
// Every position up to past the end, where the search must not read outside the view.
for (size_t position = 0U; position <= compare_text.size() + 2U; ++position)
{
for (size_t i = 0U; i < 4U; ++i)
{
CHECK_EQUAL(compare_text.find(needles[i], position), view.find(needles[i], position));
CHECK_EQUAL(compare_text.rfind(needles[i], position), view.rfind(needles[i], position));
}
}
CHECK_EQUAL(View::npos, view.find("cd", View::npos));
}
//*************************************************************************
TEST(test_find_first_of)
{

View File

@ -4064,6 +4064,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -4467,6 +4467,11 @@ namespace
position2 = haystack.rfind(needle_view, haystack.size() - 10);
CHECK_EQUAL(position1, position2);
// The default position searches the whole string.
position1 = compare_haystack.rfind(compare_needle);
position2 = haystack.rfind(needle_view);
CHECK_EQUAL(position1, position2);
View pin_view(STR("pin"));
position2 = haystack.rfind(pin_view);
CHECK_EQUAL(TextL::npos, position2);

View File

@ -10455,6 +10455,7 @@
<ClCompile Include="..\test_message_timer_atomic.cpp" />
<ClCompile Include="..\test_message_timer_interrupt.cpp" />
<ClCompile Include="..\test_message_timer_locked.cpp" />
<ClCompile Include="..\test_meta.cpp" />
<ClCompile Include="..\test_multi_array.cpp" />
<ClCompile Include="..\test_array.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../../unittest-cpp</AdditionalIncludeDirectories>

View File

@ -1685,6 +1685,9 @@
<ClCompile Include="..\test_message_timer_locked.cpp">
<Filter>Tests\Messaging</Filter>
</ClCompile>
<ClCompile Include="..\test_meta.cpp">
<Filter>Tests\Types</Filter>
</ClCompile>
<ClCompile Include="..\test_shared_message.cpp">
<Filter>Tests\Messaging</Filter>
</ClCompile>

View File

@ -3,6 +3,16 @@ if(CONFIG_ETL)
zephyr_link_libraries(etl::etl)
zephyr_compile_definitions_ifdef(CONFIG_ETL_DEBUG ETL_DEBUG)
zephyr_compile_definitions_ifdef(CONFIG_ETL_CHECK_PUSH_POP ETL_CHECK_PUSH_POP)
zephyr_compile_definitions_ifdef(CONFIG_ETL_LOG_ERRORS ETL_LOG_ERRORS)
zephyr_compile_definitions_ifdef(CONFIG_ETL_USE_ASSERT_FUNCTION ETL_USE_ASSERT_FUNCTION)
zephyr_compile_definitions_ifdef(CONFIG_ETL_THROW_EXCEPTIONS ETL_THROW_EXCEPTIONS)
zephyr_compile_definitions_ifdef(CONFIG_ETL_NO_CHECKS ETL_NO_CHECKS)
zephyr_compile_definitions_ifdef(CONFIG_ETL_VERBOSE_ERRORS ETL_VERBOSE_ERRORS)
zephyr_compile_definitions_ifdef(CONFIG_ETL_MINIMAL_ERRORS ETL_MINIMAL_ERRORS)
zephyr_compile_definitions_ifdef(CONFIG_ETL_CHECK_PUSH_POP ETL_CHECK_PUSH_POP)
zephyr_compile_definitions_ifdef(CONFIG_ETL_CHECK_INDEX_OPERATOR ETL_CHECK_INDEX_OPERATOR)
zephyr_compile_definitions_ifdef(CONFIG_ETL_CHECK_EXTRA ETL_CHECK_EXTRA)
endif()

View File

@ -8,12 +8,78 @@ if ETL
config ETL_DEBUG
bool "Build ETL with debugging checks"
default y if DEBUG
default y if ASSERT
choice ETL_ERROR_MODE
prompt "ETL error handling mode"
help
What ETL does when one of its checks fails.
config ETL_ASSERT_ERRORS
bool "Assert in ETL_DEBUG builds, otherwise ignore"
help
With ETL_DEBUG, a failed check calls assert(). Without it, nothing
is reported, but checks that guard an operation still skip it.
With ETL_LOG_ERRORS, a failed check calls the error handler instead,
with or without ETL_DEBUG.
config ETL_USE_ASSERT_FUNCTION
bool "Call a user assert function"
help
A failed check calls the function registered with
etl::set_assert_function(), and checks that guard an operation
still skip it. Until one is registered, it calls assert(false).
config ETL_THROW_EXCEPTIONS
bool "Throw an exception"
depends on CPP_EXCEPTIONS
help
A failed check throws an etl::exception.
config ETL_NO_CHECKS
bool "No checks"
help
Check conditions are not evaluated.
endchoice # ETL_ERROR_MODE
config ETL_LOG_ERRORS
bool "Call the ETL error handler"
depends on !ETL_USE_ASSERT_FUNCTION && !ETL_NO_CHECKS
help
A failed check calls the callback registered with
etl::error_handler::set_callback(). With ETL_THROW_EXCEPTIONS it
then throws; otherwise, checks that guard an operation still skip
it. With no callback registered, errors are discarded.
choice ETL_ERROR_DETAIL
prompt "ETL error detail level"
help
What information the etl::exception for a failed check carries,
whether it is thrown or passed to the error handler or assert
function. Unused when a failed check calls plain assert().
config ETL_TERSE_ERRORS
bool "Short error code only"
config ETL_VERBOSE_ERRORS
bool "Message, file and line"
config ETL_MINIMAL_ERRORS
bool "Nothing"
endchoice # ETL_ERROR_DETAIL
config ETL_CHECK_PUSH_POP
bool "Enable push/pop checks in ETL"
depends on !ETL_NO_CHECKS
config ETL_LOG_ERRORS
bool "Call ETL error handler instead of assert"
config ETL_CHECK_INDEX_OPERATOR
bool "Enable bounds checks on ETL operator[]"
depends on !ETL_NO_CHECKS
config ETL_CHECK_EXTRA
bool "Enable extra bounds and empty checks in ETL containers"
depends on !ETL_NO_CHECKS
endif # ETL