mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-15 08:26:04 +08:00
Merge branch 'development' into optional_rule_of_zero
This commit is contained in:
commit
9f4e191235
@ -41,7 +41,7 @@ elif [ "$2" = "inside_container" ] ; then
|
||||
cd build-$ARCH
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=../.devcontainer/$ARCH/toolchain-$ARCH.cmake \
|
||||
-DBUILD_TESTS=ON -DNO_STL=ON -DETL_CXX_STANDARD=23 \
|
||||
-DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=-O0 -DETL_ENABLE_SANITIZER=Off -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF \
|
||||
-DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=-O0 -DETL_ENABLE_SANITIZER=OFF -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF \
|
||||
../test
|
||||
export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
|
||||
cmake --build .
|
||||
|
||||
31
.github/workflows/meson-gcc-c++23-no-stl.yml
vendored
Normal file
31
.github/workflows/meson-gcc-c++23-no-stl.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
name: meson-gcc-c++23-no-stl
|
||||
on:
|
||||
push:
|
||||
branches: [ master, development, pull-request/* ]
|
||||
pull_request:
|
||||
branches: [ master, development, pull-request/* ]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
|
||||
build-meson-gcc-cpp23-no-stl:
|
||||
name: Meson GCC C++23 Linux - No STL
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Install Meson
|
||||
run: sudo apt-get install -y meson
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
meson setup builddir -Duse_stl=false -Dcpp_std=c++23
|
||||
|
||||
- name: Build
|
||||
run: meson compile -C builddir
|
||||
|
||||
- name: Run tests
|
||||
run: meson test -C builddir -v
|
||||
@ -365,8 +365,15 @@ etl::format_to(s, "a}b"); // unescaped }
|
||||
etl::format_to(s, "{:d}", sv); // invalid type for string_view
|
||||
```
|
||||
|
||||
> **Note:** On C++20 and later, compile-time format string validation through
|
||||
> `consteval` is planned but not yet fully implemented.
|
||||
> **Note:** On C++20 and later, format strings are validated at compile time
|
||||
> via `consteval`. The checks cover syntax (balanced braces, valid format spec
|
||||
> grammar, index bounds, no mixing of automatic and manual indexing) as well as
|
||||
> type/specifier compatibility (e.g. `{:d}` is rejected for string arguments).
|
||||
> A malformed format string produces a compile error whose diagnostic mentions
|
||||
> `please_note_this_is_error_message_format_string_syntax_error`.
|
||||
>
|
||||
> On C++11–C++17, the same checks run at runtime and throw
|
||||
> `etl::bad_format_string_exception`.
|
||||
|
||||
## 10. Differences from `std::format`
|
||||
|
||||
@ -378,5 +385,5 @@ etl::format_to(s, "{:d}", sv); // invalid type for string_view
|
||||
| **Floating-point support** | Always available | Opt-in via `ETL_USING_FORMAT_FLOATING_POINT`. |
|
||||
| **User-defined formatters** | `std::formatter<T>` specialisations | Not yet supported. |
|
||||
| **Locale** | `L` flag uses `std::locale` | `L` flag is parsed but has no effect. |
|
||||
| **Compile-time validation** | Enforced via `consteval` on C++20 | Planned; currently validates at run time and throws `etl::bad_format_string_exception`. |
|
||||
| **Compile-time validation** | Enforced via `consteval` on C++20 | Enforced via `consteval` on C++20 (syntax and type/specifier compatibility); validates at run time and throws `etl::bad_format_string_exception` on C++11–C++17. |
|
||||
| **`format_to_n` return type** | `std::format_to_n_result` | Returns the underlying `OutputIt` directly. |
|
||||
|
||||
116
docs/meson.md
Normal file
116
docs/meson.md
Normal file
@ -0,0 +1,116 @@
|
||||
# Building ETL with Meson
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Meson](https://mesonbuild.com/) >= 0.57.0
|
||||
- A C++17 compiler (GCC, Clang, or MSVC)
|
||||
- [Ninja](https://ninja-build.org/) (default Meson backend)
|
||||
|
||||
UnitTest++ is fetched automatically as a Meson subproject — no manual dependency installation is needed.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Configure (from the project root)
|
||||
meson setup builddir
|
||||
|
||||
# Build
|
||||
meson compile -C builddir
|
||||
|
||||
# Run tests
|
||||
meson test -C builddir
|
||||
```
|
||||
|
||||
## Build Options
|
||||
|
||||
### ETL project options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|---------------------|------|---------|-------------------------------------------------------------------|
|
||||
| `use_stl` | bool | `true` | Build with STL support. When `false`, defines `ETL_NO_STL`. |
|
||||
| `enable_sanitizer` | bool | `false` | Enable AddressSanitizer and UndefinedBehaviorSanitizer (GCC/Clang only). |
|
||||
|
||||
### Meson built-in options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|-------------|--------|----------|----------------------------------------------------------|
|
||||
| `cpp_std` | string | `c++17` | C++ standard to compile with (e.g. `c++20`, `c++23`). |
|
||||
| `buildtype` | string | `debug` | Build type: `plain`, `debug`, `debugoptimized`, `release`, `minsize`. |
|
||||
| `werror` | bool | `false` | Treat compiler warnings as errors. |
|
||||
|
||||
These are handled by Meson directly — no `get_option()` call is needed in the build files.
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# No STL, C++23
|
||||
meson setup builddir -Duse_stl=false -Dcpp_std=c++23
|
||||
|
||||
# Release build with sanitizers
|
||||
meson setup builddir -Dbuildtype=release -Denable_sanitizer=true
|
||||
|
||||
# Override the C++ standard on an existing build directory
|
||||
meson configure builddir -Dcpp_std=c++20
|
||||
```
|
||||
|
||||
## Selecting a Compiler
|
||||
|
||||
The compiler is chosen at configure time via environment variables:
|
||||
|
||||
```bash
|
||||
# GCC
|
||||
CC=gcc CXX=g++ meson setup builddir
|
||||
|
||||
# Clang
|
||||
CC=clang CXX=clang++ meson setup builddir
|
||||
|
||||
# Specific versions
|
||||
CC=gcc-14 CXX=g++-14 meson setup builddir
|
||||
CC=clang-18 CXX=clang++-18 meson setup builddir
|
||||
```
|
||||
|
||||
To switch compilers on an existing build directory, wipe it first:
|
||||
|
||||
```bash
|
||||
CC=clang CXX=clang++ meson setup --wipe builddir
|
||||
```
|
||||
|
||||
Or use separate directories per compiler:
|
||||
|
||||
```bash
|
||||
CC=gcc CXX=g++ meson setup build-gcc
|
||||
CC=clang CXX=clang++ meson setup build-clang
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
meson test -C builddir
|
||||
|
||||
# Verbose output (shows individual test results)
|
||||
meson test -C builddir -v
|
||||
|
||||
# Run the test binary directly
|
||||
./builddir/test/etl_unit_tests
|
||||
```
|
||||
|
||||
## Sanitizers
|
||||
|
||||
On GCC and Clang, AddressSanitizer and UndefinedBehaviorSanitizer can be enabled via the `enable_sanitizer` option:
|
||||
|
||||
```bash
|
||||
meson setup builddir -Denable_sanitizer=true
|
||||
```
|
||||
|
||||
Note: UBSan may prevent certain `constexpr` evaluations involving function pointers from compiling (e.g. in the closure tests). This matches the CMake build, where sanitizers are also opt-in via `ETL_ENABLE_SANITIZER=ON`.
|
||||
|
||||
## Using ETL as a Subproject
|
||||
|
||||
ETL can be consumed as a Meson subproject. In your project's `subprojects/` directory, create an `etl.wrap` file, then use:
|
||||
|
||||
```meson
|
||||
etl_dep = dependency('etl', fallback: ['etl', 'etl_dep'])
|
||||
```
|
||||
|
||||
When built as a subproject, the ETL test suite is not compiled.
|
||||
@ -51,7 +51,7 @@ SOFTWARE.
|
||||
#include "type_traits.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "private/minmax_push.h"
|
||||
@ -91,26 +91,6 @@ namespace etl
|
||||
template <typename TIterator, typename TCompare>
|
||||
ETL_CONSTEXPR14 void insertion_sort(TIterator first, TIterator last, TCompare compare);
|
||||
|
||||
class algorithm_exception : public etl::exception
|
||||
{
|
||||
public:
|
||||
|
||||
algorithm_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: exception(reason_, file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class algorithm_error : public algorithm_exception
|
||||
{
|
||||
public:
|
||||
|
||||
algorithm_error(string_type file_name_, numeric_type line_number_)
|
||||
: algorithm_exception(ETL_ERROR_TEXT("algorithm:error", ETL_ALGORITHM_FILE_ID"A"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace etl
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
@ -35,10 +35,7 @@ SOFTWARE.
|
||||
#include "algorithm.h"
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "functional.h"
|
||||
#include "initializer_list.h"
|
||||
#include "iterator.h"
|
||||
#include "nth_type.h"
|
||||
#include "parameter_type.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
@ -31,11 +31,8 @@ SOFTWARE.
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "integral_limits.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**************************************************************************************************************************************************************************
|
||||
* See https://en.wikipedia.org/wiki/Base64
|
||||
*
|
||||
|
||||
@ -34,7 +34,6 @@ SOFTWARE.
|
||||
///\ingroup string
|
||||
|
||||
#include "platform.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
@ -39,7 +39,6 @@ SOFTWARE.
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "flags.h"
|
||||
#include "functional.h"
|
||||
#include "integral_limits.h"
|
||||
#include "iterator.h"
|
||||
#include "memory.h"
|
||||
@ -93,20 +92,6 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup string
|
||||
/// String empty exception.
|
||||
//***************************************************************************
|
||||
class string_empty : public etl::string_exception
|
||||
{
|
||||
public:
|
||||
|
||||
string_empty(string_type file_name_, numeric_type line_number_)
|
||||
: string_exception(ETL_ERROR_TEXT("string:empty", ETL_BASIC_STRING_FILE_ID"A"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup string
|
||||
/// String out of bounds exception.
|
||||
@ -1481,9 +1466,7 @@ namespace etl
|
||||
//*********************************************************************
|
||||
size_type find(const_pointer s, size_type pos, size_type n) const
|
||||
{
|
||||
size_t sz = etl::strlen(s);
|
||||
|
||||
return find_impl(s, s + n, sz, pos);
|
||||
return find_impl(s, s + n, n, pos);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
@ -2742,6 +2725,7 @@ namespace etl
|
||||
iterator>::type
|
||||
copy_characters(TIterator1 from, size_t n, iterator to)
|
||||
{
|
||||
#include "etl/private/diagnostic_stringop_overflow_push.h"
|
||||
size_t count = 0;
|
||||
|
||||
while (count != n)
|
||||
@ -2750,6 +2734,7 @@ namespace etl
|
||||
++count;
|
||||
}
|
||||
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
return to;
|
||||
}
|
||||
|
||||
@ -3218,8 +3203,6 @@ namespace etl
|
||||
#endif
|
||||
} // namespace etl
|
||||
|
||||
#undef ETL_USING_WCHAR_T_H
|
||||
|
||||
#include "private/minmax_pop.h"
|
||||
|
||||
#endif
|
||||
|
||||
@ -1742,7 +1742,7 @@ namespace etl
|
||||
{
|
||||
count = 1U;
|
||||
|
||||
if ((value & 0xFFFFFFFFF0000000ULL) == 0U)
|
||||
if ((value & 0xFFFFFFFF00000000ULL) == 0U)
|
||||
{
|
||||
value <<= 32U;
|
||||
count += 32U;
|
||||
@ -1795,7 +1795,7 @@ namespace etl
|
||||
{
|
||||
typedef typename etl::make_unsigned<T>::type unsigned_t;
|
||||
|
||||
return static_cast<T>(count_trailing_ones(static_cast<unsigned_t>(value)));
|
||||
return static_cast<T>(count_leading_zeros(static_cast<unsigned_t>(value)));
|
||||
}
|
||||
|
||||
#if ETL_USING_8BIT_TYPES
|
||||
@ -1927,8 +1927,8 @@ namespace etl
|
||||
|
||||
if ((value & 0xFFFF0000UL) == 0xFFFF0000UL)
|
||||
{
|
||||
value <<= 8U;
|
||||
count += 8U;
|
||||
value <<= 16U;
|
||||
count += 16U;
|
||||
}
|
||||
|
||||
if ((value & 0xFF000000UL) == 0xFF000000UL)
|
||||
@ -1988,14 +1988,14 @@ namespace etl
|
||||
|
||||
if ((value & 0xFFFFFFFF00000000ULL) == 0xFFFFFFFF00000000ULL)
|
||||
{
|
||||
value <<= 8U;
|
||||
count += 8U;
|
||||
value <<= 32U;
|
||||
count += 32U;
|
||||
}
|
||||
|
||||
if ((value & 0xFFFF000000000000ULL) == 0xFFFF000000000000ULL)
|
||||
{
|
||||
value <<= 8U;
|
||||
count += 8U;
|
||||
value <<= 16U;
|
||||
count += 16U;
|
||||
}
|
||||
|
||||
if ((value & 0xFF00000000000000ULL) == 0xFF00000000000000ULL)
|
||||
|
||||
@ -51,7 +51,6 @@ SOFTWARE.
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if ETL_HAS_ATOMIC
|
||||
|
||||
|
||||
@ -33,10 +33,10 @@ SOFTWARE.
|
||||
|
||||
#include "platform.h"
|
||||
#include "iterator.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
|
||||
@ -36,10 +36,9 @@ SOFTWARE.
|
||||
#include "array.h"
|
||||
#include "cyclic_value.h"
|
||||
#include "delegate.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <stddef.h>
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
|
||||
|
||||
@ -40,13 +40,11 @@ SOFTWARE.
|
||||
#include "integral_limits.h"
|
||||
#include "iterator.h"
|
||||
#include "memory.h"
|
||||
#include "nullptr.h"
|
||||
#include "optional.h"
|
||||
#include "span.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -629,7 +629,6 @@ namespace etl
|
||||
timer_list(timer_data* ptimers_)
|
||||
: head(etl::timer::id::NO_TIMER)
|
||||
, tail(etl::timer::id::NO_TIMER)
|
||||
, current(etl::timer::id::NO_TIMER)
|
||||
, ptimers(ptimers_)
|
||||
{
|
||||
}
|
||||
@ -758,22 +757,13 @@ namespace etl
|
||||
//*******************************
|
||||
etl::timer::id::type begin()
|
||||
{
|
||||
current = head;
|
||||
return current;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type previous(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].previous;
|
||||
return current;
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type next(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].next;
|
||||
return current;
|
||||
return ptimers[last].next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
@ -788,16 +778,14 @@ namespace etl
|
||||
timer.next = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
current = etl::timer::id::NO_TIMER;
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
etl::timer::id::type head;
|
||||
etl::timer::id::type tail;
|
||||
etl::timer::id::type current;
|
||||
|
||||
timer_data* const ptimers;
|
||||
};
|
||||
|
||||
@ -33,8 +33,6 @@ SOFTWARE.
|
||||
#include "algorithm.h"
|
||||
#include "delegate.h"
|
||||
#include "error_handler.h"
|
||||
#include "function.h"
|
||||
#include "nullptr.h"
|
||||
#include "placement_new.h"
|
||||
#include "static_assert.h"
|
||||
#include "timer.h"
|
||||
@ -487,7 +485,6 @@ namespace etl
|
||||
timer_list(timer_data* ptimers_)
|
||||
: head(etl::timer::id::NO_TIMER)
|
||||
, tail(etl::timer::id::NO_TIMER)
|
||||
, current(etl::timer::id::NO_TIMER)
|
||||
, ptimers(ptimers_)
|
||||
{
|
||||
}
|
||||
@ -616,22 +613,13 @@ namespace etl
|
||||
//*******************************
|
||||
etl::timer::id::type begin()
|
||||
{
|
||||
current = head;
|
||||
return current;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type previous(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].previous;
|
||||
return current;
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type next(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].next;
|
||||
return current;
|
||||
return ptimers[last].next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
@ -646,16 +634,14 @@ namespace etl
|
||||
timer.next = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
current = etl::timer::id::NO_TIMER;
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
etl::timer::id::type head;
|
||||
etl::timer::id::type tail;
|
||||
etl::timer::id::type current;
|
||||
|
||||
timer_data* const ptimers;
|
||||
};
|
||||
|
||||
@ -33,7 +33,6 @@ SOFTWARE.
|
||||
#include "algorithm.h"
|
||||
#include "delegate.h"
|
||||
#include "error_handler.h"
|
||||
#include "nullptr.h"
|
||||
#include "placement_new.h"
|
||||
#include "static_assert.h"
|
||||
#include "timer.h"
|
||||
@ -487,7 +486,6 @@ namespace etl
|
||||
timer_list(timer_data* ptimers_)
|
||||
: head(etl::timer::id::NO_TIMER)
|
||||
, tail(etl::timer::id::NO_TIMER)
|
||||
, current(etl::timer::id::NO_TIMER)
|
||||
, ptimers(ptimers_)
|
||||
{
|
||||
}
|
||||
@ -616,22 +614,13 @@ namespace etl
|
||||
//*******************************
|
||||
etl::timer::id::type begin()
|
||||
{
|
||||
current = head;
|
||||
return current;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type previous(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].previous;
|
||||
return current;
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type next(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].next;
|
||||
return current;
|
||||
return ptimers[last].next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
@ -646,16 +635,14 @@ namespace etl
|
||||
timer.next = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
current = etl::timer::id::NO_TIMER;
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
etl::timer::id::type head;
|
||||
etl::timer::id::type tail;
|
||||
etl::timer::id::type current;
|
||||
|
||||
timer_data* const ptimers;
|
||||
};
|
||||
|
||||
@ -33,7 +33,6 @@ SOFTWARE.
|
||||
#include "algorithm.h"
|
||||
#include "delegate.h"
|
||||
#include "error_handler.h"
|
||||
#include "nullptr.h"
|
||||
#include "placement_new.h"
|
||||
#include "static_assert.h"
|
||||
#include "timer.h"
|
||||
@ -460,7 +459,6 @@ namespace etl
|
||||
timer_list(timer_data* ptimers_)
|
||||
: head(etl::timer::id::NO_TIMER)
|
||||
, tail(etl::timer::id::NO_TIMER)
|
||||
, current(etl::timer::id::NO_TIMER)
|
||||
, ptimers(ptimers_)
|
||||
{
|
||||
}
|
||||
@ -589,22 +587,13 @@ namespace etl
|
||||
//*******************************
|
||||
etl::timer::id::type begin()
|
||||
{
|
||||
current = head;
|
||||
return current;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type previous(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].previous;
|
||||
return current;
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type next(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].next;
|
||||
return current;
|
||||
return ptimers[last].next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
@ -619,16 +608,14 @@ namespace etl
|
||||
timer.next = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
current = etl::timer::id::NO_TIMER;
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
etl::timer::id::type head;
|
||||
etl::timer::id::type tail;
|
||||
etl::timer::id::type current;
|
||||
|
||||
timer_data* const ptimers;
|
||||
};
|
||||
|
||||
@ -1206,7 +1206,7 @@ namespace etl
|
||||
{
|
||||
this->clear();
|
||||
|
||||
for (typename etl::icircular_buffer<T>::const_iterator itr = other.begin(); itr != other.end(); ++itr)
|
||||
for (typename etl::icircular_buffer<T>::iterator itr = other.begin(); itr != other.end(); ++itr)
|
||||
{
|
||||
this->push(etl::move(*itr));
|
||||
}
|
||||
|
||||
@ -34,6 +34,4 @@ SOFTWARE.
|
||||
#include "platform.h"
|
||||
#include "iterator.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#endif
|
||||
|
||||
@ -38,11 +38,8 @@ SOFTWARE.
|
||||
#include "platform.h"
|
||||
#include "algorithm.h"
|
||||
#include "exception.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
|
||||
@ -32,9 +32,6 @@ SOFTWARE.
|
||||
#define ETL_DEBOUNCE_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "static_assert.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -34,9 +34,10 @@ SOFTWARE.
|
||||
#include "platform.h"
|
||||
#include "array.h"
|
||||
#include "delegate.h"
|
||||
#include "nullptr.h"
|
||||
#include "static_assert.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
|
||||
@ -44,7 +44,6 @@ SOFTWARE.
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "private/minmax_push.h"
|
||||
|
||||
@ -462,19 +461,6 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
//***************************************************
|
||||
difference_type distance(difference_type firstIndex, difference_type index_) const
|
||||
{
|
||||
if (index_ < firstIndex)
|
||||
{
|
||||
return static_cast<difference_type>(p_deque->Buffer_Size) + index_ - firstIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
return index_ - firstIndex;
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
iterator(difference_type index_, ideque& the_deque, pointer p_buffer_)
|
||||
: index(index_)
|
||||
@ -619,10 +605,10 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
reference operator[](size_t i)
|
||||
const_reference operator[](size_t i) const
|
||||
{
|
||||
iterator result(*this);
|
||||
result += i;
|
||||
const_iterator result(*this);
|
||||
result += static_cast<difference_type>(i);
|
||||
|
||||
return *result;
|
||||
}
|
||||
@ -721,19 +707,6 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
//***************************************************
|
||||
difference_type distance(difference_type firstIndex, difference_type index_) const
|
||||
{
|
||||
if (index_ < firstIndex)
|
||||
{
|
||||
return static_cast<difference_type>(p_deque->Buffer_Size) + index_ - firstIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
return index_ - firstIndex;
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
const_iterator(difference_type index_, ideque& the_deque, pointer p_buffer_)
|
||||
: index(index_)
|
||||
|
||||
@ -206,7 +206,7 @@ namespace etl
|
||||
//*******************************************
|
||||
/// Get the error.
|
||||
//*******************************************
|
||||
ETL_CONSTEXPR14 TError&& error() const&& ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 const TError&& error() const&& ETL_NOEXCEPT
|
||||
{
|
||||
return etl::move(error_value);
|
||||
}
|
||||
@ -1309,7 +1309,7 @@ namespace etl
|
||||
template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&&>::type>::type>
|
||||
auto transform_error(F&& f) const&& -> expected<void, U>
|
||||
{
|
||||
return transform_error_impl<F, const this_type&&, U, const TError&&>(etl::forward<F>(f), *this);
|
||||
return transform_error_impl<F, const this_type&&, U, const TError&&>(etl::forward<F>(f), etl::move(*this));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -39,8 +39,6 @@ SOFTWARE.
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -100,26 +100,6 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
//*********************************************************************
|
||||
/// How to compare elements and keys.
|
||||
//*********************************************************************
|
||||
class compare
|
||||
{
|
||||
public:
|
||||
|
||||
bool operator()(const value_type& element, key_type key) const
|
||||
{
|
||||
return comp(element.first, key);
|
||||
}
|
||||
|
||||
bool operator()(key_type key, const value_type& element) const
|
||||
{
|
||||
return comp(key, element.first);
|
||||
}
|
||||
|
||||
key_compare comp;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//*********************************************************************
|
||||
|
||||
@ -34,7 +34,6 @@ SOFTWARE.
|
||||
#include "platform.h"
|
||||
#include "frame_check_sequence.h"
|
||||
#include "ihash.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@ -76,17 +76,409 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
template <class... Args>
|
||||
ETL_CONSTEXPR14 bool check_f(const char* fmt)
|
||||
#if ETL_USING_CPP20
|
||||
namespace private_format_check
|
||||
{
|
||||
// to be implemented later
|
||||
// return fmt[0] == 0; // actual check
|
||||
// Type category for compile-time type/specifier compatibility checking
|
||||
enum class type_category
|
||||
{
|
||||
NONE, // monostate
|
||||
BOOLEAN, // bool
|
||||
CHAR, // char
|
||||
INTEGER, // int, unsigned, long long, unsigned long long, short, etc.
|
||||
FLOAT, // float, double, long double
|
||||
STRING, // const char*, string_view
|
||||
POINTER // const void*
|
||||
};
|
||||
|
||||
// Map a type to its category. Decays and removes cv-qualifiers.
|
||||
template <class T>
|
||||
constexpr type_category get_type_category()
|
||||
{
|
||||
using U = typename etl::remove_cv<typename etl::remove_reference<T>::type>::type;
|
||||
|
||||
// Order matters: bool before integral, char before integral
|
||||
if (etl::is_same<U, bool>::value)
|
||||
return type_category::BOOLEAN;
|
||||
if (etl::is_same<U, char>::value)
|
||||
return type_category::CHAR;
|
||||
if (etl::is_same<U, signed char>::value)
|
||||
return type_category::CHAR;
|
||||
if (etl::is_same<U, unsigned char>::value)
|
||||
return type_category::CHAR;
|
||||
if (etl::is_integral<U>::value)
|
||||
return type_category::INTEGER;
|
||||
if (etl::is_same<U, float>::value)
|
||||
return type_category::FLOAT;
|
||||
if (etl::is_same<U, double>::value)
|
||||
return type_category::FLOAT;
|
||||
if (etl::is_same<U, long double>::value)
|
||||
return type_category::FLOAT;
|
||||
if (etl::is_same<U, const char*>::value)
|
||||
return type_category::STRING;
|
||||
if (etl::is_same<U, char*>::value)
|
||||
return type_category::STRING;
|
||||
if (etl::is_same<U, etl::string_view>::value)
|
||||
return type_category::STRING;
|
||||
if (etl::is_base_of<etl::istring, U>::value)
|
||||
return type_category::STRING;
|
||||
if (etl::is_pointer<U>::value)
|
||||
return type_category::POINTER;
|
||||
if (etl::is_same<U, const void*>::value)
|
||||
return type_category::POINTER;
|
||||
if (etl::is_same<U, void*>::value)
|
||||
return type_category::POINTER;
|
||||
return type_category::NONE; // unknown type: custom formatter, be permissive
|
||||
}
|
||||
|
||||
// Check if a format type character is valid for a given type category.
|
||||
// '\0' means no explicit type was specified (always valid — uses default presentation).
|
||||
inline constexpr bool ct_check_type_spec(type_category cat, char type_char)
|
||||
{
|
||||
if (type_char == '\0')
|
||||
{
|
||||
return true; // no explicit type: always OK, uses default
|
||||
}
|
||||
|
||||
switch (cat)
|
||||
{
|
||||
case type_category::BOOLEAN:
|
||||
// bool: s (as "true"/"false"), b, B, c, d, o, x, X (as integer 0/1)
|
||||
return type_char == 's' || type_char == 'b' || type_char == 'B' || type_char == 'c' || type_char == 'd' || type_char == 'o'
|
||||
|| type_char == 'x' || type_char == 'X';
|
||||
|
||||
case type_category::CHAR:
|
||||
// char: c (default), b, B, d, o, x, X (as integer), s, ?
|
||||
return type_char == 'c' || type_char == '?' || type_char == 'b' || type_char == 'B' || type_char == 'd' || type_char == 'o'
|
||||
|| type_char == 'x' || type_char == 'X' || type_char == 's';
|
||||
|
||||
case type_category::INTEGER:
|
||||
// integers: b, B, c, d, o, x, X
|
||||
return type_char == 'b' || type_char == 'B' || type_char == 'c' || type_char == 'd' || type_char == 'o' || type_char == 'x'
|
||||
|| type_char == 'X';
|
||||
|
||||
case type_category::FLOAT:
|
||||
// floats: a, A, e, E, f, F, g, G
|
||||
return type_char == 'a' || type_char == 'A' || type_char == 'e' || type_char == 'E' || type_char == 'f' || type_char == 'F'
|
||||
|| type_char == 'g' || type_char == 'G';
|
||||
|
||||
case type_category::STRING:
|
||||
// strings: s, ?
|
||||
return type_char == 's' || type_char == '?';
|
||||
|
||||
case type_category::POINTER:
|
||||
// pointers: p, P
|
||||
return type_char == 'p' || type_char == 'P';
|
||||
|
||||
case type_category::NONE:
|
||||
default: return true; // unknown/custom type: be permissive, let runtime handle it
|
||||
}
|
||||
}
|
||||
|
||||
inline constexpr bool ct_is_digit(char c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
// Parse an unsigned integer from fmt starting at pos. Updates pos past the digits.
|
||||
// Returns the parsed number, or -1 if no digits found, or -2 on overflow.
|
||||
inline constexpr int ct_parse_num(const char* fmt, int& pos)
|
||||
{
|
||||
if (!ct_is_digit(fmt[pos]))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int result = 0;
|
||||
while (ct_is_digit(fmt[pos]))
|
||||
{
|
||||
int new_result = result * 10 + (fmt[pos] - '0');
|
||||
if (new_result < result)
|
||||
{
|
||||
// Overflow detected
|
||||
return -2;
|
||||
}
|
||||
result = new_result;
|
||||
++pos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline constexpr bool ct_is_align(char c)
|
||||
{
|
||||
return c == '<' || c == '>' || c == '^';
|
||||
}
|
||||
|
||||
inline constexpr bool ct_is_sign(char c)
|
||||
{
|
||||
return c == '+' || c == '-' || c == ' ';
|
||||
}
|
||||
|
||||
inline constexpr bool ct_is_type(char c)
|
||||
{
|
||||
// All valid type characters from the format spec
|
||||
return (c == 's') || (c == '?') || (c == 'b') || (c == 'B') || (c == 'c') || (c == 'd') || (c == 'o') || (c == 'x') || (c == 'X') || (c == 'a')
|
||||
|| (c == 'A') || (c == 'e') || (c == 'E') || (c == 'f') || (c == 'F') || (c == 'g') || (c == 'G') || (c == 'p') || (c == 'P');
|
||||
}
|
||||
|
||||
// Validate a nested replacement field like {}, {0}, {1} inside width/precision.
|
||||
// pos should be at the '{'. Updates pos past the closing '}'.
|
||||
// Updates auto_count / has_manual / has_auto. Returns false on error.
|
||||
inline constexpr bool ct_parse_nested_replacement(const char* fmt, int& pos, int n_args, int& auto_count, bool& has_auto, bool& has_manual)
|
||||
{
|
||||
if (fmt[pos] != '{')
|
||||
return false;
|
||||
++pos; // skip '{'
|
||||
|
||||
int num = ct_parse_num(fmt, pos);
|
||||
if (num == -2)
|
||||
return false; // overflow
|
||||
if (num >= 0)
|
||||
{
|
||||
// manual index
|
||||
if (has_auto)
|
||||
return false; // mixing
|
||||
has_manual = true;
|
||||
if (num >= n_args)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// automatic index
|
||||
if (has_manual)
|
||||
return false; // mixing
|
||||
has_auto = true;
|
||||
if (auto_count >= n_args)
|
||||
return false;
|
||||
++auto_count;
|
||||
}
|
||||
|
||||
if (fmt[pos] != '}')
|
||||
return false;
|
||||
++pos; // skip '}'
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip/validate the format-spec portion after the colon:
|
||||
// [[fill]align][sign][#][0][width][.precision][L][type]
|
||||
// pos is right after ':'. Returns false on invalid spec.
|
||||
// parsed_type is set to the type character found, or '\0' if none.
|
||||
inline constexpr bool ct_skip_format_spec(const char* fmt, int& pos, int n_args, int& auto_count, bool& has_auto, bool& has_manual,
|
||||
char& parsed_type, bool& parsed_has_precision)
|
||||
{
|
||||
parsed_type = '\0';
|
||||
parsed_has_precision = false;
|
||||
|
||||
if (fmt[pos] == '\0' || fmt[pos] == '}')
|
||||
{
|
||||
return true; // empty spec is valid
|
||||
}
|
||||
|
||||
// fill-and-align: either [align] or [fill][align]
|
||||
// Look ahead: if second char is an align char, first is fill
|
||||
if (fmt[pos + 1] != '\0' && ct_is_align(fmt[pos + 1]))
|
||||
{
|
||||
char fill = fmt[pos];
|
||||
if (fill == '{' || fill == '}')
|
||||
return false; // { and } not allowed as fill
|
||||
pos += 2; // skip fill + align
|
||||
}
|
||||
else if (ct_is_align(fmt[pos]))
|
||||
{
|
||||
++pos; // skip align only
|
||||
}
|
||||
|
||||
// sign
|
||||
if (ct_is_sign(fmt[pos]))
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
|
||||
// '#'
|
||||
if (fmt[pos] == '#')
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
|
||||
// '0'
|
||||
if (fmt[pos] == '0')
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
|
||||
// width: number or nested replacement
|
||||
if (ct_is_digit(fmt[pos]))
|
||||
{
|
||||
if (ct_parse_num(fmt, pos) == -2)
|
||||
return false; // overflow
|
||||
}
|
||||
else if (fmt[pos] == '{')
|
||||
{
|
||||
if (!ct_parse_nested_replacement(fmt, pos, n_args, auto_count, has_auto, has_manual))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// precision: '.' followed by number or nested replacement
|
||||
bool has_precision = false;
|
||||
if (fmt[pos] == '.')
|
||||
{
|
||||
has_precision = true;
|
||||
++pos;
|
||||
if (ct_is_digit(fmt[pos]))
|
||||
{
|
||||
if (ct_parse_num(fmt, pos) == -2)
|
||||
return false; // overflow
|
||||
}
|
||||
else if (fmt[pos] == '{')
|
||||
{
|
||||
if (!ct_parse_nested_replacement(fmt, pos, n_args, auto_count, has_auto, has_manual))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// else: '.' with no precision number/replacement — still valid (empty precision)
|
||||
}
|
||||
|
||||
// locale-specific: 'L'
|
||||
if (fmt[pos] == 'L')
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
|
||||
// type
|
||||
if (ct_is_type(fmt[pos]))
|
||||
{
|
||||
parsed_type = fmt[pos];
|
||||
++pos;
|
||||
}
|
||||
|
||||
// After parsing the spec, we must be at '}' (the closing brace is consumed by the caller)
|
||||
// Any remaining characters before '}' means invalid spec
|
||||
if (fmt[pos] != '}')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
parsed_has_precision = has_precision;
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace private_format_check
|
||||
|
||||
template <class... Args>
|
||||
constexpr bool check_format(const char* fmt)
|
||||
{
|
||||
const int n_args = static_cast<int>(sizeof...(Args));
|
||||
int pos = 0;
|
||||
int auto_count = 0;
|
||||
bool has_auto = false;
|
||||
bool has_manual = false;
|
||||
|
||||
// Build a constexpr array mapping arg index -> type category
|
||||
const private_format_check::type_category arg_categories[] = {
|
||||
private_format_check::get_type_category<Args>()...,
|
||||
private_format_check::type_category::NONE // sentinel for zero-arg case
|
||||
};
|
||||
|
||||
while (fmt[pos] != '\0')
|
||||
{
|
||||
char c = fmt[pos];
|
||||
++pos;
|
||||
|
||||
if (c == '{')
|
||||
{
|
||||
if (fmt[pos] == '{')
|
||||
{
|
||||
// escaped '{'
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start of a replacement field: [arg_id][:format_spec]
|
||||
int resolved_index = -1;
|
||||
int arg_index = private_format_check::ct_parse_num(fmt, pos);
|
||||
if (arg_index == -2)
|
||||
return false; // overflow in arg index
|
||||
if (arg_index >= 0)
|
||||
{
|
||||
// manual index
|
||||
if (has_auto)
|
||||
return false; // mixing auto and manual
|
||||
has_manual = true;
|
||||
if (arg_index >= n_args)
|
||||
return false; // index out of range
|
||||
resolved_index = arg_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
// automatic index
|
||||
if (has_manual)
|
||||
return false; // mixing auto and manual
|
||||
has_auto = true;
|
||||
if (auto_count >= n_args)
|
||||
return false; // too many arguments
|
||||
resolved_index = auto_count;
|
||||
++auto_count;
|
||||
}
|
||||
|
||||
char type_char = '\0';
|
||||
bool has_precision = false;
|
||||
if (fmt[pos] == ':')
|
||||
{
|
||||
++pos; // skip ':'
|
||||
if (!private_format_check::ct_skip_format_spec(fmt, pos, n_args, auto_count, has_auto, has_manual, type_char, has_precision))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate type specifier against argument type
|
||||
if (resolved_index >= 0 && resolved_index < n_args)
|
||||
{
|
||||
if (!private_format_check::ct_check_type_spec(arg_categories[resolved_index], type_char))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Precision is not allowed for integer, boolean, or pointer types
|
||||
if (has_precision)
|
||||
{
|
||||
auto cat = arg_categories[resolved_index];
|
||||
if (cat == private_format_check::type_category::INTEGER || cat == private_format_check::type_category::BOOLEAN
|
||||
|| cat == private_format_check::type_category::POINTER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Precision is also invalid for char when presented as char (not as integer)
|
||||
if (cat == private_format_check::type_category::CHAR && (type_char == '\0' || type_char == 'c' || type_char == '?'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fmt[pos] != '}')
|
||||
{
|
||||
return false; // missing closing brace
|
||||
}
|
||||
++pos; // skip '}'
|
||||
}
|
||||
else if (c == '}')
|
||||
{
|
||||
if (fmt[pos] != '}')
|
||||
{
|
||||
return false; // unmatched '}'
|
||||
}
|
||||
++pos; // skip second '}'
|
||||
}
|
||||
}
|
||||
|
||||
(void)fmt;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void please_note_this_is_error_message_1() noexcept {}
|
||||
inline void please_note_this_is_error_message_format_string_syntax_error() noexcept {}
|
||||
#endif // ETL_USING_CPP20
|
||||
|
||||
template <class... Args>
|
||||
struct basic_format_string
|
||||
@ -94,20 +486,15 @@ namespace etl
|
||||
inline ETL_CONSTEVAL basic_format_string(const char* fmt)
|
||||
: _sv(fmt)
|
||||
{
|
||||
bool format_string_ok = check_f(fmt);
|
||||
|
||||
if (!format_string_ok)
|
||||
#if ETL_USING_CPP20
|
||||
// Compile-time validation: check_format runs at compile time via consteval.
|
||||
// In pre-C++20, runtime checks in vformat_to/parse_format_spec/etc. are sufficient.
|
||||
if (!check_format<Args...>(fmt))
|
||||
{
|
||||
// if (etl::is_constant_evaluated()) // compile time error path
|
||||
//{
|
||||
// // calling a non-constexpr function in a consteval context to
|
||||
// trigger a compile error please_note_this_is_error_message_1();
|
||||
// }
|
||||
// else // run time error path
|
||||
//{
|
||||
ETL_ASSERT_FAIL_AND_RETURN(ETL_ERROR(bad_format_string_exception));
|
||||
//}
|
||||
// Calling a non-constexpr function in a consteval context triggers a compile error.
|
||||
please_note_this_is_error_message_format_string_syntax_error();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ETL_CONSTEXPR basic_format_string(const basic_format_string& other) = default;
|
||||
@ -181,7 +568,6 @@ namespace etl
|
||||
// automatic number generation only allowed if not already in manual mode
|
||||
ETL_ASSERT(manual_mode == false, ETL_ERROR(bad_format_string_exception));
|
||||
automatic_mode = true;
|
||||
// TODO: compile time check
|
||||
ETL_ASSERT(current < num_args, ETL_ERROR(bad_format_string_exception) /* not enough arguments for generated index */);
|
||||
return current++;
|
||||
}
|
||||
@ -598,18 +984,6 @@ namespace etl
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool parse_sequence(format_parse_context& parse_ctx, etl::string_view sequence)
|
||||
{
|
||||
auto fmt_it = parse_ctx.begin();
|
||||
if (etl::equal(sequence.cbegin(), sequence.cend(), fmt_it))
|
||||
{
|
||||
fmt_it += sequence.size();
|
||||
parse_ctx.advance_to(fmt_it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_align_character(char c)
|
||||
{
|
||||
return c == '<' || c == '>' || c == '^';
|
||||
@ -1459,6 +1833,40 @@ namespace etl
|
||||
fmt_context.advance_to(tmp);
|
||||
}
|
||||
|
||||
// Compute prefix/suffix padding sizes for alignment.
|
||||
// default_align_start: if true, NONE defaults to left-align (START); otherwise right-align (END).
|
||||
inline void compute_padding(size_t pad, spec_align_t align, bool default_align_start, size_t& prefix_size, size_t& suffix_size)
|
||||
{
|
||||
switch (align)
|
||||
{
|
||||
case spec_align_t::START:
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
break;
|
||||
case spec_align_t::CENTER:
|
||||
prefix_size = pad / 2;
|
||||
suffix_size = pad - prefix_size;
|
||||
break;
|
||||
case spec_align_t::END:
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
break;
|
||||
case spec_align_t::NONE:
|
||||
default:
|
||||
if (default_align_start)
|
||||
{
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Int>
|
||||
typename format_context<OutputIt>::iterator format_aligned_int(Int arg, format_context<OutputIt>& fmt_ctx)
|
||||
{
|
||||
@ -1467,32 +1875,13 @@ namespace etl
|
||||
|
||||
if (fmt_ctx.format_spec.width)
|
||||
{
|
||||
// calculate size
|
||||
private_format::counter_iterator counter;
|
||||
private_format::format_num<private_format::counter_iterator, Int>(counter, arg, fmt_ctx.format_spec);
|
||||
|
||||
if (counter.value() < fmt_ctx.format_spec.width.value())
|
||||
{
|
||||
size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
|
||||
switch (fmt_ctx.format_spec.align)
|
||||
{
|
||||
case private_format::spec_align_t::START:
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
break;
|
||||
case private_format::spec_align_t::CENTER:
|
||||
prefix_size = pad / 2;
|
||||
suffix_size = pad - prefix_size;
|
||||
break;
|
||||
case private_format::spec_align_t::NONE: // default
|
||||
case private_format::spec_align_t::END:
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
break;
|
||||
default:
|
||||
// invalid alignment specification
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
|
||||
}
|
||||
compute_padding(pad, fmt_ctx.format_spec.align, false, prefix_size, suffix_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1513,32 +1902,13 @@ namespace etl
|
||||
|
||||
if (fmt_ctx.format_spec.width)
|
||||
{
|
||||
// calculate size
|
||||
private_format::counter_iterator counter;
|
||||
private_format::format_floating<private_format::counter_iterator, Float>(counter, arg, fmt_ctx.format_spec);
|
||||
|
||||
if (counter.value() < fmt_ctx.format_spec.width.value())
|
||||
{
|
||||
size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
|
||||
switch (fmt_ctx.format_spec.align)
|
||||
{
|
||||
case private_format::spec_align_t::START:
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
break;
|
||||
case private_format::spec_align_t::CENTER:
|
||||
prefix_size = pad / 2;
|
||||
suffix_size = pad - prefix_size;
|
||||
break;
|
||||
case private_format::spec_align_t::NONE: // default
|
||||
case private_format::spec_align_t::END:
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
break;
|
||||
default:
|
||||
// invalid alignment specification
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
|
||||
}
|
||||
compute_padding(pad, fmt_ctx.format_spec.align, false, prefix_size, suffix_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1609,32 +1979,13 @@ namespace etl
|
||||
|
||||
if (fmt_ctx.format_spec.width)
|
||||
{
|
||||
// calculate size
|
||||
private_format::counter_iterator counter;
|
||||
private_format::format_string_view<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
|
||||
|
||||
if (counter.value() < fmt_ctx.format_spec.width.value())
|
||||
{
|
||||
size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
|
||||
switch (fmt_ctx.format_spec.align)
|
||||
{
|
||||
case private_format::spec_align_t::NONE: // default
|
||||
case private_format::spec_align_t::START:
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
break;
|
||||
case private_format::spec_align_t::CENTER:
|
||||
prefix_size = pad / 2;
|
||||
suffix_size = pad - prefix_size;
|
||||
break;
|
||||
case private_format::spec_align_t::END:
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
break;
|
||||
default:
|
||||
// invalid alignment specification
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
|
||||
}
|
||||
compute_padding(pad, fmt_ctx.format_spec.align, true, prefix_size, suffix_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1646,99 +1997,10 @@ namespace etl
|
||||
return it;
|
||||
}
|
||||
|
||||
template <typename OutputIt>
|
||||
void format_chars(OutputIt& it, const char* arg, const format_spec_t& spec)
|
||||
{
|
||||
bool escaped = false;
|
||||
if (spec.type.has_value())
|
||||
{
|
||||
switch (spec.type.value())
|
||||
{
|
||||
case 's':
|
||||
// default output
|
||||
break;
|
||||
case '?':
|
||||
// escaped string
|
||||
escaped = true;
|
||||
break;
|
||||
default:
|
||||
// invalid type for string
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
|
||||
}
|
||||
}
|
||||
size_t limit = etl::numeric_limits<size_t>::max();
|
||||
if (spec.precision.has_value())
|
||||
{
|
||||
limit = spec.precision.value();
|
||||
}
|
||||
|
||||
if (escaped)
|
||||
{
|
||||
format_plain_char(it, '"');
|
||||
}
|
||||
const char_type* arg_it = arg;
|
||||
while (*arg_it != '\0' && limit > 0)
|
||||
{
|
||||
if (escaped)
|
||||
{
|
||||
format_escaped_char(it, *arg_it);
|
||||
}
|
||||
else
|
||||
{
|
||||
format_plain_char(it, *arg_it);
|
||||
}
|
||||
++arg_it;
|
||||
--limit;
|
||||
}
|
||||
if (escaped)
|
||||
{
|
||||
format_plain_char(it, '"');
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutputIt>
|
||||
typename format_context<OutputIt>::iterator format_aligned_chars(const char* arg, format_context<OutputIt>& fmt_ctx)
|
||||
{
|
||||
size_t prefix_size = 0;
|
||||
size_t suffix_size = 0;
|
||||
|
||||
if (fmt_ctx.format_spec.width)
|
||||
{
|
||||
// calculate size
|
||||
private_format::counter_iterator counter;
|
||||
private_format::format_chars<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
|
||||
|
||||
if (counter.value() < fmt_ctx.format_spec.width.value())
|
||||
{
|
||||
size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
|
||||
switch (fmt_ctx.format_spec.align)
|
||||
{
|
||||
case private_format::spec_align_t::NONE: // default
|
||||
case private_format::spec_align_t::START:
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
break;
|
||||
case private_format::spec_align_t::CENTER:
|
||||
prefix_size = pad / 2;
|
||||
suffix_size = pad - prefix_size;
|
||||
break;
|
||||
case private_format::spec_align_t::END:
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
break;
|
||||
default:
|
||||
// invalid alignment specification
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actual output
|
||||
OutputIt it = fmt_ctx.out();
|
||||
private_format::fill<OutputIt>(it, prefix_size, fmt_ctx.format_spec.fill);
|
||||
private_format::format_chars<OutputIt>(it, arg, fmt_ctx.format_spec);
|
||||
private_format::fill<OutputIt>(it, suffix_size, fmt_ctx.format_spec.fill);
|
||||
return it;
|
||||
return format_aligned_string_view<OutputIt>(etl::string_view(arg), fmt_ctx);
|
||||
}
|
||||
|
||||
inline void check_char_spec(const format_spec_t& spec)
|
||||
@ -1793,43 +2055,16 @@ namespace etl
|
||||
|
||||
if (fmt_ctx.format_spec.width)
|
||||
{
|
||||
// calculate size
|
||||
private_format::counter_iterator counter;
|
||||
private_format::format_char<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
|
||||
|
||||
if (counter.value() < fmt_ctx.format_spec.width.value())
|
||||
{
|
||||
size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
|
||||
switch (fmt_ctx.format_spec.align)
|
||||
{
|
||||
case private_format::spec_align_t::NONE: // default
|
||||
if (!fmt_ctx.format_spec.type.has_value() || fmt_ctx.format_spec.type.value() == 'c' || fmt_ctx.format_spec.type.value() == '?')
|
||||
{
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
}
|
||||
break;
|
||||
case private_format::spec_align_t::START:
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
break;
|
||||
case private_format::spec_align_t::CENTER:
|
||||
prefix_size = pad / 2;
|
||||
suffix_size = pad - prefix_size;
|
||||
break;
|
||||
case private_format::spec_align_t::END:
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
break;
|
||||
default:
|
||||
// invalid alignment specification
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
|
||||
}
|
||||
// char type defaults to left-align, integer presentation defaults to right-align
|
||||
bool default_start =
|
||||
!fmt_ctx.format_spec.type.has_value() || fmt_ctx.format_spec.type.value() == 'c' || fmt_ctx.format_spec.type.value() == '?';
|
||||
compute_padding(pad, fmt_ctx.format_spec.align, default_start, prefix_size, suffix_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1877,32 +2112,13 @@ namespace etl
|
||||
|
||||
if (fmt_ctx.format_spec.width)
|
||||
{
|
||||
// calculate size
|
||||
private_format::counter_iterator counter;
|
||||
private_format::format_bool<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
|
||||
|
||||
if (counter.value() < fmt_ctx.format_spec.width.value())
|
||||
{
|
||||
size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
|
||||
switch (fmt_ctx.format_spec.align)
|
||||
{
|
||||
case private_format::spec_align_t::START:
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
break;
|
||||
case private_format::spec_align_t::CENTER:
|
||||
prefix_size = pad / 2;
|
||||
suffix_size = pad - prefix_size;
|
||||
break;
|
||||
case private_format::spec_align_t::NONE: // default
|
||||
case private_format::spec_align_t::END:
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
break;
|
||||
default:
|
||||
// invalid alignment specification
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
|
||||
}
|
||||
compute_padding(pad, fmt_ctx.format_spec.align, false, prefix_size, suffix_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1946,32 +2162,13 @@ namespace etl
|
||||
|
||||
if (fmt_ctx.format_spec.width)
|
||||
{
|
||||
// calculate size
|
||||
private_format::counter_iterator counter;
|
||||
private_format::format_pointer<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
|
||||
|
||||
if (counter.value() < fmt_ctx.format_spec.width.value())
|
||||
{
|
||||
size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
|
||||
switch (fmt_ctx.format_spec.align)
|
||||
{
|
||||
case private_format::spec_align_t::START:
|
||||
prefix_size = 0;
|
||||
suffix_size = pad;
|
||||
break;
|
||||
case private_format::spec_align_t::CENTER:
|
||||
prefix_size = pad / 2;
|
||||
suffix_size = pad - prefix_size;
|
||||
break;
|
||||
case private_format::spec_align_t::NONE: // default
|
||||
case private_format::spec_align_t::END:
|
||||
prefix_size = pad;
|
||||
suffix_size = 0;
|
||||
break;
|
||||
default:
|
||||
// invalid alignment specification
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
|
||||
}
|
||||
compute_padding(pad, fmt_ctx.format_spec.align, false, prefix_size, suffix_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -116,15 +116,15 @@ namespace etl
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Unsorted exception for the list.
|
||||
///\ingroup list
|
||||
/// Unsorted exception for the forward_list.
|
||||
///\ingroup forward_list
|
||||
//***************************************************************************
|
||||
class forward_list_no_pool : public forward_list_exception
|
||||
{
|
||||
public:
|
||||
|
||||
forward_list_no_pool(string_type file_name_, numeric_type line_number_)
|
||||
: forward_list_exception(ETL_ERROR_TEXT("list:no pool", ETL_FORWARD_LIST_FILE_ID"D"), file_name_, line_number_)
|
||||
: forward_list_exception(ETL_ERROR_TEXT("forward_list:no pool", ETL_FORWARD_LIST_FILE_ID"D"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@ -36,7 +36,6 @@ SOFTWARE.
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -479,7 +479,7 @@ namespace etl
|
||||
//*********************************
|
||||
const_iterator end() const
|
||||
{
|
||||
return accumulator.begin();
|
||||
return accumulator.end();
|
||||
}
|
||||
|
||||
//*********************************
|
||||
@ -487,7 +487,7 @@ namespace etl
|
||||
//*********************************
|
||||
const_iterator cend() const
|
||||
{
|
||||
return accumulator.cbegin();
|
||||
return accumulator.cend();
|
||||
}
|
||||
|
||||
//*********************************
|
||||
|
||||
@ -36,8 +36,6 @@ SOFTWARE.
|
||||
#include "exception.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
///\defgroup ihash Common data for all hash type classes.
|
||||
///\ingroup hash
|
||||
|
||||
|
||||
@ -31,7 +31,8 @@ SOFTWARE.
|
||||
|
||||
#include "platform.h"
|
||||
#include "integral_limits.h"
|
||||
#include "static_assert.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -35,7 +35,6 @@ SOFTWARE.
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "private/minmax_push.h"
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ SOFTWARE.
|
||||
#include "type_traits.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
//*****************************************************************************
|
||||
// Note:
|
||||
@ -890,7 +890,10 @@ namespace etl
|
||||
template <typename TLink>
|
||||
typename etl::enable_if< etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type link_clear_range(TLink* start)
|
||||
{
|
||||
etl::link_clear_range(*start);
|
||||
if (start != ETL_NULLPTR)
|
||||
{
|
||||
etl::link_clear_range(*start);
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
|
||||
@ -35,8 +35,6 @@ SOFTWARE.
|
||||
#include "functional.h"
|
||||
#include "limits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
|
||||
@ -37,9 +37,10 @@ SOFTWARE.
|
||||
#include "iterator.h"
|
||||
#include "memory.h"
|
||||
#include "placement_new.h"
|
||||
#include "static_assert.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define ETL_POOL_CPP03_CODE 0
|
||||
|
||||
namespace etl
|
||||
|
||||
@ -36,7 +36,6 @@ SOFTWARE.
|
||||
#include "frame_check_sequence.h"
|
||||
#include "ihash.h"
|
||||
#include "iterator.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@ -36,8 +36,6 @@ SOFTWARE.
|
||||
#include "functional.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
namespace private_limiter
|
||||
|
||||
@ -43,7 +43,6 @@ SOFTWARE.
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "private/minmax_push.h"
|
||||
|
||||
|
||||
@ -42,7 +42,6 @@ SOFTWARE.
|
||||
|
||||
#include "private/addressof.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(ETL_IN_UNIT_TEST) || ETL_USING_STL
|
||||
@ -795,12 +794,8 @@ namespace etl
|
||||
template <typename TInputIterator, typename TSize, typename TOutputIterator>
|
||||
TOutputIterator uninitialized_move_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin)
|
||||
{
|
||||
// Move not supported. Defer to copy.
|
||||
#if ETL_USING_CPP11
|
||||
return std::uninitialized_copy_n(i_begin, n, o_begin);
|
||||
#else
|
||||
// Move not supported. Defer to copy.
|
||||
return etl::uninitialized_copy_n(i_begin, n, o_begin);
|
||||
#endif
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
@ -814,12 +809,8 @@ namespace etl
|
||||
{
|
||||
count += TCounter(n);
|
||||
|
||||
// Move not supported. Defer to copy.
|
||||
#if ETL_USING_CPP11
|
||||
return std::uninitialized_copy_n(i_begin, n, o_begin);
|
||||
#else
|
||||
// Move not supported. Defer to copy.
|
||||
return etl::uninitialized_copy_n(i_begin, n, o_begin);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2643,6 +2634,14 @@ namespace etl
|
||||
{
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
// Prevent the compiler from optimising away the volatile stores
|
||||
// as dead stores (observed with GCC -O3 in C++23 mode).
|
||||
#if defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_CLANG)
|
||||
__asm__ __volatile__("" : : : "memory");
|
||||
#elif defined(ETL_COMPILER_MICROSOFT)
|
||||
_ReadWriteBarrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
@ -36,8 +36,6 @@ SOFTWARE.
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
|
||||
@ -36,8 +36,6 @@ SOFTWARE.
|
||||
#include "nullptr.h"
|
||||
#include "span.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
|
||||
@ -36,10 +36,9 @@ SOFTWARE.
|
||||
#include "message.h"
|
||||
#include "message_router.h"
|
||||
#include "message_types.h"
|
||||
#include "nullptr.h"
|
||||
#include "vector.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -39,8 +39,6 @@ SOFTWARE.
|
||||
#include "type_list.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION)
|
||||
|
||||
@ -38,14 +38,12 @@ SOFTWARE.
|
||||
#include "message.h"
|
||||
#include "message_packet.h"
|
||||
#include "message_types.h"
|
||||
#include "nullptr.h"
|
||||
#include "placement_new.h"
|
||||
#include "shared_message.h"
|
||||
#include "successor.h"
|
||||
#include "type_list.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -38,7 +38,7 @@ SOFTWARE.
|
||||
#include "memory.h"
|
||||
#include "message_router.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -157,7 +157,6 @@ namespace etl
|
||||
list(etl::message_timer_data* ptimers_)
|
||||
: head(etl::timer::id::NO_TIMER)
|
||||
, tail(etl::timer::id::NO_TIMER)
|
||||
, current(etl::timer::id::NO_TIMER)
|
||||
, ptimers(ptimers_)
|
||||
{
|
||||
}
|
||||
@ -286,22 +285,13 @@ namespace etl
|
||||
//*******************************
|
||||
etl::timer::id::type begin()
|
||||
{
|
||||
current = head;
|
||||
return current;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type previous(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].previous;
|
||||
return current;
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type next(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].next;
|
||||
return current;
|
||||
return ptimers[last].next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
@ -316,16 +306,14 @@ namespace etl
|
||||
timer.next = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
current = etl::timer::id::NO_TIMER;
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
etl::timer::id::type head;
|
||||
etl::timer::id::type tail;
|
||||
etl::timer::id::type current;
|
||||
|
||||
etl::message_timer_data* const ptimers;
|
||||
};
|
||||
|
||||
@ -466,7 +466,6 @@ namespace etl
|
||||
timer_list(timer_data* ptimers_)
|
||||
: head(etl::timer::id::NO_TIMER)
|
||||
, tail(etl::timer::id::NO_TIMER)
|
||||
, current(etl::timer::id::NO_TIMER)
|
||||
, ptimers(ptimers_)
|
||||
{
|
||||
}
|
||||
@ -595,22 +594,13 @@ namespace etl
|
||||
//*******************************
|
||||
etl::timer::id::type begin()
|
||||
{
|
||||
current = head;
|
||||
return current;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type previous(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].previous;
|
||||
return current;
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type next(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].next;
|
||||
return current;
|
||||
return ptimers[last].next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
@ -625,16 +615,14 @@ namespace etl
|
||||
timer.next = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
current = etl::timer::id::NO_TIMER;
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
etl::timer::id::type head;
|
||||
etl::timer::id::type tail;
|
||||
etl::timer::id::type current;
|
||||
|
||||
timer_data* const ptimers;
|
||||
};
|
||||
|
||||
@ -472,7 +472,6 @@ namespace etl
|
||||
timer_list(timer_data* ptimers_)
|
||||
: head(etl::timer::id::NO_TIMER)
|
||||
, tail(etl::timer::id::NO_TIMER)
|
||||
, current(etl::timer::id::NO_TIMER)
|
||||
, ptimers(ptimers_)
|
||||
{
|
||||
}
|
||||
@ -601,22 +600,13 @@ namespace etl
|
||||
//*******************************
|
||||
etl::timer::id::type begin()
|
||||
{
|
||||
current = head;
|
||||
return current;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type previous(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].previous;
|
||||
return current;
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type next(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].next;
|
||||
return current;
|
||||
return ptimers[last].next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
@ -631,16 +621,14 @@ namespace etl
|
||||
timer.next = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
current = etl::timer::id::NO_TIMER;
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
etl::timer::id::type head;
|
||||
etl::timer::id::type tail;
|
||||
etl::timer::id::type current;
|
||||
|
||||
timer_data* const ptimers;
|
||||
};
|
||||
|
||||
@ -480,7 +480,6 @@ namespace etl
|
||||
timer_list(timer_data* ptimers_)
|
||||
: head(etl::timer::id::NO_TIMER)
|
||||
, tail(etl::timer::id::NO_TIMER)
|
||||
, current(etl::timer::id::NO_TIMER)
|
||||
, ptimers(ptimers_)
|
||||
{
|
||||
}
|
||||
@ -609,22 +608,13 @@ namespace etl
|
||||
//*******************************
|
||||
etl::timer::id::type begin()
|
||||
{
|
||||
current = head;
|
||||
return current;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type previous(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].previous;
|
||||
return current;
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type next(etl::timer::id::type last)
|
||||
{
|
||||
current = ptimers[last].next;
|
||||
return current;
|
||||
return ptimers[last].next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
@ -639,16 +629,14 @@ namespace etl
|
||||
timer.next = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
current = etl::timer::id::NO_TIMER;
|
||||
head = etl::timer::id::NO_TIMER;
|
||||
tail = etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
etl::timer::id::type head;
|
||||
etl::timer::id::type tail;
|
||||
etl::timer::id::type current;
|
||||
|
||||
timer_data* const ptimers;
|
||||
};
|
||||
|
||||
@ -35,7 +35,6 @@ SOFTWARE.
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "memory.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
namespace etl
|
||||
|
||||
@ -32,7 +32,7 @@ SOFTWARE.
|
||||
#include "platform.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
namespace etl
|
||||
|
||||
@ -566,6 +566,14 @@ namespace etl
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT
|
||||
{
|
||||
// GCC's UBSan instruments function pointer comparisons, which prevents
|
||||
// constexpr evaluation. Use implicit bool conversion at compile time
|
||||
// to avoid the instrumented != comparison while still checking validity.
|
||||
if (etl::is_constant_evaluated())
|
||||
{
|
||||
return static_cast<bool>(invocation.stub);
|
||||
}
|
||||
|
||||
return invocation.stub != ETL_NULLPTR;
|
||||
}
|
||||
|
||||
|
||||
@ -35,8 +35,9 @@ SOFTWARE.
|
||||
#include "functional.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
////#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -44,7 +44,6 @@ SOFTWARE.
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//*****************************************************************************
|
||||
///\defgroup queue queue
|
||||
|
||||
@ -32,7 +32,6 @@ SOFTWARE.
|
||||
#define ETL_QUEUE_LOCKABLE_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "function.h"
|
||||
#include "integral_limits.h"
|
||||
#include "memory.h"
|
||||
#include "memory_model.h"
|
||||
@ -42,7 +41,6 @@ SOFTWARE.
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -41,7 +41,6 @@ SOFTWARE.
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if ETL_HAS_ATOMIC
|
||||
|
||||
|
||||
@ -41,7 +41,6 @@ SOFTWARE.
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -42,7 +42,6 @@ SOFTWARE.
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -3639,20 +3639,6 @@ namespace etl
|
||||
template <class... Ranges>
|
||||
concat_view(Ranges&&...) -> concat_view<views::all_t<Ranges>...>;
|
||||
|
||||
struct concat_range_adapter_closure : public range_adapter_closure<concat_range_adapter_closure>
|
||||
{
|
||||
template <typename... Ranges>
|
||||
using target_view_type = concat_view<Ranges...>;
|
||||
|
||||
constexpr concat_range_adapter_closure() = default;
|
||||
|
||||
template <typename... Ranges>
|
||||
constexpr auto operator()(Ranges&&... r) const
|
||||
{
|
||||
return concat_view(views::all(etl::forward<Ranges>(r))...);
|
||||
}
|
||||
};
|
||||
|
||||
namespace views
|
||||
{
|
||||
namespace private_views
|
||||
|
||||
@ -37,7 +37,6 @@ SOFTWARE.
|
||||
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
///\defgroup ratio ratio
|
||||
|
||||
@ -37,7 +37,6 @@ SOFTWARE.
|
||||
#include "type_traits.h"
|
||||
|
||||
// #include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -33,7 +33,6 @@ SOFTWARE.
|
||||
|
||||
#include "platform.h"
|
||||
#include "absolute.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
namespace etl
|
||||
|
||||
@ -44,7 +44,6 @@ SOFTWARE.
|
||||
#include "utility.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//*****************************************************************************
|
||||
///\defgroup stack stack
|
||||
|
||||
@ -39,7 +39,7 @@ SOFTWARE.
|
||||
#include "optional.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "private/minmax_push.h"
|
||||
|
||||
|
||||
@ -589,9 +589,9 @@ namespace etl
|
||||
return npos;
|
||||
}
|
||||
|
||||
position = etl::min(position, size());
|
||||
position = etl::min(position, size() - view.size());
|
||||
|
||||
const_iterator iposition = etl::find_end(begin(), begin() + position, view.begin(), view.end());
|
||||
const_iterator iposition = etl::find_end(begin(), begin() + position + view.size(), view.begin(), view.end());
|
||||
|
||||
if (iposition == end())
|
||||
{
|
||||
|
||||
@ -36,7 +36,6 @@ SOFTWARE.
|
||||
#include "type_traits.h"
|
||||
|
||||
// #include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -32,10 +32,10 @@ SOFTWARE.
|
||||
#include "platform.h"
|
||||
#include "integral_limits.h"
|
||||
#include "null_type.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
|
||||
@ -31,8 +31,10 @@ SOFTWARE.
|
||||
|
||||
#include "platform.h"
|
||||
#include "null_type.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
#if ETL_USING_CPP11 && !defined(ETL_TYPE_SELECT_FORCE_CPP03_IMPLEMENTATION)
|
||||
|
||||
@ -499,19 +499,19 @@ namespace etl
|
||||
};
|
||||
#if ETL_HAS_NATIVE_CHAR8_T
|
||||
template <>
|
||||
struct is_signed<char8_t> : true_type
|
||||
struct is_signed<char8_t> : false_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
#if ETL_HAS_NATIVE_CHAR16_T
|
||||
template <>
|
||||
struct is_signed<char16_t> : true_type
|
||||
struct is_signed<char16_t> : false_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
#if ETL_HAS_NATIVE_CHAR32_T
|
||||
template <>
|
||||
struct is_signed<char32_t> : true_type
|
||||
struct is_signed<char32_t> : false_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
@ -569,6 +569,24 @@ namespace etl
|
||||
struct is_unsigned<unsigned long long> : true_type
|
||||
{
|
||||
};
|
||||
#if ETL_HAS_NATIVE_CHAR8_T
|
||||
template <>
|
||||
struct is_unsigned<char8_t> : true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
#if ETL_HAS_NATIVE_CHAR16_T
|
||||
template <>
|
||||
struct is_unsigned<char16_t> : true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
#if ETL_HAS_NATIVE_CHAR32_T
|
||||
template <>
|
||||
struct is_unsigned<char32_t> : true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
template <typename T>
|
||||
struct is_unsigned<const T> : is_unsigned<T>
|
||||
{
|
||||
|
||||
@ -43,7 +43,6 @@ SOFTWARE.
|
||||
#include "intrusive_forward_list.h"
|
||||
#include "iterator.h"
|
||||
#include "nth_type.h"
|
||||
#include "nullptr.h"
|
||||
#include "parameter_type.h"
|
||||
#include "placement_new.h"
|
||||
#include "pool.h"
|
||||
|
||||
@ -42,7 +42,6 @@ SOFTWARE.
|
||||
#include "intrusive_forward_list.h"
|
||||
#include "iterator.h"
|
||||
#include "nth_type.h"
|
||||
#include "nullptr.h"
|
||||
#include "parameter_type.h"
|
||||
#include "placement_new.h"
|
||||
#include "pool.h"
|
||||
|
||||
@ -42,7 +42,6 @@ SOFTWARE.
|
||||
#include "intrusive_forward_list.h"
|
||||
#include "iterator.h"
|
||||
#include "nth_type.h"
|
||||
#include "nullptr.h"
|
||||
#include "parameter_type.h"
|
||||
#include "placement_new.h"
|
||||
#include "pool.h"
|
||||
|
||||
@ -42,7 +42,6 @@ SOFTWARE.
|
||||
#include "intrusive_forward_list.h"
|
||||
#include "iterator.h"
|
||||
#include "nth_type.h"
|
||||
#include "nullptr.h"
|
||||
#include "parameter_type.h"
|
||||
#include "placement_new.h"
|
||||
#include "pool.h"
|
||||
|
||||
@ -377,7 +377,7 @@ namespace etl
|
||||
inline bool operator==(const pair<T1, T2>& a, const pair<T1, T2>& b)
|
||||
{
|
||||
#include "private/diagnostic_float_equal_push.h"
|
||||
return (a.first == b.first) && !(a.second < b.second) && !(a.second > b.second);
|
||||
return (a.first == b.first) && (a.second == b.second);
|
||||
#include "private/diagnostic_pop.h"
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ SOFTWARE.
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -40,7 +40,6 @@ SOFTWARE.
|
||||
#include "debug_count.h"
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "functional.h"
|
||||
#include "initializer_list.h"
|
||||
#include "iterator.h"
|
||||
#include "memory.h"
|
||||
@ -1125,17 +1124,6 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
//*********************************************************************
|
||||
/// Create a new element with a default value at the back.
|
||||
//*********************************************************************
|
||||
void create_back()
|
||||
{
|
||||
etl::create_value_at(p_end);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
++p_end;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Create a new element with a value at the back
|
||||
//*********************************************************************
|
||||
|
||||
@ -1 +1,2 @@
|
||||
option('use_stl', description: 'Compiling for STL', type: 'boolean', value: true)
|
||||
option('enable_sanitizer', description: 'Enable address and undefined behavior sanitizers', type: 'boolean', value: false)
|
||||
|
||||
162
test/meson.build
162
test/meson.build
@ -1,4 +1,3 @@
|
||||
|
||||
etl_test_sources = files(
|
||||
'main.cpp',
|
||||
'murmurhash3.cpp',
|
||||
@ -8,48 +7,91 @@ etl_test_sources = files(
|
||||
'test_array_view.cpp',
|
||||
'test_array_wrapper.cpp',
|
||||
'test_atomic.cpp',
|
||||
'test_base64_RFC2152_decoder.cppp',
|
||||
'test_base64_RFC2152_encoder.cppp',
|
||||
'test_base64_RFC3501_decoder.cppp',
|
||||
'test_base64_RFC3501_encoder.cppp',
|
||||
'test_base64_RFC4648_decoder_with_no_padding.cppp',
|
||||
'test_base64_RFC4648_decoder_with_padding.cppp',
|
||||
'test_base64_RFC4648_encoder_with_no_padding.cppp',
|
||||
'test_base64_RFC4648_encoder_with_padding.cppp',
|
||||
'test_base64_RFC4648_URL_decoder_with_no_padding.cppp',
|
||||
'test_base64_RFC4648_URL_decoder_with_padding.cppp',
|
||||
'test_base64_RFC4648_URL_encoder_with_no_padding.cppp',
|
||||
'test_base64_RFC2152_decoder.cpp',
|
||||
'test_base64_RFC2152_encoder.cpp',
|
||||
'test_base64_RFC3501_decoder.cpp',
|
||||
'test_base64_RFC3501_encoder.cpp',
|
||||
'test_base64_RFC4648_URL_decoder_with_no_padding.cpp',
|
||||
'test_base64_RFC4648_URL_decoder_with_padding.cpp',
|
||||
'test_base64_RFC4648_URL_encoder_with_no_padding.cpp',
|
||||
'test_base64_RFC4648_URL_encoder_with_padding.cpp',
|
||||
'test_base64_RFC4648_decoder_with_no_padding.cpp',
|
||||
'test_base64_RFC4648_decoder_with_padding.cpp',
|
||||
'test_base64_RFC4648_encoder_with_no_padding.cpp',
|
||||
'test_base64_RFC4648_encoder_with_padding.cpp',
|
||||
'test_binary.cpp',
|
||||
'test_bip_buffer_spsc_atomic.cpp',
|
||||
'test_bit.cpp',
|
||||
'test_bitset_legacy.cpp',
|
||||
'test_bitset_new_default_element_type.cpp',
|
||||
'test_bitset_new_explicit_single_element_type.cpp',
|
||||
'test_bitset_new_ext_default_element_type.cpp',
|
||||
'test_bitset_new_ext_explicit_single_element_type.cpp',
|
||||
'test_bit_stream.cpp',
|
||||
'test_bit_stream_reader_big_endian.cpp',
|
||||
'test_bit_stream_reader_little_endian.cpp',
|
||||
'test_bit_stream_writer_big_endian.cpp',
|
||||
'test_bit_stream_writer_little_endian.cpp',
|
||||
'test_byte.cpp',
|
||||
'test_byte_stream.cpp',
|
||||
'test_bitset_legacy.cpp',
|
||||
'test_bitset_new_comparisons.cpp',
|
||||
'test_bitset_new_default_element_type.cpp',
|
||||
'test_bitset_new_explicit_single_element_type.cpp',
|
||||
'test_bitset_new_ext_default_element_type.cpp',
|
||||
'test_bitset_new_ext_explicit_single_element_type.cpp',
|
||||
'test_bloom_filter.cpp',
|
||||
'test_bresenham_line.cpp',
|
||||
'test_bsd_checksum.cpp',
|
||||
'test_buffer_descriptors.cpp',
|
||||
'test_byte.cpp',
|
||||
'test_byte_stream.cpp',
|
||||
'test_callback_service.cpp',
|
||||
'test_callback_timer.cpp',
|
||||
'test_callback_timer_atomic.cpp',
|
||||
'test_callback_timer_deferred_locked.cpp',
|
||||
'test_callback_timer_interrupt.cpp',
|
||||
'test_callback_timer_locked.cpp',
|
||||
'test_char_traits.cpp',
|
||||
'test_checksum.cpp',
|
||||
'test_chrono_clocks.cpp',
|
||||
'test_chrono_day.cpp',
|
||||
'test_chrono_duration.cpp',
|
||||
'test_chrono_hh_mm_ss.cpp',
|
||||
'test_chrono_literals.cpp',
|
||||
'test_chrono_month.cpp',
|
||||
'test_chrono_month_day.cpp',
|
||||
'test_chrono_month_day_last.cpp',
|
||||
'test_chrono_month_weekday.cpp',
|
||||
'test_chrono_month_weekday_last.cpp',
|
||||
'test_chrono_operators.cpp',
|
||||
'test_chrono_time_point.cpp',
|
||||
'test_chrono_weekday.cpp',
|
||||
'test_chrono_weekday_indexed.cpp',
|
||||
'test_chrono_weekday_last.cpp',
|
||||
'test_chrono_year.cpp',
|
||||
'test_chrono_year_month.cpp',
|
||||
'test_chrono_year_month_day.cpp',
|
||||
'test_chrono_year_month_day_last.cpp',
|
||||
'test_chrono_year_month_weekday.cpp',
|
||||
'test_chrono_year_month_weekday_last.cpp',
|
||||
'test_circular_buffer.cpp',
|
||||
'test_circular_buffer_external_buffer.cpp',
|
||||
'test_circular_iterator.cpp',
|
||||
'test_closure_with_default_delegate.cpp',
|
||||
'test_closure_with_default_delegate_constexpr.cpp',
|
||||
'test_closure_with_inplace_function.cpp',
|
||||
'test_compare.cpp',
|
||||
'test_compiler_settings.cpp',
|
||||
'test_concepts.cpp',
|
||||
'test_const_map.cpp',
|
||||
'test_const_map_constexpr.cpp',
|
||||
'test_const_map_ext.cpp',
|
||||
'test_const_map_ext_constexpr.cpp',
|
||||
'test_const_multimap.cpp',
|
||||
'test_const_multimap_constexpr.cpp',
|
||||
'test_const_multimap_ext.cpp',
|
||||
'test_const_multimap_ext_constexpr.cpp',
|
||||
'test_const_multiset.cpp',
|
||||
'test_const_multiset_constexpr.cpp',
|
||||
'test_const_multiset_ext.cpp',
|
||||
'test_const_multiset_ext_constexpr.cpp',
|
||||
'test_const_set.cpp',
|
||||
'test_const_set_constexpr.cpp',
|
||||
'test_const_set_ext.cpp',
|
||||
'test_const_set_ext_constexpr.cpp',
|
||||
'test_constant.cpp',
|
||||
'test_container.cpp',
|
||||
'test_correlation.cpp',
|
||||
@ -69,9 +111,12 @@ etl_test_sources = files(
|
||||
'test_crc16_en13757.cpp',
|
||||
'test_crc16_genibus.cpp',
|
||||
'test_crc16_kermit.cpp',
|
||||
'test_crc16_m17.cpp',
|
||||
'test_crc16_maxim.cpp',
|
||||
'test_crc16_mcrf4xx.cpp',
|
||||
'test_crc16_modbus.cpp',
|
||||
'test_crc16_opensafety_a.cpp',
|
||||
'test_crc16_opensafety_b.cpp',
|
||||
'test_crc16_profibus.cpp',
|
||||
'test_crc16_riello.cpp',
|
||||
'test_crc16_t10dif.cpp',
|
||||
@ -90,6 +135,7 @@ etl_test_sources = files(
|
||||
'test_crc32_q.cpp',
|
||||
'test_crc32_xfer.cpp',
|
||||
'test_crc64_ecma.cpp',
|
||||
'test_crc64_iso.cpp',
|
||||
'test_crc8_ccitt.cpp',
|
||||
'test_crc8_cdma2000.cpp',
|
||||
'test_crc8_darc.cpp',
|
||||
@ -97,21 +143,29 @@ etl_test_sources = files(
|
||||
'test_crc8_ebu.cpp',
|
||||
'test_crc8_icode.cpp',
|
||||
'test_crc8_itu.cpp',
|
||||
'test_crc8_j1850.cpp',
|
||||
'test_crc8_j1850_zero.cpp',
|
||||
'test_crc8_maxim.cpp',
|
||||
'test_crc8_nrsc5.cpp',
|
||||
'test_crc8_opensafety.cpp',
|
||||
'test_crc8_rohc.cpp',
|
||||
'test_crc8_wcdma.cpp',
|
||||
'test_cyclic_value.cpp',
|
||||
'test_debounce.cpp',
|
||||
'test_delegate.cpp',
|
||||
'test_delegate_cpp03.cpp',
|
||||
'test_delegate_observable.cpp',
|
||||
'test_delegate_service.cpp',
|
||||
'test_delegate_service_compile_time.cpp',
|
||||
'test_delegate_service_cpp03.cpp',
|
||||
'test_deque.cpp',
|
||||
'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',
|
||||
'test_fixed_iterator.cpp',
|
||||
'test_fixed_sized_memory_block_allocator.cpp',
|
||||
'test_flags.cpp',
|
||||
@ -120,18 +174,24 @@ etl_test_sources = files(
|
||||
'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',
|
||||
'test_fsm.cpp',
|
||||
'test_function.cpp',
|
||||
'test_function_traits.cpp',
|
||||
'test_functional.cpp',
|
||||
'test_gamma.cpp',
|
||||
'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',
|
||||
@ -140,7 +200,9 @@ etl_test_sources = files(
|
||||
'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',
|
||||
@ -148,14 +210,17 @@ etl_test_sources = files(
|
||||
'test_limits.cpp',
|
||||
'test_list.cpp',
|
||||
'test_list_shared_pool.cpp',
|
||||
'test_macros.cpp',
|
||||
'test_make_string.cpp',
|
||||
'test_manchester.cpp',
|
||||
'test_map.cpp',
|
||||
'test_math.cpp',
|
||||
'test_math_functions.cpp',
|
||||
'test_mean.cpp',
|
||||
'test_mem_cast.cpp',
|
||||
'test_mem_cast_ptr.cpp',
|
||||
'test_memory.cpp',
|
||||
'test_memory.cpp',
|
||||
'test_message.cpp',
|
||||
'test_message_broker.cpp',
|
||||
'test_message_bus.cpp',
|
||||
'test_message_packet.cpp',
|
||||
@ -163,18 +228,23 @@ etl_test_sources = files(
|
||||
'test_message_router_registry.cpp',
|
||||
'test_message_timer.cpp',
|
||||
'test_message_timer_atomic.cpp',
|
||||
'test_message_timer_interrupt.cpp',
|
||||
'test_message_timer_interrupt.cpp',
|
||||
'test_message_timer_locked.cpp',
|
||||
'test_multimap.cpp',
|
||||
'test_multiset.cpp',
|
||||
'test_multi_array.cpp',
|
||||
'test_multi_range.cpp',
|
||||
'test_multi_span.cpp',
|
||||
'test_multi_vector.cpp',
|
||||
'test_multimap.cpp',
|
||||
'test_multiset.cpp',
|
||||
'test_murmur3.cpp',
|
||||
'test_not_null_pointer.cpp',
|
||||
'test_not_null_pointer_constexpr.cpp',
|
||||
'test_not_null_unique_pointer.cpp',
|
||||
'test_nth_type.cpp',
|
||||
'test_numeric.cpp',
|
||||
'test_observer.cpp',
|
||||
'test_optional.cpp',
|
||||
'test_overload.cpp',
|
||||
'test_packet.cpp',
|
||||
'test_parameter_pack.cpp',
|
||||
'test_parameter_type.cpp',
|
||||
@ -184,6 +254,7 @@ etl_test_sources = files(
|
||||
'test_poly_span_fixed_extent.cpp',
|
||||
'test_pool.cpp',
|
||||
'test_pool_external_buffer.cpp',
|
||||
'test_print.cpp',
|
||||
'test_priority_queue.cpp',
|
||||
'test_pseudo_moving_average.cpp',
|
||||
'test_quantize.cpp',
|
||||
@ -200,45 +271,54 @@ etl_test_sources = files(
|
||||
'test_queue_spsc_locked.cpp',
|
||||
'test_queue_spsc_locked_small.cpp',
|
||||
'test_random.cpp',
|
||||
'test_ranges.cpp',
|
||||
'test_ratio.cpp',
|
||||
'test_reference_flat_map.cpp',
|
||||
'test_reference_flat_multimap.cpp',
|
||||
'test_reference_flat_multiset.cpp',
|
||||
'test_reference_flat_set.cpp',
|
||||
'test_rescale.cpp',
|
||||
'test_result.cpp',
|
||||
'test_rms.cpp',
|
||||
'test_rounded_integral_division.cpp',
|
||||
'test_scaled_rounding.cpp',
|
||||
'test_set.cpp',
|
||||
'test_shared_message.cpp',
|
||||
'test_signal.cpp',
|
||||
'test_singleton.cpp',
|
||||
'test_singleton_base.cpp',
|
||||
'test_smallest.cpp',
|
||||
'test_span_dynamic_extent.cpp',
|
||||
'test_span_fixed_extent.cpp',
|
||||
'test_stack.cpp',
|
||||
'test_standard_deviation.cpp',
|
||||
'test_state_chart.cpp',
|
||||
'test_state_chart_with_data_parameter.cpp',
|
||||
'test_state_chart_with_rvalue_data_parameter.cpp',
|
||||
'test_state_chart_compile_time.cpp',
|
||||
'test_state_chart_compile_time_with_data_parameter.cpp',
|
||||
'test_state_chart_with_data_parameter.cpp',
|
||||
'test_state_chart_with_rvalue_data_parameter.cpp',
|
||||
'test_string_char.cpp',
|
||||
'test_string_char_external_buffer.cpp',
|
||||
'test_string_stream.cpp',
|
||||
'test_string_u8.cpp',
|
||||
'test_string_u8_external_buffer.cpp',
|
||||
'test_string_stream_u16.cpp',
|
||||
'test_string_stream_u32.cpp',
|
||||
'test_string_stream_u8.cpp',
|
||||
'test_string_stream_wchar_t.cpp',
|
||||
'test_string_u16.cpp',
|
||||
'test_string_u16_external_buffer.cpp',
|
||||
'test_string_u32.cpp',
|
||||
'test_string_u32_external_buffer.cpp',
|
||||
'test_string_u8.cpp',
|
||||
'test_string_u8_external_buffer.cpp',
|
||||
'test_string_utilities.cpp',
|
||||
'test_string_utilities_std.cpp',
|
||||
'test_string_utilities_std_u16.cpp',
|
||||
'test_string_utilities_std_u32.cpp',
|
||||
'test_string_utilities_std_u8.cpp',
|
||||
'test_string_utilities_std_wchar_t.cpp',
|
||||
'test_string_utilities_u16.cpp',
|
||||
'test_string_utilities_u32.cpp',
|
||||
'test_string_utilities_u8.cpp',
|
||||
'test_string_utilities_wchar_t.cpp',
|
||||
'test_string_view.cpp',
|
||||
'test_string_wchar_t.cpp',
|
||||
@ -246,17 +326,25 @@ etl_test_sources = files(
|
||||
'test_successor.cpp',
|
||||
'test_task_scheduler.cpp',
|
||||
'test_threshold.cpp',
|
||||
'test_to_arithmetic.cpp',
|
||||
'test_to_arithmetic_u16.cpp',
|
||||
'test_to_arithmetic_u32.cpp',
|
||||
'test_to_arithmetic_u8.cpp',
|
||||
'test_to_arithmetic_wchar_t.cpp',
|
||||
'test_to_string.cpp',
|
||||
'test_to_u8string.cpp',
|
||||
'test_to_u16string.cpp',
|
||||
'test_to_u32string.cpp',
|
||||
'test_to_u8string.cpp',
|
||||
'test_to_wstring.cpp',
|
||||
'test_tuple.cpp',
|
||||
'test_type_def.cpp',
|
||||
'test_type_list.cpp',
|
||||
'test_type_lookup.cpp',
|
||||
'test_type_select.cpp',
|
||||
'test_type_traits.cpp',
|
||||
'test_unaligned_type.cpp',
|
||||
'test_unaligned_type_constexpr.cpp',
|
||||
'test_unaligned_type_ext.cpp',
|
||||
'test_uncopyable.cpp',
|
||||
'test_unordered_map.cpp',
|
||||
'test_unordered_multimap.cpp',
|
||||
'test_unordered_multiset.cpp',
|
||||
@ -265,9 +353,9 @@ etl_test_sources = files(
|
||||
'test_utility.cpp',
|
||||
'test_variance.cpp',
|
||||
'test_variant_legacy.cpp',
|
||||
'test_variant_variadic.cpp',
|
||||
'test_variant_pool.cpp',
|
||||
'test_variant_pool_external_buffer.cpp',
|
||||
'test_variant_variadic.cpp',
|
||||
'test_vector.cpp',
|
||||
'test_vector_external_buffer.cpp',
|
||||
'test_vector_non_trivial.cpp',
|
||||
@ -280,24 +368,26 @@ etl_test_sources = files(
|
||||
|
||||
compile_args = [
|
||||
'-DENABLE_ETL_UNIT_TESTS',
|
||||
'-DETL_DEBUG',
|
||||
]
|
||||
link_args = []
|
||||
|
||||
if get_option('use_stl')
|
||||
compile_args += '-DETL_NO_STL=0'
|
||||
elif
|
||||
else
|
||||
compile_args += '-DETL_NO_STL=1'
|
||||
endif
|
||||
|
||||
if meson.get_compiler('cpp').get_argument_syntax() == 'gcc'
|
||||
compile_args += '-fsanitize=address,undefined'
|
||||
compile_args += '-fexceptions'
|
||||
compile_args += '-Wall'
|
||||
compile_args += '-Wextra'
|
||||
compile_args += '-Wextra'
|
||||
compile_args += '-Wno-non-virtual-dtor' #TODO remove and fix warning in code
|
||||
compile_args += '-Werror'
|
||||
link_args += '-fsanitize=address,undefined'
|
||||
|
||||
if get_option('enable_sanitizer')
|
||||
compile_args += '-fsanitize=address,undefined'
|
||||
link_args += '-fsanitize=address,undefined'
|
||||
endif
|
||||
endif
|
||||
|
||||
threads_dep = dependency('threads')
|
||||
|
||||
@ -58,7 +58,7 @@ for CXXSTD in 11 14 17 20 23 26; do
|
||||
-DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
|
||||
-DETL_OPTIMISATION=-O0 \
|
||||
-DETL_CXX_STANDARD=$CXXSTD \
|
||||
-DETL_ENABLE_SANITIZER=Off \
|
||||
-DETL_ENABLE_SANITIZER=OFF \
|
||||
-DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF \
|
||||
-DETL_USE_BUILTIN_MEM_FUNCTIONS=ON ..
|
||||
cmake --build .
|
||||
|
||||
@ -163,11 +163,11 @@ fi
|
||||
# Set the sanitizer enable. Default OFF
|
||||
#******************************************************************************
|
||||
if [ "$4" = "s" ]; then
|
||||
sanitize="On"
|
||||
sanitize="ON"
|
||||
elif [ "$4" = "n" ]; then
|
||||
sanitize="Off"
|
||||
sanitize="OFF"
|
||||
else
|
||||
sanitize="Off"
|
||||
sanitize="OFF"
|
||||
fi
|
||||
|
||||
#******************************************************************************
|
||||
|
||||
@ -3040,6 +3040,108 @@ namespace
|
||||
|
||||
CHECK_ARRAY_EQUAL(expected.data(), output.data(), expected.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_count_leading_zeros_signed_32)
|
||||
{
|
||||
// int32_t(-1) = 0xFFFFFFFF → 0 leading zeros
|
||||
CHECK_EQUAL(0, int(etl::count_leading_zeros(int32_t(-1))));
|
||||
|
||||
// int32_t(1) = 0x00000001 → 31 leading zeros
|
||||
CHECK_EQUAL(31, int(etl::count_leading_zeros(int32_t(1))));
|
||||
|
||||
// int32_t(0) = 0x00000000 → 32 leading zeros
|
||||
CHECK_EQUAL(32, int(etl::count_leading_zeros(int32_t(0))));
|
||||
|
||||
// int32_t(256) = 0x00000100 → 23 leading zeros
|
||||
CHECK_EQUAL(23, int(etl::count_leading_zeros(int32_t(256))));
|
||||
|
||||
// Verify against unsigned version
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
int32_t value = int32_t(1) << i;
|
||||
CHECK_EQUAL(int(etl::count_leading_zeros(uint32_t(value))), int(etl::count_leading_zeros(value)));
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_count_leading_zeros_signed_64)
|
||||
{
|
||||
CHECK_EQUAL(0, int(etl::count_leading_zeros(int64_t(-1))));
|
||||
CHECK_EQUAL(63, int(etl::count_leading_zeros(int64_t(1))));
|
||||
CHECK_EQUAL(64, int(etl::count_leading_zeros(int64_t(0))));
|
||||
|
||||
for (int i = 0; i < 64; ++i)
|
||||
{
|
||||
int64_t value = int64_t(1) << i;
|
||||
CHECK_EQUAL(int(etl::count_leading_zeros(uint64_t(value))), int(etl::count_leading_zeros(value)));
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_count_leading_zeros_64_specific_values)
|
||||
{
|
||||
// Value that specifically triggers the upper-32-bit mask path
|
||||
// Bit 35 set: 0x0000000800000000 → 28 leading zeros
|
||||
CHECK_EQUAL(28, int(etl::count_leading_zeros(uint64_t(0x0000000800000000ULL))));
|
||||
// Bit 31 set: 0x0000000080000000 → 32 leading zeros
|
||||
CHECK_EQUAL(32, int(etl::count_leading_zeros(uint64_t(0x0000000080000000ULL))));
|
||||
// All zeros in upper 32: 0x00000000FFFFFFFF → 32 leading zeros
|
||||
CHECK_EQUAL(32, int(etl::count_leading_zeros(uint64_t(0x00000000FFFFFFFFULL))));
|
||||
// Upper half has bit: 0x0000000100000000 → 31 leading zeros
|
||||
CHECK_EQUAL(31, int(etl::count_leading_zeros(uint64_t(0x0000000100000000ULL))));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_count_leading_ones_32_specific_values)
|
||||
{
|
||||
// 0xFFFF0000 → upper 16 bits set → exactly 16 leading ones
|
||||
CHECK_EQUAL(16, int(etl::count_leading_ones(uint32_t(0xFFFF0000UL))));
|
||||
// 0xFFFF8000 → 17 leading ones
|
||||
CHECK_EQUAL(17, int(etl::count_leading_ones(uint32_t(0xFFFF8000UL))));
|
||||
// 0xFFFFF000 → 20 leading ones
|
||||
CHECK_EQUAL(20, int(etl::count_leading_ones(uint32_t(0xFFFFF000UL))));
|
||||
// 0xFFFFFF00 → 24 leading ones
|
||||
CHECK_EQUAL(24, int(etl::count_leading_ones(uint32_t(0xFFFFFF00UL))));
|
||||
// 0xFFFFFFFE → 31 leading ones
|
||||
CHECK_EQUAL(31, int(etl::count_leading_ones(uint32_t(0xFFFFFFFEUL))));
|
||||
// 0xFFFFFFFF → 32 leading ones
|
||||
CHECK_EQUAL(32, int(etl::count_leading_ones(uint32_t(0xFFFFFFFFUL))));
|
||||
// 0x80000000 → 1 leading one
|
||||
CHECK_EQUAL(1, int(etl::count_leading_ones(uint32_t(0x80000000UL))));
|
||||
|
||||
// Verify against reference for boundary values
|
||||
for (uint32_t i = 0; i < 33; ++i)
|
||||
{
|
||||
// Create value with exactly 'i' leading ones
|
||||
uint32_t value = (i == 0) ? 0U : (i == 32) ? 0xFFFFFFFFUL : ~((1UL << (32U - i)) - 1UL);
|
||||
CHECK_EQUAL(int(test_leading_ones(value)), int(etl::count_leading_ones(value)));
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_count_leading_ones_64_specific_values)
|
||||
{
|
||||
// 0xFFFFFFFF00000000 → 32 leading ones
|
||||
CHECK_EQUAL(32, int(etl::count_leading_ones(uint64_t(0xFFFFFFFF00000000ULL))));
|
||||
// 0xFFFFFFFFFFFF0000 → 48 leading ones
|
||||
CHECK_EQUAL(48, int(etl::count_leading_ones(uint64_t(0xFFFFFFFFFFFF0000ULL))));
|
||||
// 0xFFFF000000000000 → 16 leading ones
|
||||
CHECK_EQUAL(16, int(etl::count_leading_ones(uint64_t(0xFFFF000000000000ULL))));
|
||||
// 0xFFFFFFFFFFFFFF00 → 56 leading ones
|
||||
CHECK_EQUAL(56, int(etl::count_leading_ones(uint64_t(0xFFFFFFFFFFFFFF00ULL))));
|
||||
// 0xFFFFFFFFFFFFFFFE → 63 leading ones
|
||||
CHECK_EQUAL(63, int(etl::count_leading_ones(uint64_t(0xFFFFFFFFFFFFFFFEULL))));
|
||||
// 0xFFFFFFFFFFFFFFFF → 64 leading ones
|
||||
CHECK_EQUAL(64, int(etl::count_leading_ones(uint64_t(0xFFFFFFFFFFFFFFFFULL))));
|
||||
|
||||
// Verify against reference for boundary values
|
||||
for (uint64_t i = 0; i < 65; ++i)
|
||||
{
|
||||
uint64_t value = (i == 0) ? 0ULL : (i == 64) ? 0xFFFFFFFFFFFFFFFFULL : ~((1ULL << (64ULL - i)) - 1ULL);
|
||||
CHECK_EQUAL(int(test_leading_ones(value)), int(etl::count_leading_ones(value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ namespace
|
||||
|
||||
for (size_t i = 0UL; i < sizeof(value_type); ++i)
|
||||
{
|
||||
uint8_t byte = static_cast<uint8_t>((static_cast<unsigned char>(value) >> (i * 8UL)) & 0xFFU);
|
||||
uint8_t byte = static_cast<uint8_t>((static_cast<unsigned int>(value) >> (i * 8U)) & 0xFFU);
|
||||
checksum = etl::rotate_right(checksum) + byte;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1072,5 +1072,30 @@ namespace
|
||||
|
||||
CHECK(!is_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_assignment_actually_moves)
|
||||
{
|
||||
DataM data;
|
||||
data.push(ItemM("A"));
|
||||
data.push(ItemM("B"));
|
||||
data.push(ItemM("C"));
|
||||
|
||||
DataM data2;
|
||||
data2 = std::move(data);
|
||||
|
||||
CHECK_EQUAL(3U, data2.size());
|
||||
|
||||
// If the move was correct, data2 should hold the moved-to values
|
||||
CHECK_EQUAL("A", data2[0].value);
|
||||
CHECK_EQUAL("B", data2[1].value);
|
||||
CHECK_EQUAL("C", data2[2].value);
|
||||
|
||||
// Original should be moved-from (empty strings with move-only type)
|
||||
for (size_t i = 0; i < data.size(); ++i)
|
||||
{
|
||||
CHECK(data[i].value.empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -2272,6 +2272,29 @@ namespace
|
||||
|
||||
CHECK(std::equal(blank_data.begin(), blank_data.end(), data.begin()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_const_iterator_subscript)
|
||||
{
|
||||
DataNDC data(initial_data.begin(), initial_data.end());
|
||||
|
||||
const DataNDC& cdata = data;
|
||||
|
||||
// Access via const_iterator operator[]
|
||||
DataNDC::const_iterator cit = cdata.begin();
|
||||
|
||||
// Verify operator[] returns values matching sequential access
|
||||
for (size_t i = 0; i < cdata.size(); ++i)
|
||||
{
|
||||
CHECK(cit[i] == cdata[i]);
|
||||
}
|
||||
|
||||
// Verify const_iterator operator[] returns const_reference
|
||||
// (This is a compile-time check - if the fix is reverted,
|
||||
// the type would be non-const reference which is incorrect for const_iterator)
|
||||
const NDC& ref = cit[0];
|
||||
CHECK(ref == cdata[0]);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -1616,5 +1616,26 @@ namespace
|
||||
Error result = exp.error_or(Error("default"));
|
||||
CHECK_EQUAL("real_error", result.e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_unexpected_error_const_rvalue_ref)
|
||||
{
|
||||
const etl::unexpected<Error> ue(Error("test_error"));
|
||||
|
||||
// Move from const rvalue — should get const Error&&
|
||||
const Error&& ref = std::move(ue).error();
|
||||
CHECK_EQUAL("test_error", ref.e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_transform_error_void_const_rvalue)
|
||||
{
|
||||
const etl::expected<void, Error> exp(etl::unexpected<Error>(Error("original")));
|
||||
|
||||
auto result = std::move(exp).transform_error([](const Error& e) { return Error(e.e + "_transformed"); });
|
||||
|
||||
CHECK_FALSE(result.has_value());
|
||||
CHECK_EQUAL("original_transformed", result.error().e);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -403,7 +403,9 @@ namespace
|
||||
|
||||
CHECK_EQUAL("data1", test_format(s, "{}", sv));
|
||||
CHECK_EQUAL("data1", test_format(s, "{:s}", sv));
|
||||
#if !ETL_USING_CPP20
|
||||
CHECK_THROW(test_format(s, "{:d}", sv), etl::bad_format_string_exception);
|
||||
#endif
|
||||
CHECK_EQUAL("data1 ", test_format(s, "{:10s}", sv));
|
||||
CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", sv));
|
||||
CHECK_EQUAL(" data1", test_format(s, "{:>10s}", sv));
|
||||
@ -432,7 +434,9 @@ namespace
|
||||
|
||||
CHECK_EQUAL("data1", test_format(s, "{}", s_arg));
|
||||
CHECK_EQUAL("data1", test_format(s, "{:s}", s_arg));
|
||||
#if !ETL_USING_CPP20
|
||||
CHECK_THROW(test_format(s, "{:d}", s_arg), etl::bad_format_string_exception);
|
||||
#endif
|
||||
CHECK_EQUAL("data1 ", test_format(s, "{:10s}", s_arg));
|
||||
CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", s_arg));
|
||||
CHECK_EQUAL(" data1", test_format(s, "{:>10s}", s_arg));
|
||||
@ -466,7 +470,9 @@ namespace
|
||||
|
||||
CHECK_EQUAL("data1", test_format(s, "{}", string_t(data)));
|
||||
CHECK_EQUAL("data1", test_format(s, "{:s}", string_t(data)));
|
||||
#if !ETL_USING_CPP20
|
||||
CHECK_THROW(test_format(s, "{:d}", string_t(data)), etl::bad_format_string_exception);
|
||||
#endif
|
||||
CHECK_EQUAL("data1 ", test_format(s, "{:10s}", string_t(data)));
|
||||
CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", string_t(data)));
|
||||
CHECK_EQUAL(" data1", test_format(s, "{:>10s}", string_t(data)));
|
||||
@ -495,7 +501,9 @@ namespace
|
||||
|
||||
CHECK_EQUAL("data1", test_format(s, "{}", chars));
|
||||
CHECK_EQUAL("data1", test_format(s, "{:s}", chars));
|
||||
#if !ETL_USING_CPP20
|
||||
CHECK_THROW(test_format(s, "{:d}", chars), etl::bad_format_string_exception);
|
||||
#endif
|
||||
CHECK_EQUAL("data1 ", test_format(s, "{:10s}", chars));
|
||||
CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", chars));
|
||||
CHECK_EQUAL(" data1", test_format(s, "{:>10s}", chars));
|
||||
@ -640,28 +648,28 @@ namespace
|
||||
{
|
||||
etl::string<100> s;
|
||||
|
||||
#if !ETL_USING_CPP20
|
||||
// These are caught at compile time in C++20 (consteval), so only test at runtime for pre-C++20
|
||||
CHECK_THROW(test_format(s, "a{b}", 1),
|
||||
etl::bad_format_string_exception); // bad format index spec
|
||||
// goal: rejected at compile time on C++20, error on <= C++17
|
||||
|
||||
CHECK_THROW(test_format(s, "a{b"),
|
||||
etl::bad_format_string_exception); // closing brace missing
|
||||
// goal: rejected at compile time on C++20, error on <= C++17
|
||||
|
||||
CHECK_THROW(test_format(s, "a{b}"),
|
||||
etl::bad_format_string_exception); // arg missing
|
||||
// goal: rejected at compile time on C++20, error on <= C++17
|
||||
|
||||
CHECK_THROW(test_format(s, "a}b"),
|
||||
etl::bad_format_string_exception); // bad format: only escaped
|
||||
// }} allowed
|
||||
// goal: rejected at compile time on C++20, error on <= C++17
|
||||
|
||||
CHECK_EQUAL("123", test_format(s, "{:}", 123)); // valid
|
||||
CHECK_THROW(test_format(s, "{::}", 123),
|
||||
etl::bad_format_string_exception); // bad format spec
|
||||
CHECK_THROW(test_format(s, "{1}", 123),
|
||||
etl::bad_format_string_exception); // bad index
|
||||
#endif
|
||||
|
||||
CHECK_EQUAL("123", test_format(s, "{:}", 123)); // valid
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -720,7 +728,9 @@ namespace
|
||||
CHECK_EQUAL(" 34 ", test_format(s, "{:^5}", 34));
|
||||
CHECK_EQUAL(" -65 ", test_format(s, "{:^5}", -65));
|
||||
CHECK_EQUAL("34 ", test_format(s, "{:<4}", 34));
|
||||
#if !ETL_USING_CPP20
|
||||
CHECK_THROW(test_format(s, "a{:*5}", 34), etl::bad_format_string_exception);
|
||||
#endif
|
||||
CHECK_EQUAL("a*34**", test_format(s, "a{:*^5}", 34));
|
||||
CHECK_EQUAL("a*34**", test_format(s, "a{:*^5}", static_cast<unsigned int>(34)));
|
||||
CHECK_EQUAL("a***-341234567890****", test_format(s, "a{:*^20}", static_cast<long long int>(-341234567890)));
|
||||
@ -773,7 +783,9 @@ namespace
|
||||
CHECK_EQUAL("00067", test_format(s, "{:05d}", 67));
|
||||
CHECK_EQUAL("+00067", test_format(s, "{:+05d}", 67));
|
||||
CHECK_EQUAL("+0X00EF1", test_format(s, "{:+#05X}", 0xEF1));
|
||||
#if !ETL_USING_CPP20
|
||||
CHECK_THROW(test_format(s, "{:+#05.5X}", 0xEF1), etl::bad_format_string_exception);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -1444,6 +1444,28 @@ namespace
|
||||
CHECK_EQUAL(ItemNDC("F"), *itr++);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_forward_list_exception_types)
|
||||
{
|
||||
// Verify exception class hierarchy is correct
|
||||
CHECK(true == (std::is_base_of<etl::exception, etl::forward_list_exception>::value));
|
||||
CHECK(true == (std::is_base_of<etl::forward_list_exception, etl::forward_list_full>::value));
|
||||
CHECK(true == (std::is_base_of<etl::forward_list_exception, etl::forward_list_empty>::value));
|
||||
CHECK(true == (std::is_base_of<etl::forward_list_exception, etl::forward_list_iterator>::value));
|
||||
|
||||
#if defined(ETL_VERBOSE_ERRORS)
|
||||
// When verbose errors are enabled, check the error text contains "forward_list"
|
||||
etl::forward_list_full ex_full(__FILE__, __LINE__);
|
||||
etl::forward_list_empty ex_empty(__FILE__, __LINE__);
|
||||
|
||||
std::string full_msg(ex_full.what());
|
||||
std::string empty_msg(ex_empty.what());
|
||||
|
||||
CHECK(full_msg.find("forward_list") != std::string::npos);
|
||||
CHECK(empty_msg.find("forward_list") != std::string::npos);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
} // namespace
|
||||
|
||||
@ -332,5 +332,59 @@ namespace
|
||||
isEqual = std::equal(output2.begin(), output2.end(), histogram.begin());
|
||||
CHECK(isEqual);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_sparse_histogram_iteration)
|
||||
{
|
||||
StringHistogram histogram;
|
||||
|
||||
// Empty histogram: begin == end
|
||||
CHECK(histogram.begin() == histogram.end());
|
||||
CHECK(histogram.cbegin() == histogram.cend());
|
||||
|
||||
// Add items
|
||||
histogram.add(std::string("apple"));
|
||||
histogram.add(std::string("banana"));
|
||||
histogram.add(std::string("apple"));
|
||||
|
||||
// Non-empty: begin != end
|
||||
CHECK(histogram.begin() != histogram.end());
|
||||
CHECK(histogram.cbegin() != histogram.cend());
|
||||
|
||||
// Count elements by iterating
|
||||
size_t count = 0;
|
||||
for (auto it = histogram.begin(); it != histogram.end(); ++it)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
CHECK_EQUAL(2U, count); // "apple" and "banana"
|
||||
|
||||
// Same with cbegin/cend
|
||||
count = 0;
|
||||
for (auto it = histogram.cbegin(); it != histogram.cend(); ++it)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
CHECK_EQUAL(2U, count);
|
||||
|
||||
// Verify we can find the expected values
|
||||
bool found_apple = false;
|
||||
bool found_banana = false;
|
||||
for (auto it = histogram.begin(); it != histogram.end(); ++it)
|
||||
{
|
||||
if (it->first == "apple")
|
||||
{
|
||||
CHECK_EQUAL(2, it->second);
|
||||
found_apple = true;
|
||||
}
|
||||
if (it->first == "banana")
|
||||
{
|
||||
CHECK_EQUAL(1, it->second);
|
||||
found_banana = true;
|
||||
}
|
||||
}
|
||||
CHECK(found_apple);
|
||||
CHECK(found_banana);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -1845,5 +1845,15 @@ namespace
|
||||
CHECK(c.etl_left == nullptr);
|
||||
CHECK(c.etl_right == nullptr);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_link_clear_range_bidirectional_nullptr)
|
||||
{
|
||||
// Passing nullptr should be a no-op, not a crash
|
||||
BData* null_ptr = nullptr;
|
||||
etl::link_clear_range<BLink0>(null_ptr);
|
||||
// If we get here without crashing, the test passes
|
||||
CHECK(true);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -2980,5 +2980,31 @@ namespace
|
||||
CHECK_EQUAL(0, relocatable_t::destructor_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_wipe_on_destruct)
|
||||
{
|
||||
struct Data : public etl::wipe_on_destruct<Data>
|
||||
{
|
||||
uint32_t d1;
|
||||
uint32_t d2;
|
||||
char d3;
|
||||
};
|
||||
|
||||
alignas(Data) unsigned char buffer[sizeof(Data)] = {0};
|
||||
|
||||
// Construct a Data object in the buffer with known non-zero values.
|
||||
Data* p = new (buffer) Data();
|
||||
p->d1 = 0x12345678UL;
|
||||
p->d2 = 0xAABBCCDDUL;
|
||||
p->d3 = char(0xEE);
|
||||
|
||||
// Destroy the object; wipe_on_destruct should zero the memory.
|
||||
p->~Data();
|
||||
|
||||
// Verify the memory occupied by the object has been cleared.
|
||||
unsigned char zeroes[sizeof(Data)] = {0};
|
||||
CHECK(memcmp(buffer, zeroes, sizeof(Data)) == 0);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -3384,6 +3384,42 @@ namespace
|
||||
CHECK(it == ev.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ranges_keys_view_alias)
|
||||
{
|
||||
std::vector<std::pair<int, double>> v = {{10, 1.1}, {20, 2.2}, {30, 3.3}};
|
||||
|
||||
using range_t = etl::ranges::views::all_t<decltype(v)&>;
|
||||
etl::ranges::keys_view<range_t> kv(etl::ranges::views::all(v));
|
||||
|
||||
auto it = kv.begin();
|
||||
CHECK_EQUAL(10, *it);
|
||||
++it;
|
||||
CHECK_EQUAL(20, *it);
|
||||
++it;
|
||||
CHECK_EQUAL(30, *it);
|
||||
++it;
|
||||
CHECK(it == kv.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ranges_values_view_alias)
|
||||
{
|
||||
std::vector<std::pair<int, double>> v = {{10, 1.1}, {20, 2.2}, {30, 3.3}};
|
||||
|
||||
using range_t = etl::ranges::views::all_t<decltype(v)&>;
|
||||
etl::ranges::values_view<range_t> vv(etl::ranges::views::all(v));
|
||||
|
||||
auto it = vv.begin();
|
||||
CHECK_CLOSE(1.1, *it, 0.001);
|
||||
++it;
|
||||
CHECK_CLOSE(2.2, *it, 0.001);
|
||||
++it;
|
||||
CHECK_CLOSE(3.3, *it, 0.001);
|
||||
++it;
|
||||
CHECK(it == vv.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ranges_views_keys)
|
||||
{
|
||||
|
||||
@ -5475,5 +5475,32 @@ namespace
|
||||
CHECK(text1 == sstream_view);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_find_char_pointer_n_shorter_than_strlen)
|
||||
{
|
||||
const value_t haystack_str[] = STR("Hello World");
|
||||
|
||||
TextSTD compare(haystack_str);
|
||||
TextL text(haystack_str);
|
||||
|
||||
// Haystack is "Hello World" (size 11).
|
||||
// search_str is "Worldly" (strlen 7).
|
||||
// We search for first 5 chars ("World") starting at pos=6.
|
||||
// Old code: (6 + 7 = 13) > 11 → premature npos (BUG)
|
||||
// Fixed: (6 + 5 = 11) <= 11 → proceeds to search → finds at 6
|
||||
const value_t search_str[] = STR("Worldly");
|
||||
|
||||
size_t pos_std = compare.find(search_str, 6, 5);
|
||||
size_t pos_etl = text.find(search_str, 6, 5);
|
||||
CHECK_EQUAL(6U, pos_std);
|
||||
CHECK_EQUAL(pos_std, pos_etl);
|
||||
|
||||
// pos=5 also triggers: (5 + 7 = 12) > 11 with old code
|
||||
pos_std = compare.find(search_str, 5, 5);
|
||||
pos_etl = text.find(search_str, 5, 5);
|
||||
CHECK_EQUAL(6U, pos_std);
|
||||
CHECK_EQUAL(pos_std, pos_etl);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -877,7 +877,7 @@ namespace
|
||||
CHECK(2U == view.rfind(s2, 5));
|
||||
CHECK(View::npos == view.rfind(s4));
|
||||
|
||||
CHECK(1U == view.rfind(s3, 5, 2));
|
||||
CHECK(5U == view.rfind(s3, 5, 2));
|
||||
CHECK(View::npos == view.rfind(s4, 0, 11));
|
||||
}
|
||||
|
||||
@ -1183,5 +1183,40 @@ namespace
|
||||
CHECK_TRUE(u32view == u32sstream_view);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_rfind_boundary_positions)
|
||||
{
|
||||
etl::string_view sv("abcabc");
|
||||
|
||||
// rfind "abc" with position=3: should find the second "abc" at position 3
|
||||
size_t pos = sv.rfind(etl::string_view("abc"), 3);
|
||||
CHECK_EQUAL(3U, pos);
|
||||
|
||||
// rfind "abc" with position=2: should find only the first "abc" at position 0
|
||||
pos = sv.rfind(etl::string_view("abc"), 2);
|
||||
CHECK_EQUAL(0U, pos);
|
||||
|
||||
// rfind "abc" with position=0: should find at position 0
|
||||
pos = sv.rfind(etl::string_view("abc"), 0);
|
||||
CHECK_EQUAL(0U, pos);
|
||||
|
||||
// rfind with npos (search entire string)
|
||||
pos = sv.rfind(etl::string_view("abc"));
|
||||
CHECK_EQUAL(3U, pos);
|
||||
|
||||
// rfind something not found
|
||||
pos = sv.rfind(etl::string_view("xyz"));
|
||||
CHECK_EQUAL(etl::string_view::npos, pos);
|
||||
|
||||
// Compare with std::string to verify exact behavior
|
||||
std::string std_sv("abcabc");
|
||||
for (size_t p = 0; p <= std_sv.size(); ++p)
|
||||
{
|
||||
size_t std_pos = std_sv.rfind("abc", p);
|
||||
size_t etl_pos = sv.rfind(etl::string_view("abc"), p);
|
||||
CHECK_EQUAL(std_pos, etl_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -2247,6 +2247,25 @@ namespace
|
||||
CHECK_FALSE((etl::is_object_v<int&>));
|
||||
CHECK_FALSE((etl::is_object_v<int&&>));
|
||||
CHECK_FALSE((etl::is_object_v<decltype(f)>));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_is_signed_unsigned_char_types)
|
||||
{
|
||||
#if ETL_HAS_NATIVE_CHAR8_T
|
||||
CHECK_FALSE(etl::is_signed<char8_t>::value);
|
||||
CHECK_TRUE(etl::is_unsigned<char8_t>::value);
|
||||
#endif
|
||||
|
||||
#if ETL_HAS_NATIVE_CHAR16_T
|
||||
CHECK_FALSE(etl::is_signed<char16_t>::value);
|
||||
CHECK_TRUE(etl::is_unsigned<char16_t>::value);
|
||||
#endif
|
||||
|
||||
#if ETL_HAS_NATIVE_CHAR32_T
|
||||
CHECK_FALSE(etl::is_signed<char32_t>::value);
|
||||
CHECK_TRUE(etl::is_unsigned<char32_t>::value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1047,5 +1047,51 @@ namespace
|
||||
CHECK_EQUAL(expect1c, result1g);
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_pair_equality_uses_equality_operator)
|
||||
{
|
||||
// Basic equality
|
||||
etl::pair<int, int> p1(1, 2);
|
||||
etl::pair<int, int> p2(1, 2);
|
||||
etl::pair<int, int> p3(1, 3);
|
||||
etl::pair<int, int> p4(2, 2);
|
||||
|
||||
CHECK_TRUE(p1 == p2);
|
||||
CHECK_FALSE(p1 == p3); // different second
|
||||
CHECK_FALSE(p1 == p4); // different first
|
||||
|
||||
// Custom type where operator== and operator< can disagree
|
||||
// The old code used !(a<b) && !(a>b), which is NOT equivalent to a==b
|
||||
// for types that don't define a total order consistent with equality.
|
||||
struct WeirdType
|
||||
{
|
||||
int value;
|
||||
bool equal_flag;
|
||||
|
||||
bool operator==(const WeirdType& other) const
|
||||
{
|
||||
return equal_flag && other.equal_flag;
|
||||
}
|
||||
bool operator<(const WeirdType& other) const
|
||||
{
|
||||
return value < other.value;
|
||||
}
|
||||
bool operator>(const WeirdType& other) const
|
||||
{
|
||||
return value > other.value;
|
||||
}
|
||||
};
|
||||
|
||||
WeirdType w1{1, false};
|
||||
WeirdType w2{1, false}; // same value, but equal_flag is false
|
||||
|
||||
// With proper ==: w1 == w2 should be false (both equal_flags are false)
|
||||
// With old !(w1<w2)&&!(w1>w2): would be true (same value)
|
||||
etl::pair<int, WeirdType> pw1(0, w1);
|
||||
etl::pair<int, WeirdType> pw2(0, w2);
|
||||
|
||||
CHECK_FALSE(pw1 == pw2); // This would FAIL with the old < > based comparison
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -3541,6 +3541,7 @@
|
||||
<ClInclude Include="..\..\include\etl\crc8_wcdma.h" />
|
||||
<ClInclude Include="..\..\include\etl\delegate_observable.h" />
|
||||
<ClInclude Include="..\..\include\etl\expected.h" />
|
||||
<ClInclude Include="..\..\include\etl\format.h" />
|
||||
<ClInclude Include="..\..\include\etl\function_traits.h" />
|
||||
<ClInclude Include="..\..\include\etl\gcd.h" />
|
||||
<ClInclude Include="..\..\include\etl\generators\fsm_cpp03_generator.h" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user